池对象事件
接口名
IPoolObjectEvent
说明
需要接受池对象的事件时,可以实现该接口。
代码
namespace ZeroFramework
{
public interface IPoolObjectEvent
{
void OnPoolObjectCreate();
void OnPoolObjectRequest();
void OnPoolObjectReturn();
void OnPoolObjectDestroy();
}
public class NullPoolObjectEvent : IPoolObjectEvent
{
public void OnPoolObjectCreate()
{
}
public void OnPoolObjectRequest()
{
}
public void OnPoolObjectReturn()
{
}
public void OnPoolObjectDestroy()
{
}
}
}
对象池
类名
UnityObjectPool
说明
对象池,不要调用构造函数创建,用对象池工厂创建。
代码
using System.Collections.Generic;
using UnityEngine;
namespace ZeroFramework
{
public class UnityObjectPool<T> where T : Object
{
private readonly List<T> _globalPool = new List<T>();
private readonly Queue<T> _pool = new Queue<T>();
private readonly T _prefab;
private IPoolObjectEvent _objectEvent;
private Transform _root;
public UnityObjectPool(T prefab)
{
_prefab = prefab;
}
public void SetObjectRoot(Transform root)
{
_root = root;
}
public void Generate(int capacity)
{
for (int i = 0; i < capacity; i++)
{
CreatePoolObject();
}
}
private void CreatePoolObject()
{
var poolObject = InstantiatePrefab();
RegisterObjectToGlobalPool(poolObject);
AddObjectToPool(poolObject);
GetObjectEvent(poolObject).OnPoolObjectCreate();
}
private T InstantiatePrefab()
{
var poolObject = Object.Instantiate(_prefab, _root);
InactiveObject(poolObject);
return poolObject;
}
private IPoolObjectEvent GetObjectEvent(T poolObject)
{
return _objectEvent ??= GetObjectComponent<IPoolObjectEvent>(poolObject) ?? new NullPoolObjectEvent();
}
private TComponent GetObjectComponent<TComponent>(T poolObject)
{
return poolObject switch
{
GameObject gameObject => gameObject.GetComponent<TComponent>(),
Component component => component.GetComponent<TComponent>(),
_ => throw new ZeroFrameworkException("预设类型错误")
};
}
private void ActiveObject(T poolObject)
{
SetObjectActive(poolObject, true);
}
private void InactiveObject(T poolObject)
{
SetObjectActive(poolObject, false);
}
private void SetObjectActive(T poolObject, bool isActive)
{
switch (poolObject)
{
case GameObject gameObject:
gameObject.SetActive(isActive);
break;
case Component component:
component.gameObject.SetActive(isActive);
break;
}
}
private void AddObjectToPool(T poolObject)
{
_pool.Enqueue(poolObject);
}
private void RegisterObjectToGlobalPool(T poolObject)
{
_globalPool.Add(poolObject);
}
public T RequestObject()
{
if (IsPoolEmpty())
{
CreatePoolObject();
}
var poolObject = _pool.Dequeue();
ActiveObject(poolObject);
GetObjectEvent(poolObject).OnPoolObjectRequest();
return poolObject;
}
private bool IsPoolEmpty()
{
return _pool.Count <= 0;
}
public void ReturnObject(T poolObject)
{
if (InPool(poolObject))
{
return;
}
InactiveObject(poolObject);
AddObjectToPool(poolObject);
GetObjectEvent(poolObject).OnPoolObjectReturn();
}
public void ReturnAllObject()
{
foreach (var poolObject in _globalPool)
{
ReturnObject(poolObject);
}
}
private bool InPool(T poolObject)
{
return _pool.Contains(poolObject);
}
public void Clear()
{
foreach (var poolObject in _globalPool)
{
DestroyObject(poolObject);
GetObjectEvent(poolObject).OnPoolObjectDestroy();
}
_globalPool.Clear();
_pool.Clear();
}
private void DestroyObject(T poolObject)
{
switch (poolObject)
{
case GameObject gameObject:
Object.Destroy(gameObject);
break;
case Component component:
Object.Destroy(component.gameObject);
break;
}
}
}
}
对象池工厂
类名
UnityObjectPoolFactory
说明
用来创建对象池
代码
using UnityEngine;
namespace ZeroFramework
{
public static class UnityObjectPoolFactory
{
public static UnityObjectPool<T> Create<T>(T prefab, int capacity = 16, Transform root = null)
where T : Object
{
var pool = new UnityObjectPool<T>(prefab);
pool.SetObjectRoot(root);
pool.Generate(capacity);
return pool;
}
}
}
示例
子弹脚本
类名
Bullet
说明
代码
using UnityEngine;
using ZeroFramework;
public class Bullet : MonoBehaviour, IPoolObjectEvent
{
private UnityObjectPool<Bullet> _pool;
public void SetPool(UnityObjectPool<Bullet> pool)
{
_pool = pool;
}
public void ReturnToPool()
{
_pool.ReturnObject(this);
}
#region 池对象事件接口
public void OnPoolObjectCreate()
{
Debug.Log(nameof(OnPoolObjectCreate));
}
public void OnPoolObjectRequest()
{
Debug.Log(nameof(OnPoolObjectRequest));
}
public void OnPoolObjectReturn()
{
Debug.Log(nameof(OnPoolObjectReturn));
}
public void OnPoolObjectDestroy()
{
Debug.Log(nameof(OnPoolObjectDestroy));
}
#endregion
}
使用子弹对象池脚本
类名
TestButtleObjectPool
说明
使用UnityObjectPoolFactory.Create 创建对象池
代码
using UnityEngine;
using ZeroFramework;
public class TestButtleObjectPool : MonoBehaviour
{
[SerializeField] private Bullet _bullet;
[SerializeField] private Transform _poolRoot;
private UnityObjectPool<Bullet> _pool;
private Bullet _poolObject;
private void Awake()
{
_pool = UnityObjectPoolFactory.Create(_bullet, 5, _poolRoot);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
_poolObject = _pool.RequestObject();
_poolObject.SetPool(_pool);
}
if (Input.GetKeyDown(KeyCode.E))
{
if (_poolObject)
{
_poolObject.ReturnToPool();
_poolObject = null;
}
}
if (Input.GetKeyDown(KeyCode.R))
{
_pool.ReturnAllObject();
}
if (Input.GetKeyDown(KeyCode.T))
{
_pool.Clear();
}
}
}
仓库(代码会有差异)
https://gitee.com/ZeroRevival/zero-framework.git
|