unity3d PoolManager和Destroy函数中哪一个更快?

whlutmcx  于 2022-12-13  发布在  其他
关注(0)|答案(1)|浏览(129)

我发现poolManager可以让游戏变得更有趣。我发现它很吸引人,所以我做了自己的PoolManager。仔细研究一下,它似乎比Destroy函数更复杂。用这种方法管理PoolManager,使用Destroy()而不是删除示例,难道不是更实用吗?
我想做一个更好的PollManager。

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

public class PoolManager : MonoBehaviour
{
    [SerializeField]
    GameObject containerPrefab;

    [SerializeField]
    PoolProfile[] new1Profile;

    static PoolProfile[] newProfile;

    private void Awake()
    {
        newProfile = new PoolProfile[new1Profile.Length];

        for(int i = 0; i<new1Profile.Length; i++)
        {
            newProfile[i] = new1Profile[i];
        }
        Init();
    }

    public void Init()
    {
        for (int i = 0; i < newProfile.Length; i++)
        {
            GameObject newContainer = Instantiate(containerPrefab);
            newContainer.name = newProfile[i].name;
            newProfile[i].container = newContainer;
            for (int j = 0; j < newProfile[i].defalutAmount; j++)
            {
                GameObject prefab = Instantiate(newProfile[i].prefabSet, newContainer.transform);
                prefab.transform.position = newProfile[i].defalutVector;
                prefab.transform.parent = newContainer.transform;
                prefab.SetActive(false);
                newProfile[i].inConObject.Enqueue(prefab);
            }
        }
    }

    public static void AddAmount(Queue<GameObject> set, GameObject addObject)
    {
        set.Enqueue(Instantiate(addObject));
    }

    public static GameObject PoolRequest(Queue<GameObject> set,GameObject pullObject, Vector3 pos, Quaternion rot)
    {
        if(set.Count == 0)
        {
            AddAmount(set, pullObject);
        }
        set.Peek().SetActive(true);
        set.Peek().transform.position = pos;
        set.Peek().transform.rotation = rot;

        GameObject nowpeek = set.Peek();
        set.Dequeue();
        return nowpeek;
    }


    public static GameObject PoolRequest(string objName)
    {
        for(int i = 0; i<newProfile.Length; i++)
        {
            if(newProfile[i].name == objName)
            {
                return PoolRequest(newProfile[i].inConObject,newProfile[i].inConObject.Peek(), new Vector3(0, 0, 0), new Quaternion(0,0,0,0));
            }
        }

        return null; 
    }

    public static GameObject PoolRequest(string objName, Vector3 pos)
    {
        for (int i = 0; i < newProfile.Length; i++)
        {
            if (newProfile[i].name == objName)
            {
                return PoolRequest(newProfile[i].inConObject,newProfile[i].inConObject.Peek(), pos, new Quaternion(0, 0, 0, 0));
            }
        }
        return null; 
    }

    public static GameObject PoolRequest(string objName, Vector3 pos, Quaternion rot)
    {
        for (int i = 0; i < newProfile.Length; i++)
        {
            if (newProfile[i].name == objName)
            {
                return PoolRequest(newProfile[i].inConObject,newProfile[i].inConObject.Peek(), pos, rot);
            }
        }
        return null; 
    }

    public static void CullObject(GameObject cullObject)
    {
        cullObject.SetActive(false);
        cullObject.transform.position = new Vector3(0, 0, 0);
        cullObject.transform.rotation = new Quaternion(0, 0, 0, 0);

        for (int i = 0; i < newProfile.Length; i++)
        {
            if (cullObject.transform.parent == newProfile[i].container)
            {
                newProfile[i].inConObject.Enqueue(cullObject);
            }
        }
    }
}

[System.Serializable]
struct PoolProfile
{
    [Header("Container Name")]
    public string name;
    [Header("Default Amount")]
    public int defalutAmount;
    [Header("Add Amount")]
    public int AddAmount;
    [Header("GameObject")]
    public GameObject prefabSet;
    [Header("Container")]
    [HideInInspector]
    public GameObject container;
    [Header("Default Position")]
    public Vector3 defalutVector;
    [Header("Container Object")]
    public Queue<GameObject> inConObject;
}
8i9zcol2

8i9zcol21#

销毁对象有时比创建对象池更快,确切地说,创建第一个对象往往是这个过程中最繁重的部分。
当对象生成拖慢了整个游戏时,引入对象池是很好的。在引入对象池后,总是需要进行性能检查。
我认为最快的方法是在Stack中实现它。

using System;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;

public sealed class ObjectPool<T> : IDisposable where T : Component
{
    readonly Stack<T> _instances = new ();
    readonly int _maxObjects;
    Transform _parent;
    T _prefab;
    bool _isDisposed;

    public ObjectPool(T prefab, int maxObjects = 0)
    {
        _prefab = prefab;
        _maxObjects = maxObjects;
        _parent = new GameObject(prefab.name + "_Poo").transform;
    }

    public ObjectPool(T prefab, GameObject parent, int maxObjects = 0)
    {
        _prefab = prefab;
        _maxObjects = maxObjects;
        _parent = parent.transform;
    }

    public ObjectPool(T prefab, Transform parent, int maxObjects = 0)
    {
        _prefab = prefab;
        _maxObjects = maxObjects;
        _parent = parent;
    }

    public T Spawn()
    {
        var instance = _instances.Count > 0
                ? _instances.Pop()
                : CreateInstance();
        instance.gameObject.SetActive(true);
        return instance;
    }

    public void DeSpawn(T instance)
    {
        instance.gameObject.SetActive(false);
        if (_maxObjects > 0
            && _instances.Count >= _maxObjects)
        {
            Object.Destroy(instance.gameObject);
        }
        else
        {
            _instances.Push(instance);
        }
    }

    public void PreLoad(int count)
    {
        if (_maxObjects > 0)
        {
            count = Mathf.Clamp(count, 0, _maxObjects);
        }
        for (var i = 0; i < count; i++)
        {
            DeSpawn(CreateInstance());
        }
    }
    
    T CreateInstance() => Object.Instantiate<T>(_prefab, _parent, false);

    public void ClearAll()
    {
        while (_instances is {Count: > 0})
        {
            var obj = _instances.Pop();
            if (obj != default)
            {
                Object.Destroy(obj.gameObject);
            }
        }
    }

    public void Dispose()
    {
        if (_isDisposed)
        {
            return;
        }
        _isDisposed = true;
        _parent = null;
        _prefab = null;
        ClearAll();
    }
}

其使用方法如下

using UnityEngine;

public sealed class BulletsSpawner : MonoBehaviour
{
    [SerializeField] Bullet _bulletPrefab;

    ObjectPool<Bullet> _pool;
    
    void Awake()
    {
        _pool = new ObjectPool<Bullet>(_bulletPrefab, transform);
    }

    public Bullet Spawn(Vector3 position, Vector3 rotation)
    {
        var obj = _pool.Spawn();
        obj.transform.SetPositionAndRotation(position, Quaternion.Euler(rotation));
        return obj;
    }

    public void DeSpawn(Bullet bullet) => _pool.DeSpawn(bullet);

    void OnDestroy() => _pool.Dispose();
}

相关问题