這項優化方法又是從別的領域借鑑來的, 最開始瞭解的一個東西是線程池,內存池。
其實不論是線程池還是內存池,都在遊戲引擎中非常常見,首先我們先介紹一下他們的應用場景,因爲在遊戲引擎裏我們常常遇到這樣一個問題,那就是內存(線程)的申請和釋放非常頻繁,雖然這塊線程或者說內存的申請的數目或者大小不多,但是不論是內存的申請、釋放或者是線程的申請、釋放,都會導致要讓操作系統在用戶態和核心態之間還會切換,這是一項很耗時的操作。
所以前輩們就想到一種以空間換時間的方式,就是可以提前預申請一大塊內存,一大堆線程,然後先不用,不喚醒,用一個管理系統去存儲他們,於是在用戶申請內存或者線程的時候,就不是向操作系統提出申請,而是向這個我們自己的管理系統提出申請。往往這就是一個移動指針的時間——雖然這種方式實際用掉了很多待機的空間。
在我們做AI的時候,同樣面臨着這個問題,有一些AI,是死亡和生成非常頻繁,比如Boss召喚的自爆兵,偏偏這些東西數量還可能很大。而Instantiate和Destroy,偏偏又是兩個很耗時的操作,所以我們同樣使用了AI池的技術。
public class AIPoorComponent:UComponent
{
public GameObject mAI_Template;
public AIEntity[] mAIPoor = new AIEntity[3000];
public int mMaxCount = 3000;
private int mTempCount = 0;
public override void Init ()
{
for (int i = 0; i < mMaxCount; i++)
{
mAIPoor [i].mAI = mAI_Template;
mAIPoor [i].Init ();
mAIPoor [i].GetComponent<BaseAIComponent> ().mPoorID = i;
}
}
public override void Release ()
{
for (int i = 0; i < mMaxCount; i++)
{
mAIPoor [i].Release ();
}
}
public void DestroyEntity(int id)
{
mUEntity.mWorld.deleteEntity (mAIPoor[id]);
mAIPoor [id].GetComponent<BaseAIComponent> ().mAIRT.SetActive (false);
AIEntity temp = mAIPoor [id];
mAIPoor [id] = mAIPoor[mTempCount-1];
mAIPoor [mTempCount - 1] = temp;
mAIPoor [id].GetComponent<BaseAIComponent> ().mPoorID = id;
mAIPoor [mTempCount - 1].GetComponent<BaseAIComponent> ().mPoorID = mTempCount - 1;
mTempCount--;
}
public AIEntity InstantiateEntity()
{
mAIPoor [mTempCount].mAllBitBunch.SetCount ((int)mUEntity.mWorld.mComponentCount);
mUEntity.mWorld.registerEntity (mAIPoor[mTempCount]);
mAIPoor [mTempCount].GetComponent<BaseAIComponent> ().mAIRT.SetActive (true);
mTempCount++;
return mAIPoor [mTempCount - 1];
}
}
首先這個管理器會有一個模板,也就是這些AI的Prefab,然後在遊戲一開始,我們就生成了一大堆這個玩意,然後都不激活他。
然後我們可以看到,Instantiate和Destroy在這裏,僅僅只是移動一下數組指針,和激活一下GameObject的操作。