有的时候,我们需要动态创建某个对象,比如点击就会出现漂浮的文本提示,漂浮的奖励等等,他们可能会创建很多,而且很快就会被销毁,并且创建销毁的操作很频繁,如果太频繁,会很耗性能,好的办法是,当创建出来后,把它存在内存中,需要销毁的时候只是把它隐藏了,放在对象池中,等需要用了,再从对象池中把它拿出来显示。这样省去了频繁创建,销毁的操作。
这里自己写了一个泛型的对象池类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameObjectPool <T>: MonoBehaviour where T : class {
private T m_resGameObj ;
private GameObject m_componentParent;
public delegate void OnCall();
public delegate void OnCall<T0>(T0 arg0);
public OnCall OnRecycle = null;
public OnCall OnNew = null;
public OnCall OnInitialize = null ;
private List<T> m_pool = new List<T>() ;
private List<T> m_usePool = new List<T>();
public GameObjectPool(T resObj) {
m_resGameObj = resObj;
}
public GameObjectPool(GameObject parent) {
m_componentParent = parent;
}
public int Length() {
return m_pool.Count;
}
public T0 get<T0>() where T0 : class {
T0 obj = null ;
if (m_pool.Count 0) {
obj = m_pool[m_pool.Count-1] as T0;
m_usePool.Add(m_pool[m_pool.Count-1]);
m_pool.RemoveAt(m_pool.Count-1);
}
else {
if (this.OnNew != null) {
this.OnNew.Invoke();
}
Debug.Log("~~~~ type os " + typeof(Component) + " dafdafada " + typeof(T));
if (m_resGameObj != null && typeof(GameObject) == m_resGameObj.GetType()) {
obj = Instantiate(m_resGameObj as GameObject) as T0;
m_usePool.Add(obj as T);
}
else if (m_componentParent != null && typeof(Component).IsAssignableFrom(typeof(T) ) ) {
obj = m_componentParent.AddComponent(typeof(AudioSource)) as T0;
m_usePool.Add(obj as T);
Debug.Log("~~~~ new a obj , current used count is " + m_usePool.Count);
}
else {
//TODO: 其他类型的暂不处理
}
}
if (this.OnInitialize != null) {
this.OnInitialize.Invoke();
}
return obj ;
}
public void Recycle<T0>(T0 obj) where T0: class {
if (obj == null) {
return ;
}
for (int i = 0 ; i < m_usePool.Count ; ++i) {
if (obj == m_usePool[i]) {
m_usePool.Remove(obj as T);
Debug.Log("~~~~ remove usepool " + m_usePool.Count );
}
}
m_pool.Add(obj as T);
if (this.OnRecycle != null) {
this.OnRecycle.Invoke();
}
Debug.Log("~~~~ current pool is " + m_pool.Count );
}
public List<T GetAllUseObj() {
return m_usePool;
}
public List<T GetAllUnUsedObj() {
return m_pool;
}
}
比如这里我用在声音的控制上,我有一个soundsManager来控制所有音效和背景音乐的播放,而音效是可能同时播放多个的,这时候就需要创建多个audioSource来同时播放不同的音乐。
使用:
private GameObjectPool<AudioSource> m_objPool ;
void Awake(){
DontDestroyOnLoad(this);
m_objPool = new GameObjectPool<AudioSource>(this.gameObject);
}
public void playSounds(string clipName) {
StartCoroutine(poolToPlaySounds(clipName));
}
IEnumerator poolToPlaySounds(string clipName) {
AudioSource audio = m_objPool.get<AudioSource>();
audio.loop = false ;
singlePlaySounds(clipName, audio);
yield return new WaitForSeconds(audio.clip.length);
m_objPool.Recycle(audio);
}
在播放声音的时候,起一个进程,从objectpool中获取一个AudioSource的component, 如果对象池中没有空余的,那么就创建一个新的返回使用,
simgleplaysounds是我自己写的一个方法,里面的逻辑就是普通的将clip赋值给audio ,然后去播放,这时可以获得这个clip的播放时长,然后给这个进程设置一个delay时间,等播放时间完了,后面对象池将这个新创建的AudioSource对象存起来,供下次重复使用.