Re: note

技術的な知見やポエムなど役に立たない情報を書き連ねる場所

UniRxのObjectPoolを使う

f:id:hik0leaf:20190608131621j:plain UniRxのObjectPoolについては下記のサイトで詳しく解説されています。

qiita.com

ここでは、上記のサイトを参考にして最小構成でUniRxのObjectPoolを使ってみたいと思います。 今回解説するコードは以下のリポジトリから取得できます。
Unity Version: 2018.4.0f1

github.com

1. UniRxのインポート

新規プロジェクトを作成したらAsset StoreからUniRxをインポートします。

2. Cubeの作成

[Create] > [3D Object] > [Cube]からCubeを作成します。

3. CubeScriptの作成

以下のスクリプトを作成して先程作成したCubeにアタッチします。 Cubeが生成されると自動回転して2秒後に自分自身を消すための通知を行います。

using UnityEngine;
using UniRx;
using System;

public class CubeScript : MonoBehaviour
{
    void Update()
    {
        transform.Rotate(new Vector3(0, 0, 5));
    }

    public IObservable<long> Generate(Vector3 position)
    {
        transform.position = position;
        
        return Observable.Timer(TimeSpan.FromSeconds(2.0f));
    }
}

4. CubeのPrefab化

作成したCubeをHierarchyからProjectに移動してCubeをPrefab化します。Prefab化が済んだらCubeは削除して構いせません。

5. CubePoolの作成

生成されるCubeをPoolするためのスクリプトを作成します。

using UnityEngine;
using UniRx.Toolkit;

public class CubePool : ObjectPool<CubeScript>
{
    private readonly CubeScript prefab;

    public CubePool(CubeScript prefab)
    {
        this.prefab = prefab;
    }

    protected override CubeScript CreateInstance()
    {
        return GameObject.Instantiate(prefab);
    }
}

6. MainScriptの作成

CubeをObjectPoolから生成するためスクリプトを作成します。名前は何でも構いせません。今回はわかりやすいようにGUIボタンにアタッチしてクリックされたらCubeの生成を行うようにしています。

using UnityEngine;
using UniRx;
using UniRx.Triggers;

public class MainScript : MonoBehaviour
{
    [SerializeField] private CubeScript cubePrefab;
    private CubePool cubePool;

    public void OnClick()
    {
        var position = new Vector3(Random.Range(-50f, 50f), Random.Range(-50f, 50f), transform.position.z);

        var cube = cubePool.Rent();

        cube.Generate(position)
            .Subscribe(_ => cubePool.Return(cube))
            .AddTo(this);
    }

    void Start()
    {
        cubePool = new CubePool(cubePrefab);

        this.OnDestroyAsObservable()
            .Subscribe(_ => {
                Debug.Log("dipose");
                cubePool.Dispose();
            }).AddTo(this);
    }
}

cubePool.Return(cube)3. で作成したコードから通知を受け取ったときにCubeをObjectPoolに元に戻しています。

7. 実行

実行してボタンをクリックするとCubeが生成され回転しながら2秒後に消えます。Hierarchyをみると生成のたびにCubeがCloneされますが、ObjectPool内で賄える分についてはオブジェクトが再利用されていることが分かります。

実行の様子は以下の動画をご覧ください。