Unity对象池
迪丽瓦拉
2025-05-30 04:47:50
0

Unity对象池

  • 创建对象池基类
  • 创建宝石对象池
  • 创建物体脚本
  • 创建对象池控制器

在unity的2021版本后,Unity引入了对象池,从这以后就可以用Unity内置的对象池,这次我们就来演示一下Unity内置的对象池。

创建对象池基类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Pool;public class Basepool : MonoBehaviour where T : Component
{[SerializeField] protected T prefab;[SerializeField] private int defaultSize = 100; //对象池默认容量[SerializeField] private int maxSize = 500; //对象池最大容量private ObjectPool pool;public int ActiveCount => pool.CountActive;public int InactiveCount => pool.CountInactive;public int TotalCount => pool.CountAll;protected void Initialize(bool collectionCheck = true) =>pool = new ObjectPool(OnCreatePoolItem, OnGetPoolItem, OnRealeasePoolItem, OnDestroyPoolItem,collectionCheck, defaultSize, maxSize);protected virtual T OnCreatePoolItem() => Instantiate(prefab, transform);protected virtual void OnRealeasePoolItem(T obj) => obj.gameObject.SetActive(true); //将物体返回对象池protected virtual void OnGetPoolItem(T obj) => obj.gameObject.SetActive(true);protected virtual void OnDestroyPoolItem(T obj) => Destroy(obj.gameObject);public T Get() => pool.Get();public void Release(T obj) => pool.Release(obj);public void Clear() => pool.Clear();}

这段代码定义了一个泛型类 Basepool,用于创建对象池并管理其生命周期。具体来说,该类做了以下事情:

引入了必要的命名空间。
定义了一个泛型类型参数 T,用于表示对象池中存储的类型。
声明了一个 prefab 字段,用于存储需要缓存的对象的预制体。
声明了一个 defaultSize 字段,用于设置对象池的默认容量。
声明了一个 maxSize 字段,用于设置对象池的最大容量。
声明了一个 pool 字段,用于存储对象池实例。
定义了三个只读属性 ActiveCount、InactiveCount 和 TotalCount,用于获取对象池中活动、非活动和总共的对象数量。
定义了一个 Initialize 方法,用于初始化对象池,并接收一个 collectionCheck 参数用于设置对象池是否在每次 Get() 和 Release() 方法调用时进行垃圾回收。
实现了 OnCreatePoolItem、OnRealeasePoolItem、OnGetPoolItem 和 OnDestroyPoolItem 四个虚方法,它们分别在对象池中创建对象、释放对象、获取对象和销毁对象时被调用。这些方法的实现可以通过子类覆盖来自定义对象池的行为。
定义了 Get、Release 和 Clear 三个公共方法,分别用于从对象池中获取对象、释放对象和清空对象池。其中 Get 方法会从对象池中获取一个非活动对象并将其设置为活动状态,Release 方法则将一个活动对象返回到对象池中并将其设置为非活动状态,Clear 方法则会清空对象池中所有的对象并将其销毁。

创建宝石对象池

创建一个脚本Gempool,具体内容为

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.Pool;
using Random = UnityEngine.Random;
public class Gempool : Basepool{private void Awake() //初始化对象池{Initialize();}protected override Gem OnCreatePoolItem(){var gem = base.OnCreatePoolItem();gem.SetDeactivateAction(delegate { Release(gem); });return gem;}protected override void OnGetPoolItem(Gem gem){base.OnGetPoolItem(gem);gem.transform.position = transform.position + Random.insideUnitSphere * 2f;}public void SetPrefab(Gem prefab){this.prefab = prefab;}}

这段代码实现了一个基于泛型的对象池(Object Pool),其中的 Gem 是对象池中的对象类型。对象池可以用来重复利用已经创建的对象,从而减少对象的频繁创建和销毁,提高程序的性能和效率。

这个对象池继承自一个名为 Basepool 的基类,使用了泛型以适用不同类型的对象。代码中使用了 Unity 引擎中的一些类和接口,例如 MonoBehaviour、UnityEditor、UnityEngine.Pool 和 UnityEngine.Random。

在代码中,Awake() 方法用于初始化对象池,OnCreatePoolItem() 方法用于创建新的对象池中的对象,并将其设置为可重复利用状态,OnGetPoolItem() 方法用于获取对象池中的对象并设置其位置,SetPrefab() 方法用于设置对象池的预制件。

总的来说,这段代码实现了一个对象池,用于重复利用对象以提高程序的性能和效率。

创建物体脚本

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Gem : MonoBehaviour{[SerializeField] private float lifeTimeAfterLanding = 2f; //宝石生命周期private bool hasLanded;private float deactivateTimer;private System.Action deactivateAction;private void Update(){if (!hasLanded) return;deactivateTimer += Time.deltaTime;if (deactivateTimer >= lifeTimeAfterLanding){deactivateTimer = 0;deactivateAction.Invoke(this); //执行委托}}private void OnTriggerEnter(Collider other) //进入触发器{hasLanded = true;}private void OnDisable(){hasLanded = false;}public void SetDeactivateAction(System.Action dectivateAction) //设置委托{this.deactivateAction = dectivateAction;}}

这段代码定义了一个 Gem 类,该类实现了宝石的生命周期管理,主要功能包括:

监听碰撞器的触发事件,当宝石落地时,记录宝石已经着陆;
在宝石着陆后,开始计时,若宝石在一定时间内未被收集,则将其从场景中移除,以节省内存资源;
为了实现这个功能,该类使用了一个计时器 deactivateTimer,以及一个回调函数 deactivateAction,当计时器超过生命周期时间时,执行回调函数,将自身从场景中移除;
在对象被禁用时(例如被放回对象池时),将记录是否已经着陆的标志 hasLanded 置为 false,以便下次正确计算宝石生命周期;
通过 SetDeactivateAction 方法,将回调函数传递给 deactivateAction 成员变量,用于在计时器超时时执行。

创建对象池控制器

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;public class GemControl : MonoBehaviour{[SerializeField] private Gem[] gemPrefabs;[SerializeField] private int spawnAmount = 50;[SerializeField] private float spawnInterval = 0.5f;private float spawnTimer;private List gempools = new List();private void Start(){foreach (var prefab in gemPrefabs){var poolHolder = new GameObject($"Pool:{prefab.name}");poolHolder.transform.parent = transform;poolHolder.transform.position = transform.position;poolHolder.SetActive(false);var pool = poolHolder.AddComponent();pool.SetPrefab(prefab);poolHolder.SetActive(true);gempools.Add(pool);}}private void Update(){spawnTimer += Time.deltaTime;if (spawnTimer >= spawnInterval){spawnTimer = 0f;Spawn();}}void Spawn(){for (int i = 0; i < spawnAmount; i++){var randomIndex = Random.Range(0, gemPrefabs.Length);var pool = gempools[randomIndex];pool.Get();}}}

这段代码定义了一个 GemControl 类,该类用于生成和管理多个宝石对象池。主要功能包括:

定义一个宝石预制体数组 gemPrefabs,其中包含多种不同类型的宝石;
定义生成的宝石数量 spawnAmount,以及生成间隔时间 spawnInterval,用于控制宝石的生成频率和数量;
在 Start 方法中,对每个宝石预制体创建一个对象池,并将其添加到 gempools 列表中;
在 Update 方法中,根据设定的生成间隔时间 spawnInterval 和计时器 spawnTimer,判断是否需要生成新的宝石;
在 Spawn 方法中,循环生成指定数量的宝石,通过随机选择一个宝石预制体,从相应的对象池中获取一个未使用的宝石对象;
生成的宝石会自动加入它所属的对象池,并在被回收时被放回该对象池中。
总之,该类提供了一种可以在运行时动态生成多种不同类型宝石的方法,并通过对象池的方式管理宝石对象,避免了频繁的创建和销毁操作,提高了性能和效率。

最后的运行结果
在这里插入图片描述

相关内容