这周VR做飞机的项目,子弹太多,用到对象池,用的是一个插件,但是发现一个问题,子弹数特别多的情况下,池里放了400个子弹,特效也特别多,结果发现一个问题,从池中取对象和对象回池用时太长,多的时候能达到2ms。最后查看了底层,发现一个问题,池中对象是用list存放的,每次移除的时候耗时太多,应该是这个原因造成的。为了验证这个问题,我自己写了一个对象池,思路大致是对的,没有写那么严谨,可以做个参考。最后发现消时减少不少。主要是将list换成了LinkedList。
<pre name="code" class="csharp">using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace Patent
{
public class ObjectPool
{
public LinkedList<GameObject> UsingLinkedList;
public LinkedList<GameObject> UnusingLinkedList;
private GameObject prefab;
public ObjectPool(GameObject prefab)
{
this.prefab = prefab;
UsingLinkedList =new LinkedList<GameObject>();
UnusingLinkedList = new LinkedList<GameObject>();
for (int i = 0; i < 10; i++)
{
GameObject go = GameObject.Instantiate(prefab);
go.SetActive(false);
UnusingLinkedList.AddFirst(go);
}
}
public ObjectPool(GameObject prefab, int preloadNum)
{
this.prefab = prefab;
UsingLinkedList = new LinkedList<GameObject>();
UnusingLinkedList = new LinkedList<GameObject>();
for (int i = 0; i < preloadNum; i++)
{
GameObject go = GameObject.Instantiate(prefab);
go.SetActive(false);
UnusingLinkedList.AddFirst(go);
}
}
public GameObject PullObjcetFromPool(Quaternion q,Vector3 pos)
{
GameObject go = null;
if (UnusingLinkedList.Count > 0)
{
go = UnusingLinkedList.First.Value;
go.SetActive(true);
go.transform.rotation = q;
go.transform.position = pos;
UnusingLinkedList.RemoveFirst();
UsingLinkedList.AddLast(go);
}
else
{
go = GameObject.Instantiate(prefab);
go.transform.rotation = q;
go.transform.position = pos;
UsingLinkedList.AddLast(go);
}
return go;
}
public void PushObjcetToPool(GameObject handleObjcet)
{
if (handleObjcet.activeSelf)
{
handleObjcet.SetActive(false);
UnusingLinkedList.AddFirst(handleObjcet);
UsingLinkedList.Remove(handleObjcet);
}
}
public void Dispose()
{
UsingLinkedList.Clear();
UnusingLinkedList.Clear();
UsingLinkedList = null;
UnusingLinkedList = null;
}
}
}
namespace Patent
{
public class PoolManager : MonoBehaviour
{
public static PoolManager Instance;
public List<GameObject> prefabList;
//存放预制体对应的id,ObjcetPool
public Dictionary<int ,ObjectPool> poolManagerDic;
void Awake()
{
Instance = this;
//初始化所有成员
poolManagerDic =new Dictionary<int, ObjectPool>();
if (prefabList!=null&&prefabList.Count>0)
{
int leng = prefabList.Count;
GameObject prefabUnit = null;
for (int i = 0; i < leng; i++)
{
prefabUnit = prefabList[i];
poolManagerDic.Add(prefabUnit.GetInstanceID(),new ObjectPool(prefabUnit));
}
}
}
void Start()
{
}
void Update()
{
}
/// <summary>
/// 获取对应的对象池
/// </summary>
/// <param name="instanceID"></param>
/// <returns></returns>
public ObjectPool GetMyObjcetPool(int instanceID)
{
ObjectPool objcetPool = null;
if (poolManagerDic.ContainsKey(instanceID))
{
objcetPool = poolManagerDic[instanceID];
}
else
{
Debug.Log("cant find poolOjbects");
}
return objcetPool;
}
/// <summary>
/// 获取对应的对象池
/// </summary>
/// <param name="prefab"></param>
/// <returns></returns>
public ObjectPool GetMyObjcetPool(GameObject prefab)
{
ObjectPool objcetPool = null;
int instanceID = prefab.GetInstanceID();
if (poolManagerDic.ContainsKey(instanceID))
{
objcetPool = poolManagerDic[instanceID];
}
return objcetPool;
}
public void PushObjectPool(GameObject handleObjcet,ObjectPool objcetPool)
{
objcetPool.PushObjcetToPool(handleObjcet);
}
public void PushObjectPool(GameObject handleObject, ObjectPool objcetPool, float delayTime)
{
StartCoroutine(DelayPushToObjcetPool(handleObject,objcetPool,delayTime));
}
IEnumerator DelayPushToObjcetPool(GameObject handleObject, ObjectPool objcetPool, float delayTime)
{
yield return new WaitForSeconds(delayTime);
objcetPool.PushObjcetToPool(handleObject);
}
}
}
有时间将它完成,做成工具类,方便使用