Unity-对象池

 该脚本需要实例化

主要思想:用字典作为存放对象池的集合,用字典中的列表存放每个对象池的对象。

通过控制物体在unity场景中的active实现对象池的回收与再生,这样可以有效减少每次通过预制体生成物体的时间消耗,但是增加了使用的内存空间。

1、需要加入对象池的对象,需要实现IResetable接口,用于对象出生时的初始化

public interface IResetable
{
    void OnReset();
}

2、把管理对象池的脚本作成单例,初始化,并提供3个基础方法

        1)CreateObject:用于创建对象

        2)CollectObject:用于回收对象

        3)Clear:可以做成两个方法,一个是清理某一类物体的对象池;一个清理所有的对象池

public class GameObjectPool : MonoSingleton<GameObjectPool>
{
    //对象池的字典,事实上是放了好几个对象池
    //key:对象类型的字符串
    private Dictionary<string, List<GameObject>> cahe;
    //初始化
    public override void Init()
    {
        base.Init();
        cahe = new Dictionary<string, List<GameObject>>();
    }

    //需要的参数:对象类型字符串,对象预制体,位置,旋转
    public GameObject CreateObject(string key , GameObject prefab , Vector3 pos, Quaternion quaternion)
    {
        //FindUseableObject:寻找对象池中是否有可用的对象
        GameObject go = FindUsableObject(key);
        //如果没有在场景中创建该对象的物体
        if (go == null)
        {
            //AddObject:创建对象
            go = AddObject(key, prefab);
        }

        //初始化需要创建的对象
        UseObject(pos, quaternion, go);
        return go;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="go">回收对象</param>
    /// <param name="delay">延迟</param>
    public void CollectObject(GameObject go,float delay =0)
    {
        //协程用于延迟回收
        StartCoroutine(CollectObjectDelay(go,delay));
    }

    //清空
    //一般清空是倒着清空
    public void Clear(string key)
    {
        if (cahe.ContainsKey(key))
        {
            foreach(GameObject go in cahe[key])
            {
                Destroy(go);
            }
            cahe.Remove(key);
        }
    }

    //清空所有
    public void ClearAll()
    {
        foreach (List<GameObject> go in cahe.Values)
        {
            foreach(GameObject go1 in go)
            {
                Destroy(go1);
            }
        }
        cahe.Clear();
    }

    //回收对象:把对象的active设成false
    private IEnumerator CollectObjectDelay(GameObject go,float delay)
    {
        yield return new WaitForSeconds(delay);
        go.SetActive(false);
    }

    //初始化对象
    private static void UseObject(Vector3 pos, Quaternion quaternion, GameObject go)
    {
        go.transform.position = pos;
        go.transform.rotation = quaternion;
        go.SetActive(true);
        //遍历执行物体中需要重置的脚本
        foreach(var item in go.GetComponents<IResetable>())
        {
            item.OnReset();
        }
    }

    //创建预制体,并加入字典(对象池)中
    private GameObject AddObject(string key, GameObject prefab)
    {
        GameObject go = Instantiate(prefab);
        if (!cahe.ContainsKey(key))
            cahe.Add(key, new List<GameObject>());
        cahe[key].Add(go);
        return go;
    }

    //查找对象池中是否有该类型的物体
    private GameObject FindUsableObject(string key)
    {
        if (cahe.ContainsKey(key))
             return cahe[key].Find(g => !g.activeInHierarchy);
        return null;
    }
}

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity中,虽然没有内置的对象池类,但是可以通过自定义脚本来实现对象池的功能。下面是一个简单的示例代码,展示了如何创建一个基本的对象池: ```csharp using System.Collections.Generic; using UnityEngine; public class ObjectPool : MonoBehaviour { public GameObject prefab; // 预制体 public int poolSize; // 对象池大小 private List<GameObject> objectPool; void Start() { objectPool = new List<GameObject>(); for (int i = 0; i < poolSize; i++) { GameObject obj = Instantiate(prefab); obj.SetActive(false); objectPool.Add(obj); } } public GameObject GetObjectFromPool() { for (int i = 0; i < objectPool.Count; i++) { if (!objectPool[i].activeInHierarchy) { objectPool[i].SetActive(true); return objectPool[i]; } } // 如果对象池中没有可用对象,则动态创建一个新对象 GameObject newObj = Instantiate(prefab); objectPool.Add(newObj); return newObj; } public void ReturnObjectToPool(GameObject obj) { obj.SetActive(false); } } ``` 在上述代码中,我们创建了一个名为ObjectPool的脚本。在Start方法中,我们初始化了对象池,根据poolSize的值来创建一定数量的对象,并将它们存储在objectPool列表中。 GetObjectFromPool方法用于从对象池中获取一个可用的对象。我们遍历objectPool列表,寻找第一个处于非激活状态的对象,并将其设置为激活状态,然后返回该对象。如果对象池中没有可用对象,则动态创建一个新对象,并将其添加到objectPool列表中。 ReturnObjectToPool方法用于将使用完的对象返回到对象池中。我们将传入的对象设置为非激活状态,以便下次复用。 通过这样的自定义脚本,你可以在Unity中实现对象池的功能,以提高游戏的性能和效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值