簡體   English   中英

為什么 object 池不重新生成被破壞的對象?

[英]Why is object pooling not regenerating destroyed objects?

因此,過去幾天我一直在閱讀有關 object 池化的信息,試圖了解它是如何工作的。 好吧,我想我現在基本明白了,但編碼是我的巨大弱點......需要池的游戲是一個簡單的無盡之字折線類型的游戲,隨着玩家前進,平台會生成。 我寫了一個代碼,希望它能工作,但它沒有。 我設置了 20 個平台正在生成,這是可行的,但它們不會在播放器面前禁用和重新啟用。

我附上一張圖片以便更好地理解這是代碼:

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;
    }
}

負責平台生成的腳本:

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();
    }
}

我知道它有點太長了,但它有助於看透一切。 有人可以告訴我我到底需要更改、刪除或做什么嗎? 每一個答案都非常感謝!

簡單解決方案:使用現有解決方案,例如SimplePool

或者你可以得到簡單的池,檢查它是如何工作的,然后創建你自己的實現。

困難但有趣的解決方案:讓你的代碼工作。 以下是步驟:

  1. 讓您的游戲在沒有池的情況下運行良好。 可以肯定的是,您對游戲玩法本身沒有任何問題。

  2. 實施您的游泳池。 object 池中最重要的事情:它只是默認實例化(也許還有銷毀)的替代品。 所以,你的游戲代碼應該對池本身一無所知——它只要求:“在這里創建這個 object 的實例”——就是這樣。 好吧,也許,“把這個 object 帶回池中”。 但是不能返回“null”,也沒有額外的邏輯來處理案例。

  3. 在您的 ObjectPooler 代碼中,您在數組中搜索免費(禁用)object,並在找到時返回它。 但是,當所有對象都在使用時,發生了什么? 不再需要的對象如何回到池中以供將來重用? 所以,池應該處理的事情是:

  • 搜索免費的 object,如果找到則返回(完成);
  • 如果沒有找到可用的 object,則實例化一個新的;
  • 將未使用的對象帶回池中。

最后一點可以通過多種方式實現。 在 SimplePool 中,您需要手動調用 Despawn(),當您的 object 不再需要(通過屏幕)。 它的好方法,特別是對於插件 - 使用戶能夠為其實現任何自定義邏輯。 但是您可以在一段時間延遲后為每個池化的 object 實現自動消失,或者創建協程,例如 [等待 OnBecameVisible -> 等待 OnBecameInvisible -> Despawn] 或其他 - 這取決於您。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM