Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

[Unity] 2秒でオブジェクトプールしたい君へ [Lean Pool]

More than 1 year has passed since last update.

謝罪

2秒ではできません、ごめんなさい。

オブジェクトプールしたい

弾幕ゲーで弾Instantiateしてたら大変なことになったので、オブジェクトプールしたくなった。
簡単なオブジェクトプールくらいなら自分で書いてもそんなに時間はかからない気がするが、書きたくないのでアセットに頼りたい。

地獄。
image.png

Lean Pool を使って楽しよう

image.png
現在無料で一番人気のオブジェクトプールアセットである。

使いかた

ダウンロードしてインポートする。
プールしたいオブジェクトのInstantiateとDestroyを置換する。

Instantiate(poolShitaiObject); -> Lean.Pool.LeanPool.Spawn(poolShitaiObject);
Destroy(poolShitaiObject); -> Lean.Pool.LeanPool.Despawn(poolShitaiObject);

これだけでプールされるが、もう少しやることはある。

初期化

同じオブジェクトを使いまわす以上、以下のような普段やってる初期化は当てにならない。
AwakeとStartが都度呼ばれないのだ。

class Ahan : MonoBehaviour {
    public Ahahan ahahan;
    // 何もしてないので、再利用されるとき、値が引き継がれてしまう。
    public int ahanCount = 0;
    public int ahanAhanCount;

    private void Start() {
        ahahan = GetComponent<Ahahan>();
        // Startは一度は呼ばれるが、再利用時には呼び出されないので、値が引き継がれてしまう。
        ahanAhanCount = 10;
    }

    private void Update() {
        ahanCount++;
        ahanAhanCount++;
    }
}

変更される可能性のある値は全てOnEnableの中で初期化すべし。

class Ahan : MonoBehaviour {
    public Ahahan ahahan;
    public int ahanCount;
    public int ahanAhanCount;

    private void Start() {
        // 変化しない値はStartのままでいい。
        // 重たくない処理の場合は脳死で全部OnEnableにおいてもええで
        ahahan = GetComponent<Ahahan>();
    }

    // Spawn時に毎回呼び出されるため、値がリセットされる。
    private void OnEnable() {
        ahanCount = 0;
        ahanAhanCount = 10;
    }

    private void Update() {
        ahanCount++;
        ahanAhanCount++;
    }
}

OnEnableはStartの完全な代替にはなれない

なぜならStartはInstantiateされた次のフレームに実行されるが、OnEnableはSpawnされた時点で実行されるからだ。
どういうことかというと、
Instantiate -> 変数にいろいろ代入 -> 次のフレームにStartが実行されて、代入された値をもとに準備ができる
がStartは出来るのに対して、OnEnableは、
Spawn -> OnEnableがその瞬間実行される -> 変数にいろいろ代入 -> OnEnableはもう実行済みのため、次のフレームでは実行されず、値が反映されない
という感じになる。
普通に使っている分には脳死でStart -> OnEnableで問題ないはず。

プールサイズを設定する

ただInstantiateとDestroyを置き換えただけでも高速化はされる。
しかしプールサイズが設定されていないため、弾が増える最初のタイミングはやはり重い。

こんな感じ。
image.png

最初から使いまわす用のインスタンスを用意しておくと、このコストもなくなる。
プールオブジェクトを作る。
image.png

image.png
Prefabのところに弾のPrefabを置いて、Preloadに用意したい弾の数を入れる(適当に1000)。

こうなった。
image.png

比較してみる

Before
image.png
After
image.png

これで君もニッコリ

やったね!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away