Unity对象池的高级写法 (Plus优化版)

唐老师关于对物体分类的OOD的写法确实十分好,代码也耦合度也低,但是我有个简单的写法同样能实现一样的效果,所以我就充分发挥了一下主观能动性

相较于基本功能,这一版做出了如下改动

1.限制了对象池最大数量,多出来的要入池就会销毁掉

  // 最大容量
  private int maxCapacity = 100;

2.对生成出来的对象做出了二级分类更加清晰

 public void SetParent(string name, GameObject obj) {
     // 设置一级父对象
     if (poolObjF == null)
         poolObjF = new GameObject("一级分类");

     // 查找或创建二级父对象
     if (!poolObjS.ContainsKey(name)) {
         //创建临时物体当作二级分类空对象,之后添加到字典中
         GameObject tempObj = new GameObject("二级分类" + name);
         tempObj.transform.parent = poolObjF.transform;
         poolObjS[name] = tempObj;
     }
     obj.transform.parent = poolObjS[name].transform;
 }

98e18a00ff7a4b409b6f1ac7c7ecd596.gif

3.优化了清空池的方法

 public void ClearPool() {
     foreach (var item in pool) {
         foreach (var obj in item.Value) {
             GameObject.Destroy(obj);
         }
     }
     pool.Clear();
     poolObjF = null;
     poolObjS.Clear();
 }

4.添加了处理其他逻辑的函数,可以写一些重置AI状态的逻辑,会在拿出物体的时候调用

   /// <summary>
   /// 处理其他事情的逻辑可以写在这里面,比如重置怪物血量等
   /// </summary>
   public void OtherThing()
       { 
   
   }

 

5.切换场景不销毁池物品调用方法即可

    //public void DontDestoryPool(GameObject gameObject)
    //    {
    //   GameObject.DontDestroyOnLoad(gameObject);
    //}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyPool : SingleBase<MyPool> {
    // 一级父对象
    private GameObject poolObjF;
    // 二级父对象字典
    private Dictionary<string, GameObject> poolObjS = new Dictionary<string, GameObject>();
    // 抽屉字典 string => 物品名字,List => 具体物品
    public Dictionary<string, List<GameObject>> pool = new Dictionary<string, List<GameObject>>();
    // 最大容量
    private int maxCapacity = 100;

    /// <summary>
    /// 得到对象池中的物品
    /// </summary>
    /// <param name="path">预制体路径</param>
    /// <returns></returns>
    public GameObject GetObj(string path) {
        GameObject obj = null;
        // 如果有该物体,从抽屉中取出,如果没有则创建一个
        if (pool.ContainsKey(path) && pool[path].Count > 0) {
            obj = pool[path][0];
            pool[path].RemoveAt(0);
        }
        else {
            obj = GameObject.Instantiate(Resources.Load<GameObject>(path));
            obj.name = path;
        }
        obj.SetActive(true);
        //OtherThing();
        return obj;
    }
    /// <summary>
    /// 向对象池放回物品
    /// </summary>
    /// <param name="name">要放回的抽屉名</param>
    /// <param name="obj">要放回的物品对象</param>
    public void PutBackObj(string name, GameObject obj) {
        SetParent(name, obj);
        obj.SetActive(false);
        // 如果有抽屉则放回去,没有则新建一个抽屉放进去,同时注意限制最大数量
        if (pool.ContainsKey(name)) {
            if (pool[name].Count < maxCapacity) {
                pool[name].Add(obj);
            }
            else {
                GameObject.Destroy(obj);
            }
        }

        else {
            pool.Add(name, new List<GameObject>() { obj });
        }
    }

    public void SetParent(string name, GameObject obj) {
        // 设置一级父对象
        if (poolObjF == null)
            poolObjF = new GameObject("一级分类");

        // 查找或创建二级父对象
        if (!poolObjS.ContainsKey(name)) {
            //创建临时物体当作二级分类空对象,之后添加到字典中
            GameObject tempObj = new GameObject("二级分类" + name);
            tempObj.transform.parent = poolObjF.transform;
            poolObjS[name] = tempObj;
        }
        obj.transform.parent = poolObjS[name].transform;
    }

    public void ClearPool() {
        foreach (var item in pool) {
            foreach (var obj in item.Value) {
                GameObject.Destroy(obj);
            }
        }
        pool.Clear();
        poolObjF = null;
        poolObjS.Clear();
    }
    /// <summary>
    /// 处理其他事情的逻辑可以写在这里面,比如重置怪物血量等
    /// </summary>
    public void OtherThing()
        { 
    
    }
}

 

 

Unity 中的对象池是一种资源管理技术,用于在游戏运行过程中高效地创建、管理和回收对象。对象池的主要目的是减少频繁创建和销毁对象带来的性能开销,尤其是在有大量短期使用对象(如小敌人、项目等)的情况下。 下面是使用 Unity 对象池的基本步骤: 1. 创建对象池:首先,你需要创建一个包含所需对象类型的新对象池。这通常是一个静态类或专用脚本,负责管理对象的生命周期。 ```csharp public class ObjectPool<T> where T : Component { private List<T> poolObjects; private Stack<T> availableObjects; // 初始化方法 public ObjectPool(int initialSize) { poolObjects = new List<T>(); for (int i = 0; i < initialSize; i++) { T obj = Instantiate<T>(); obj.SetActive(false); // 设置对象为非活动状态,直到需要时才激活 poolObjects.Add(obj); } availableObjects = new Stack<T>(poolObjects); } // 获取对象 public T BorrowObject() { if (availableObjects.Count > 0) { T obj = availableObjects.Pop(); obj.SetActive(true); return obj; } else { T obj = Instantiate<T>(); return obj; } } // 归还对象 public void ReturnObject(T obj) { obj.SetActive(false); availableObjects.Push(obj); } } ``` 2. 使用对象池:当你需要一个新对象时,从池中借用一个,用完后记得归还。这样,当对象不再被使用时,它会被放回池而不是直接销毁,以便后续其他地方可能需要它。 ```csharp private ObjectPool<MyObject> objectPool; void Start() { objectPool = new ObjectPool<MyObject>(10); } void Update() { MyObject newObj = objectPool.BorrowObject(); // 使用 newObj ... newObj.gameObject.SetActive(false); // 当对象不再需要时,归还给池子 // 如果对象池已满,考虑创建更多对象 if (objectPool.availableObjects.Count == 0 && poolSize < MaxPoolSize) { // 添加新对象到池中 objectPool.poolObjects.Add(Instantiate<MyObject>()); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值