画面上に表示したオブジェクトを再利用する
以前公開したこちらのゲームで、工夫した点について書き残しておこうと思い立ったので、備忘録的に。
工夫した点は
・画面上に一度表示したオブジェクトを再利用する
と、いう点です。
上のゲームでは空からウニが落ちてくるのですが、
よくあるパターンとしては
ウニ落ちてくる -> 床かユニティちゃんに当たる -> オブジェクト消して再生成
かと思いますが、そういう感じだと削除と生成のオーバーヘッドが発生するんじゃないかと思って、「オブジェクト再利用(?)すればオーバーヘッドないし、メモリ使用量も変わらないんじゃないか?」と思って、
床かユニティちゃんに当たった瞬間に位置を初期の場所に移動させる
というスクリプトをあてました。
実際には以下のようなスクリプトをあてています。
using UnityEngine;
using System.Collections;
public class uni : MonoBehaviour {
private State state = State.Normal;
private GameMaster gm;
void Start()
{
gm = GameObject.Find("Root").GetComponent<GameMaster>();
}
void Update()
{
if(state == State.Inited)
{
state = State.Normal;
gameObject.rigidbody2D.isKinematic = false;
}
}
void OnTriggerEnter2D(Collider2D obj)
{
if (obj.name == "Ground" )
{
float f = Random.value * 8;
if (Random.value > 0.5f)
{
f = f * -1.0f;
}
gameObject.transform.position = new Vector3(f,6.0f,gameObject.transform.position.z);
gameObject.rigidbody2D.isKinematic = true;
state = State.Inited;
}
else if(obj.name == "UnityChan2D")
{
gm.substructLifeCount();
}
}
enum State
{
Normal,
Inited
}
}
using System.Collections;
public class uni : MonoBehaviour {
private State state = State.Normal;
private GameMaster gm;
void Start()
{
gm = GameObject.Find("Root").GetComponent<GameMaster>();
}
void Update()
{
if(state == State.Inited)
{
state = State.Normal;
gameObject.rigidbody2D.isKinematic = false;
}
}
void OnTriggerEnter2D(Collider2D obj)
{
if (obj.name == "Ground" )
{
float f = Random.value * 8;
if (Random.value > 0.5f)
{
f = f * -1.0f;
}
gameObject.transform.position = new Vector3(f,6.0f,gameObject.transform.position.z);
gameObject.rigidbody2D.isKinematic = true;
state = State.Inited;
}
else if(obj.name == "UnityChan2D")
{
gm.substructLifeCount();
}
}
enum State
{
Normal,
Inited
}
}
初期位置(y)を決めておく必要があります。
xはRandomで適当な数字とってきて、そこから実際に配置する場所を毎回変えてあげています。
今回貼付けたウニの動きに関して言うと、単純に位置を上に戻すだけだと、働いている慣性力が消えないため、ゲーム開始と同時にウニの落下速度が際限なく増えていってしまいます。
そのため位置を初期位置に戻すタイミングで一旦isKinematicを有効にしてあげることで、働いていた慣性力をゼロに戻してあげています。
そのあとisKinematicをfalseに戻してあげれば、再度重力がかかって、ちょどいい(?)速度で降ってくるようになります。
こうしてあげると、オブジェクトを毎回削除 -> 生成する必要はなくなり、決められたオブジェクトのみを使い回すことができます。
今回私が作成したような、生成にそれほど時間のかからないオブジェクトであればこういった工夫は必要ないかもしれませんが、生成時に負荷がかかるオブジェクトを削除 -> 生成して使用している場合は、使い回すということも選択肢にいれてあげると、もしかしたらゲームの処理速度なんかがはやくなるかもしれませんね。
注意点としましては、使い回す必要のあるオブジェクトを最初の段階ですべて生成しておかないといけないため、初回表示の際の負荷があがる、ということでしょうか。
ただ、最初のタイミングが時間かかるか、プレイ中に負荷がかかってもっさりしちゃうか、どちらをとるかといえば私は前者だと思うので、このやり方が使える場面では、使っていこうと思います。