簡體   English   中英

Unity3D:如何在沒有生成器的情況下進行 object 池化 singleton

[英]Unity3D: How to do object pooling without a spawner singleton

通常,如果你使用 object 池,你會像視頻中那樣制作 singleton。 看完這個視頻,我才發現singleton到底有多亂。 有沒有其他方法可以在不使用單例的情況下進行 object 池化? 我想改為使用事件。

您需要將池保存在 class 而不是 singleton 中,並根據您的事件處理您的游戲對象池。 關於用事件調用它們,“我想用事件”不是一個很具體的問題。 您需要將事件設置為偵聽(方法訂閱)並在代碼中應發生的任何地方調用它們,這就是調用方法。 我建議,如果您不清楚這一點,請嘗試使用統一事件( Update中的 OnTriggerEnter、 if(Input.GetMouseButtonDown(0))等),直到您深入了解主題以了解它們並制作自己的事件需要時使用 c# 事件或UnityEvents

找到兩個模板腳本、一個池和事件處理程序來處理場景中的對象。 您可以在一個空場景中檢查它們,並附加兩個要附加的游戲對象,以及池中您想要的 object,分別按“空格”和“A”從池中創建並返回到池中。

泳池經理:

using System.Collections.Generic;
using UnityEngine;

public class PoolManager : MonoBehaviour
{
    private Queue<GameObject> objPool;
    private Queue<GameObject> activeObj;
    private int poolSize = 10;
    public GameObject objPrefab;

    void Start()
    {
        //queues init
        objPool = new Queue<GameObject>();  
        activeObj = new Queue<GameObject>();
        //pool init
        for (int i = 0; i < poolSize; i++) 
        {
            GameObject newObj = Instantiate(objPrefab);
            objPool.Enqueue(newObj);   
            newObj.SetActive(false);    
        }
    }

    public GameObject GetRandomActiveGO() {
        GameObject lastActive = default;
        if (activeObj.Count > 0)
            lastActive = activeObj.Dequeue();
        else {
            Debug.LogError("Active object queue is empty");
        }
        return lastActive;
    }

    //get from pool
    public GameObject GetObjFromPool(Vector3 newPosition, Quaternion newRotation)
    {
        GameObject newObject = objPool.Dequeue();
        newObject.SetActive(true);
        newObject.transform.SetPositionAndRotation(newPosition, newRotation);

        //keep actives to be retrieved
        activeObj.Enqueue(newObject);
        return newObject;
    }

    //return to pool
    public void ReturnObjToPool(GameObject go)
    {
        go.SetActive(false);
        objPool.Enqueue(go);
    }
}

事件處理程序:

using UnityEngine;

public class EventHandler : MonoBehaviour
{
    public delegate GameObject OnSpacePressed(Vector3 newPosition, Quaternion newRotation);
    public OnSpacePressed onSpacePressed;

    public delegate void OnAKeyPressed(GameObject go);
    public OnAKeyPressed onAKeyPressed;

    public PoolManager poolManager;

    void Start()
    {
        onSpacePressed = poolManager.GetObjFromPool;
        onAKeyPressed = poolManager.ReturnObjToPool;
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            onSpacePressed?.Invoke(new Vector3(0, 0, 0), Quaternion.identity);
        }

        //here I get a random active, however this would be called in the specific objects remove circumstances, 
        //so you should have a reference to that specific gameobje when rerunrning it to the pool.
        if (Input.GetKeyDown(KeyCode.A))
        { 
            GameObject go = poolManager.GetRandomActiveGO();
            onAKeyPressed?.Invoke(go);
        }
    }
}

編輯:Singleton 模式

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    protected static T _instance;
    public static T instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = GameObject.FindObjectOfType<T>();
                if (_instance == null)
                {
                    _instance = new GameObject(typeof(T).Name).AddComponent<T>();
                }

            }
            return _instance;
        }
    }
}

暫無
暫無

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

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