Perl日記

PerlとかRubyとかPHPとかPythonとか

MLAPI その9

非推奨となった UNet のやつを参考に、オブジェクトプールをやってみる。

docs.unity3d.com
mlapi.network
mlapi.network



シーン内に SpawnManager オブジェクトを作ってスクリプトをアタッチ。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SpawnManager : MonoBehaviour
{
    public GameObject bullet;
    private GameObject[] bulletPool;
    private int poolSize = 5;

    void Start()
    {
        bulletPool = new GameObject[poolSize];
        for (int i = 0; i < poolSize; i++)
        {
            bulletPool[i] = (GameObject)Instantiate(bullet, Vector3.zero, Quaternion.identity);
            bulletPool[i].name = "PoolObject" + i;
            bulletPool[i].SetActive(false);
        }

        MLAPI.Spawning.SpawnManager.RegisterSpawnHandler(MLAPI.Spawning.SpawnManager.GetPrefabHashFromIndex(1), SpawnObject);
        MLAPI.Spawning.SpawnManager.RegisterCustomDestroyHandler(MLAPI.Spawning.SpawnManager.GetPrefabHashFromIndex(1), UnSpawnObject);
    }

    public GameObject GetFromPool(Vector3 position, Quaternion rotation)
    {
        for (int i = 0; i < poolSize; i++)
        {
            if (!bulletPool[i].activeSelf)
            {
                Debug.Log("Activating GameObject " + bulletPool[i].name + " at " + position);
                bulletPool[i].transform.position = position;
                bulletPool[i].transform.rotation = rotation;
                bulletPool[i].SetActive(true);
                return bulletPool[i];
            }
        }
        Debug.LogError("Could not grab GameObject from pool, nothing available");
        return null;
    }

    public MLAPI.NetworkedObject SpawnObject(Vector3 position, Quaternion rotation)
    {
        return GetFromPool(position, rotation).GetComponent<MLAPI.NetworkedObject>();
    }

    public void UnSpawnObject(MLAPI.NetworkedObject networkedObject)
    {
        Debug.Log("Re-pooling GameObject " + networkedObject.gameObject.name);
        networkedObject.gameObject.SetActive(false);
    }
}

PlayerCubeController の方で、SpawnManager 経由で弾を呼び出すように変更。

public class PlayerCubeController : MLAPI.NetworkedBehaviour
{
    private SpawnManager spawnManager;
    private void Start()
    {
        spawnManager = GameObject.Find("SpawnManager").GetComponent<SpawnManager>();
    }

    [MLAPI.Messaging.ServerRPC]
    private void Shoot()
    {
        GameObject bullet = spawnManager.GetFromPool(new Vector3(Random.Range(-9, 9), 1.0f, Random.Range(-9, 9)), Quaternion.Euler(0, 0, 90));
        bullet.GetComponent<MLAPI.NetworkedObject>().Spawn();
        StartCoroutine(BackToPool(bullet, 2.0f));
    }

    private IEnumerator BackToPool(GameObject bullet, float timer)
    {
        yield return new WaitForSeconds(timer);
        MLAPI.NetworkedObject no = bullet.GetComponent<MLAPI.NetworkedObject>();
        spawnManager.UnSpawnObject(no);
        no.UnSpawn();
    }
}

弾が自動的に消えないようにコメントアウト

public class Bullet : MonoBehaviour
{
    void Update()
    {
        //restTime -= Time.deltaTime;
        //if (restTime < 0)
        //{
        //    Destroy(this.gameObject);
        //}
    }
}

いまひとつ理解ができていない……。
これだとクライアントが複数つながっても、シーン内に弾が 5 発しか存在できない。
なかなか難しかった。