Spawnpool 的使用 帶例項
最近也是看到一個挺不錯的外掛,所以自己簡單應用了一下。和大家分享下。
之前一直用的是ObjectPool,也就是物件池做東西,沒想到還有怎麼好的外掛緩衝池,確實對例項化的東西可以提高例項化的速度和優化記憶體。使用起來也挺方便的。
首先就是對spwanpool 的介紹:(我用的PoolManager版本是5.5.2的)
PoolName:快取池的唯一名稱。
MatchPoolScale:勾選後例項化的遊戲物件的縮放比例將全是1,不勾選擇用Prefab預設的。
MachPool Layer:勾選後例項化的遊戲物件的Layer將用Prefab預設的。
Don’t Reparent:勾選後例項化的物件將沒有父節點,通通在最上層,建議不要勾選。
Don’t Destroy On Load:這個就不用我解釋了吧?切換場景不釋放。
Log Messages 是否列印日誌資訊
Pre-Prefab Pool Options :快取池列表,意思就是快取列表裡面可以放各種型別的Prefab。右邊有個 “+”按鈕點選就新增每個型別的Prefab了
prefab:可以直接把工程裡的Prefab直接拖進來。
preloadAmount:快取池這個Prefab的預載入數量。意思為一開始載入的數量!
preloadTime:如果勾選表示快取池所有的gameobject可以“非同步”載入。
preloadFrames:每幾幀載入一個。
preloadDelay:延遲多久開始載入。
limitInstance:是否開啟物件例項化的限制功能。
limit Amount:限制例項化Prefab的數量,也就是限制緩衝池的數量,它和上面的preloadAmount是有衝突的,如果同時開啟則以limitAmout為準。
limitFIFO:如果我們限制了快取池裡面只能有10個Prefab,如果不勾選它,那麼你拿第11個的時候就會返回null。如果勾選它在取第11個的時候他會返回給你前10個裡最不常用的那個。
cullDespawend:是否開啟快取池智慧自動清理模式。
cull Above:快取池自動清理,但是始終保留幾個物件不清理。
cull Delay:每過多久執行一遍自動清理,單位是秒。從上一次清理過後開始計時
cullMaxPerPass:每次自動清理幾個遊戲物件。
緩衝池的幾個重要指令碼:
1、SpawnPool指令碼
指令碼用在佈局場景時,就把遊戲執行用時頻繁到的物體存放到此指令碼建立的快取池中在需要時使用就好,下面還有一個是用在場景佈局時不準備用到的物體,而是在用到時使用程式碼動態的建立一個快取池來使用。
limitInstance是否開啟(打鉤)的區別:
不開啟情況:假如此時preloadAmount為1,如果使用者想要每隔5秒去Spawn一個緩衝池中的物件,那麼當載入第二個prefab物件的時候,緩衝池會再建立一個此物件,如果程式再Spawn,那麼還會在產生一個這樣的物件,就這樣一直產生下去,Spawn幾次就產生幾個物件!
(粒子系統:迴圈時:Spawn幾次,就會產生幾個物件,不迴圈時(迴圈結束狀態為false):會再產生一個物件,如果此時的Spawn速度特別快,並且檢測不到前面的物件狀態為false,那麼可能會產生多個物件,直到檢測到前面的幾個物件有false狀態,那麼產生物件到此為止,程式在此幾個物件之間來回Spawn!)
開啟情況:
此時Limit Amount為1
limitFIFO勾選:那麼程式永遠使用的是預載入物件,而不會再產生其他物件!當載入第二次的時候,即使第一個物件處於true狀態,也使用它,即操作第一個物件!(粒子系統為迴圈或者不迴圈時,效果和這一樣)
limitFIFO不勾選:那麼程式永遠使用的是預載入物件,而不會再產生其他物件!當載入第二次的時候,那麼必須等第一個物件變為false狀態,才能使用它!如果過了5s,第一個物件還沒變為false狀態,那麼程式會報錯!(粒子系統為迴圈:會迴圈下去,只有一個預載入物件,不報錯,不迴圈時:等上一個變為false才能進行第二次,只有一個預載入物件,不報錯!)
如果limit Amount數量大於1,為10的話
limitFIFO勾選:永遠只有10個物件產生,當載入第11個物件時,如果前十個物件沒有一個active為false狀態,那麼程式會選擇不常用的那個,從而避免報錯!
limitFIFO不勾選:永遠只有10個物件產生,但是當載入第11個物件時,如果前十個物件沒有一個active為false狀態,那麼程式會報錯!
獲取緩衝池的方式:
SpawnPool pool = PoolManager.Pools[poolName];
SpawnPool pool = this.GetComponent<SpawnPool>();
2、PreRuntimePoolItem指令碼
程式碼為緩衝池預載入物件:這是PreRuntimePoolItem指令碼的作用,SpawnPool下的Options預設必須包含prefabName,並且懸掛PreRuntimePoolItem指令碼的物件和SpawnPool指令碼下的Options中的預設無關!
如果SpawnPool指令碼下已經有預設為Cube的物件,並且預載入數量為3,如果此時我們通過 PreRuntimePoolItem指令碼的作用,也為此緩衝池載入了2個預設為Cube的物件,那麼即使PreRuntimePoolItem指令碼的Do Not Reparent是否勾選,一旦程式進行Spawn獲取,那麼這些預載入物件都會被載入到掛有SpawnPool指令碼的物件下,如果Spawn50個,那麼就會依次啟用他們!Despawn On Start為true的不會算在內!
取緩衝池中的某一個物件
Transform cubePrefab = PoolManager.Pools["Shapes"].prefabs["Cube"]; Transform cubeinstance = PoolManager.Pools["Shapes"].Spawn(cubePrefab); cubeinstance.name = "Cube (Spawned By CreationExample.cs)";
專案例項:
首先就是Unity佈局:簡單搭建如下圖所示的場景。
指令碼程式碼:
using UnityEngine;
using System.Collections;
using PathologicalGames;
public class NewBehaviourScript : MonoBehaviour {
SpawnPool spawnPool;
PrefabPool refabPool;
public Transform myTran;
int count = 0;
bool isShoot = false;
public GameObject ShootCube;
void Start()
{
spawnPool = PoolManager.Pools["Shapes"];
refabPool = new PrefabPool(Resources.Load<Transform>("momo"));
intT();
}
void intT()
{
refabPool = new PrefabPool(Resources.Load<Transform>("momo"));
//預設初始化兩個Prefab
refabPool.preloadAmount =1 ;
//開啟限制
refabPool.limitInstances = true;
//關閉無限取Prefab
refabPool.limitFIFO = false;
//限制池子裡最大的Prefab數量
refabPool.limitAmount = 5;
//開啟自動清理池子
refabPool.cullDespawned = true;
//最終保留
refabPool.cullAbove = 10;
//多久清理一次
refabPool.cullDelay = 5;
//每次清理幾個
refabPool.cullMaxPerPass = 5;
//初始化記憶體池
spawnPool._perPrefabPoolOptions.Add(refabPool);
spawnPool.CreatePrefabPool(spawnPool._perPrefabPoolOptions[spawnPool.Count]);
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Transform momo = spawnPool.Spawn("momo");
momo.transform.position = myTran.position;
momo.transform.forward = myTran.forward;
ShootCube = momo.gameObject;
count++;
isShoot = true;
if (count>=5)
{
spawnPool.DespawnAll();
intT();
count = 0;
}
}
if (isShoot)
{
ShootCube.transform.position += new Vector3(0, 0, 5f);
}
}
}
效果展示:
通過建立緩衝池,並緩衝需要的物件,可以達到Objectpool 的效果,大大提高例項化的速度和節省記憶體空間。
下面的連線帶有Demo,可以直接使用。
緩衝池資源連線(已經修改匯入報錯的bug,大家可以放心使用,要不匯入高版本的Unity會報錯。):