通过对象池减少对象的创建优化性能:空间换时间
常用切重复的对象可以通过对象池管理进行复用,减少重复创建。
例:同一个技能释放每次使用的都是预制体,只是技能伤害可能有所变化。技能每次释放结束通过gameObject.SetActive(false)隐藏对象,再次释放同一技能修改其伤害数值并gameObject.SetActive(true)展示对象。就可以避免大量的重复技能创建节约CPU运算性能。
示例代码
对象池代码
using System.Collections.Generic;
using UnityEngine;
public class GameObjectPool
{
public GameObject gameObjectPool;
private Dictionary<string, Queue<GameObject>> _pool;
public GameObjectPool(string name)
{
_pool = new Dictionary<string, Queue<GameObject>>();
gameObjectPool = new GameObject(name);
}
// 获取对象,通过预制体资源地址,分别获取、存储不同的队列中。
public GameObject GetGameObject(string key)
{
if (!_pool.ContainsKey(key))
{
return null;
}
if (_pool[key].Count > 0)
{
return _pool[key].Dequeue();
}
else
{
return null;
}
}
// 回收对象
public void RecoveryGameObject(string key, GameObject gameObject)
{
if (!_pool.ContainsKey(key))
{
_pool[key] = new Queue<GameObject>();
}
gameObject.SetActive(false);
gameObject.transform.SetParent(gameObjectPool.transform);
_pool[key].Enqueue(gameObject);
}
}
对象池的使用
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class SkillManager : MonoBehaviour
{
public SkillEventSO skillManagerSO;
private AsyncOperationHandle<GameObject> _gameObjectHandle;
private GameObjectPool _bulletPool;
#region Unity生命周期
private void Awake()
{
_bulletPool = new GameObjectPool("BulletGameObjectPool");
_bulletPool.gameObjectPool.transform.SetParent(transform);
}
#endregion
// 释放技能
public void CastSkill(SkillDTO skillDTO)
{
string prefabAddress = skillDTO.prefabAddress;
// 对象池获取对象,如果池中存在对象就直接拿来用,如果没有就是实例化一个新的
GameObject bullet = _bulletPool.GetGameObject(prefabAddress);
if (bullet != null)
{
bullet.transform.SetParent(transform);
bullet.GetComponent<BulletController>().skillDTO = skillDTO;
bullet.SetActive(true);
}
else
{
_gameObjectHandle = Addressables.LoadAssetAsync<GameObject>(prefabAddress);
_gameObjectHandle.Completed += (handle) =>
{
if (handle.Status == AsyncOperationStatus.Succeeded)
{
bullet = Instantiate(handle.Result, transform);
bullet.transform.SetParent(transform);
bullet.GetComponent<BulletController>().skillDTO = skillDTO;
bullet.GetComponent<BulletController>().skillManager = this;
}
else
{
Debug.LogError("Asset load failed: " + prefabAddress);
}
};
}
}
// 回收技能
public void RecoveryBulletGameObject(GameObject bulletGameObject)
{
_bulletPool.RecoveryGameObject(bulletGameObject.GetComponent<BulletController>().skillDTO.prefabAddress, bulletGameObject);
}
}