Unity 对象池(ObjectPool)-含实现

文章介绍了在Unity中如何通过使用对象池来优化内存分配和垃圾回收,减少CPU开销。通过预先加载和存储实例对象,可以避免运行时频繁的内存分配。对象池的实现包括入池、取出和清除等操作,使用Dictionary和Queue数据结构进行管理。文章还提供了具体的实现代码示例以及如何在实际项目中应用对象池进行内存优化。

尽可能使用对象池:

在unity中,内存的分配和内存消耗都会程序带来影响,以及每次C#对实例对象的垃圾回收都很吃力,会占用大量的CPU算力,因此我们才需要尽可能的使用对象池将暂时不适用的对“存放起来”,待到再次使用的时候直接拿出来,而省去实例化的操作”

ps:减少内存的分配除了使用对象池外,还可以在对象池上使用预加载来优化,在程序运行前让对象池中的对象分配的多一些,这样在需要实例对象的时候就不在需要临时分配内存了。同时!此方法也可以拓展到资源内存,类实例对象有对象池,资源也可以有对象池,在核心程序运行前,如果能够提前知道后面的加载的内容,那么就提前将资源内容加载到内存就可以减少让内存分配的次数,甚至完全避免临时的加载和分配。
例如:统计每个角色图样的资源和实例对象在下一个场景中数量并提前加载,或者接近某个出口或者出口的时候开始预测即将进入的场景内容等


实现思路:

  1. 使用queue先入先出的特点(使用stack也可以)存放同一种实例对象
  2. 以相同对象的name为key,queue<实例对象>为value 生命字典作为对象池
  3. 实现基本的三个方法:入池,取出和清除

公共函数

函数名 解释
GetObj(GameObject) 从对象池中得到一个游戏对象,如果池中不存在就会创建一个
PushAllChildren(GameObject) 将传入物体的子物体全部放入对象池
PushObj(GameObject) 将游戏对象放入对象池

实现:

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

//对象池
public class  ObjectPool {
   
   
    //存放所有池中物体的父对象
    private GameObject poolPos = GameObject.Find("ObjectPool");
    private static ObjectPool instance;
    public static ObjectPool Instance {
   
   
        get {
   
   
            if (instance == null) instance 
### 在 Unity 中通过 ObjectPool 实现对象池的分类存储与可视化扩容 在 Unity实现对象池的分类存储和可视化扩容,可以通过以下方法完成。这种方法结合了对象池的设计思路[^1],并扩展了其功能以支持分类存储和动态调整池大小。 #### 1. 分类存储的实现 为了实现对象池的分类存储,可以使用字典(`Dictionary`)来管理不同类型的池对象。每个池对象对应一个特定的类型,并通过键值对的形式进行存储。 ```csharp using System.Collections.Generic; using UnityEngine; public class ObjectPoolManager : MonoBehaviour { private static Dictionary<string, ObjectPool> poolLibrary = new(); /// <summary> /// 创建分类对象池 /// </summary> public static ObjectPool CreatePool<T>(string name, GameObject sample) where T : MonoBehaviour { ObjectPool pool = new GameObject($"{name} Pool").AddComponent<ObjectPool>(); string key = typeof(T).Name; if (!poolLibrary.ContainsKey(key)) { poolLibrary.Add(key, pool); } pool.transform.SetParent(Instance.transform); pool.Init<T>(sample); return pool; } /// <summary> /// 获取分类对象池 /// </summary> public static ObjectPool GetPool<T>() where T : Component { string key = typeof(T).Name; if (poolLibrary.ContainsKey(key)) { return poolLibrary[key]; } return null; } } ``` 上述代码中,`ObjectPoolManager` 类负责管理所有对象池的创建和获取操作。通过 `typeof(T).Name` 作为键值,确保每个池对象能够被唯一标识并分类存储。 #### 2. 可视化扩容的实现 为了实现对象池的可视化扩容,可以在 Unity 编辑器中添加一个自定义窗口,允许开发者在运行时动态调整池大小。 ##### 自定义编辑器窗口 ```csharp using UnityEditor; using UnityEngine; public class ObjectPoolWindow : EditorWindow { private ObjectPool selectedPool; private int newSize; [MenuItem("Window/Object Pool Manager")] public static void ShowWindow() { GetWindow(typeof(ObjectPoolWindow)); } private void OnGUI() { GUILayout.Label("Object Pool Manager", EditorStyles.boldLabel); // 显示当前所有池对象 foreach (var pair in ObjectPoolManager.poolLibrary) { if (GUILayout.Button(pair.Key)) { selectedPool = pair.Value; } } if (selectedPool != null) { EditorGUILayout.LabelField($"Selected Pool: {selectedPool.name}"); newSize = EditorGUILayout.IntField("New Size:", selectedPool.PoolSize); if (GUILayout.Button("Resize Pool")) { selectedPool.Resize(newSize); } } } } ``` 上述代码中,`ObjectPoolWindow` 提供了一个图形界面,允许用户选择特定的对象池并调整其大小。通过调用 `Resize` 方法,可以动态改变池的容量。 #### 3. 对象池的核心逻辑 以下是对象池的核心逻辑,包括初始化、对象分配和回收等功能。 ```csharp using System.Collections.Generic; using UnityEngine; public class ObjectPool : MonoBehaviour { private Queue<GameObject> pooledObjects; private GameObject objectToPool; public int PoolSize { get; private set; } public void Init<T>(GameObject sample) where T : MonoBehaviour { pooledObjects = new Queue<GameObject>(); objectToPool = sample; PoolSize = 0; for (int i = 0; i < 5; i++) // 初始池大小为5 { GameObject obj = Instantiate(sample); obj.SetActive(false); pooledObjects.Enqueue(obj); PoolSize++; } } public GameObject GetPooledObject() { if (pooledObjects.Count > 0) { GameObject obj = pooledObjects.Dequeue(); obj.SetActive(true); return obj; } else { GameObject newObj = Instantiate(objectToPool); newObj.SetActive(true); PoolSize++; // 动态扩展池大小 return newObj; } } public void ReturnObjectToPool(GameObject obj) { obj.SetActive(false); pooledObjects.Enqueue(obj); } public void Resize(int newSize) { while (pooledObjects.Count > newSize) { GameObject obj = pooledObjects.Dequeue(); Destroy(obj); } while (pooledObjects.Count < newSize) { GameObject obj = Instantiate(objectToPool); obj.SetActive(false); pooledObjects.Enqueue(obj); } PoolSize = newSize; } } ``` 上述代码中,`ObjectPool` 类实现对象池的基本功能,包括初始化、对象分配、回收和动态调整大小等操作[^1]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值