简体   繁体   中英

Why is object pooling not regenerating destroyed objects?

So I've been reading about object pooling in the past few days, trying to understand how it works. Well, I think I mostly understand now, but coding is my huge weakness... The game is which pooling is needed for is a simple endless ZigZag type-ish game, where platforms are generated as the player moves forward. I wrote a code in hope that it will work, but it doesn't. I set that 20 platforms are getting generated, which works, but they do not disable and re-enable in front of the player.

I attach a picture for the better understanding Here is the code:

public class ObjectPooler : MonoBehaviour
{
    public static ObjectPooler current;
    public GameObject pooledObject;
    public int pooledAmount;
    private List<GameObject> pooledObjects;

    private void Awake()
    {
        current = this;
    }

    void Start()
    {
        //current = this;
        pooledObjects = new List<GameObject>();
        for (int i = 0; i < pooledAmount; i++)
        {
            GameObject obj = Instantiate(pooledObject);
            obj.SetActive(false);
            pooledObjects.Add(obj);
        }
    }

    public GameObject GetPooledObject()
    {
        for (int i = 0; i < pooledObjects.Count; i++)
        {
            if (!pooledObjects[i].activeInHierarchy)
            {
                return pooledObjects[i];
            }
        }

        return null;
    }
}

The script which is responsible for the platform generation:

public class PlatformSpawner : MonoBehaviour
{
    public GameObject platform;
    public Transform lastPlatform;
    SpawnPoint _spawn;
    bool stop;

    [System.Serializable]
    public struct SpawnPoint
    {
        public Vector3 position;
        public Quaternion orientation;

        public void Step(float distance)
        {
            if (Random.value < 0.5)
            {
                position.x += distance;
                orientation = Quaternion.Euler(0, 90, 0);
            }
            else
            {
                position.z += distance;
                orientation = Quaternion.Euler(0, 0, 0);
            }
        }
    }

    private void OnEnable()
    {
        Invoke("Disable", 1f);
    }

    void Start()
    {
        _spawn.position = lastPlatform.position;
        _spawn.orientation = transform.rotation;
        
        StartCoroutine(SpawnPlatforms());
    }

    IEnumerator SpawnPlatforms()
    {
        while (!stop)
        {
            GameObject obj = ObjectPooler.current.GetPooledObject();
            if (obj == null) yield break; //return
            obj.transform.position = lastPlatform.position;
            obj.transform.rotation = lastPlatform.rotation;
            obj.SetActive(true);

            _spawn.Step(1.5f);

            var newPlatform = Instantiate(platform, _spawn.position, _spawn.orientation);

            yield return new WaitForSeconds(0.1f);
        }
    }

    void Disable()
    {
        gameObject.SetActive(false);
    }

    private void OnDisable()
    {
        CancelInvoke();
    }
}

I know it's a bit too long, but it helps to see through everything. Can someone tell me what exactly do I have to change, delete or do? Every answer is highly appreciated!

Simple solution: use existing solution, for example, SimplePool .

Or you can get simple pool, examine, how it works, and then create your own implementation.

Difficult, but interesting solution: make your code work. Here are the steps:

  1. Make your game work well without pooling. Just to be sure, you don't have any issues with gameplay itself.

  2. Implement your pool. The most important thing in object pooling: it's just a replace for default Instantiate (and, maybe, Destroy). So, your gameplay code should know nothing about pooling itself - it only requests: "create an instance of this object here" - that's all. Ok, maybe, "bring this object back to pool". But no "null" can be returned, no additional logic to handle cases.

  3. In your ObjectPooler code, you are search for free (disabled) object in array, and return it, when it found. But what happened, when all the objects are in use? How the objects, that not needed any more, will get back to pool for future reuse? So, there are the things that pool should handle:

  • search for free object, and return, if found (done);
  • if no free object found, instantiate a new one;
  • bring unused objects back to pool.

The last point can be implemented in various ways. In SimplePool, you need to call Despawn() manually, when your object is not needed any more (passed out of screen). Its good approach, especially for plugin - enables user to implement any custom logic for it. But you can implement auto-despawn for every pooled object after some time delay, or create the coroutine like [wait for OnBecameVisible -> wait for OnBecameInvisible -> Despawn], or something else - it's up to you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM