Unity3D:如何做对象池没有产卵单一



通常,如果你使用对象池,你会像这个视频中那样创建一个单例。看完这个视频后,我发现单例模式有多混乱。有没有其他的方法来做对象池不使用单例?我想使用Events

你需要将池保存在一个非单例类中,并根据你的事件处理你的游戏对象池。关于用事件调用它们,"我想用事件"。这不是一个非常具体的问题。您需要将事件设置为监听(方法订阅),并在它们应该发生的地方在代码中调用它们,这是调用方法。我建议,如果你不清楚这一点,尝试使用统一事件(OnTriggerEnter, Update中的if(Input.GetMouseButtonDown(0))等),直到你深入了解主题,足以理解它们,并在需要时使用c#事件或UnityEvents制作自己的事件。

找到两个模板脚本,一个池和一个事件处理程序来处理场景中的对象。你可以在一个空的场景中用你各自的两个gameObject附加,和你想要的对象在池中,按'space'和'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);
        }
    }
}

编辑:单例模式

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

相关内容

  • 没有找到相关文章

最新更新