? ?我們知道不限于工程 代碼之中 萬事之中 總是不斷尋找最好的方案 方法去解決同一樣事 當然 一個事物 這樣做可以 那樣做也行 但是我們所要的解決當然是基于一種理解下 的“最好” 比如 計算1+2+3+...100點結(jié)果 可以咯 你可以1+2=3 3+3 =6.费奸。社付。 對啊 結(jié)果是可以出來 但是我們所說的計算這個值絕對是有意義的計算 ?同樣的 在接觸一樣新事物的時候 我們可能為了實現(xiàn)功能 采取的就是1+2=3 3+3=6.八秃。荡灾。固惯。 隨著學(xué)習(xí)的深入與理解 自然而然會有新的方案 沒錯 在程序中 對象池就是解決重復(fù)利用同一資源而出現(xiàn)的新方案 是不是最好 我現(xiàn)在的知識有限 基于目前 我所能用的知識 卻是最好的?
? ? 什么是對象池?我們將需要重復(fù)利用對象存儲在一個池子中,當需要時在再次使用,而不是每次都實例化一個新的對象眷茁。 比如我們在工程中開槍射擊所用到的“子彈” 子彈射出去后 會消失 當再次射擊 是否重新生成呢? 可不可以把消失的子彈在此拿出來使用呢纵诞? 讓我們來試一下
? ?我們已子彈為模型-預(yù)設(shè)體來簡單講解一下
? ? 三個腳本
? 1.ObjectPool腳本 (保存對象到對象池與獲取對象)該腳本不需要掛在任何游戲?qū)ο笊?/h2>? 2.GameManager腳本(加載生成對象)第一次加載預(yù)設(shè)體 該腳本掛在一個空物體上就行
3.SphereObj腳本 (控制保存到對象池的對象)掛在預(yù)設(shè)體上
ObjectPool腳本 ()注意 此腳本不繼承MonoBehaviour 否則保存到對象池不成功 為什么? 留給讀者自己思考一下
usingSystem.Collections;
usingSystem.Collections.Generic;
using UnityEngine ;
public class ObjectPool{
// 創(chuàng)建單例
public static ObjectPool _instant ;
public static ObjectPool GetInstant()
{
if(_instant ==null)
{
_instant = new ObjectPool() ;
}
return _instant ;
}
// 對象池 就是一個字典 鍵是預(yù)設(shè)體的名字string類型 值是一個數(shù)組存儲GameObject的數(shù)組
private Dictionary<string,List<GameObject>> pool ;
// 字典需要初始化 在構(gòu)造方法中初始化
public ObjectPool(){
pool = new Dictionary<string,List<GameObject>>();
}
// 獲取對象 也是判斷對象池是否有這個對象?
public GameObject GetObj(string objName,Vector3pos,Quaternionqua))
{
? ? ?// 要獲取的對象?
? ? GameObject currentObj = null ;
// 根據(jù)鍵去判斷字典是否有這個對象 也是判斷對象池中是否有
if(pool.ContainsKey(objName))
? {
? ? ?// 對象池中有剩余 這句話的意思是說 當我射擊子彈很快很快或者需求子彈數(shù)大時 對象池存儲的對象是否夠 不夠就重新產(chǎn)生且添加到對象池
? ? ? if(pool[objName].count>0)
? {
? ? ? //獲取當前的對象
currentObj = pool[objName][0] ;
// ? 一個對象利用完取出去后 就要移除 ?為啥培遵?不是添加嗎 怎么還要從對象池中移除呢 我們說了浙芙。有時候需求子彈數(shù)很大 利用過的在一定時間內(nèi)就不能利用了 在后面的方法會在此添加進來
pool[objeName].Remove(currentObj) ;
}
}
// 如果對象為空 意思是第一次程序運行 還沒有一個產(chǎn)生 或者是需求大 對象池中沒有這么多 對象池就增加對象?
if(currentObj==Null)
{
//實例化對象
currentObj = GameManager.instance.Load(objName) ;
// 設(shè)置好對象的位置和角度 就是子彈的位置和角度
currentObj.transform.position = pos ;
currentObj.transform.rotation = qua ;
//激活對象?
currentObj.SetActive(true);
}
// 保存對象
public void SaveObj(GameObject go)
{
go.setActive(false) ;
//獲取對象池名稱
stringobjPoolName=go.name.Replace("(Clone)","");
Debug.Log(objPoolName);
//如果該類型的對象池存在
if(pool.ContainsKey(objPoolName))
{
//將對象保存到對象池
pool[objPoolName].Add(go);
}
else
{
//創(chuàng)建對象池,并保存對象到對象池
pool.Add(objPoolName,newList()
{
go
});
Debug.Log(objPoolName);
}
}
2.GameManager腳本
using System.Collections ;
using System.Collections.Generic ;
using UnityEngine ;
public class GameManager:MonBehaviour
{
// 單例
public static GameManager instance ;
void Awake()
{
? ?instance = this ;
}
// 加載并聲稱對象
public GameObject LoadObj(string objName)
{
? ? // 加載預(yù)設(shè)體 "Prefab"是創(chuàng)建的文件夾
? ?GameObject currentPrefab = Resources.LoAD<GameObject>("Prefab/"+objName);
return Instantite(currentPregab) ;
}
void Start()
{
}
// 這里我們模擬 每按下空格 產(chǎn)生一個子彈
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
ObjectPool.GetInstant(),GetObj("Sphere",Vector3.zero,Quaternion.identity);
}
}
}
SphereObj腳本 這個是加到對象池中對象所帶的腳本 這里我們用到協(xié)程 每2s去調(diào)用一次 讀者可以自己去試一下 看自己按空格的手速有多快 最多能有幾個預(yù)設(shè)體產(chǎn)生 手速越快 對象池能提供的不足 就會重新產(chǎn)生一個來補充 并添加到對象池
usingSystem.Collections;
usingSystem.Collections.Generic;
usingUnityEngine;
publicclassSphereObj:MonoBehaviour{
voidOnEnable()
{
StartCoroutine(Recycle());
}
IEnumeratorRecycle()
{
yieldreturnnewWaitForSeconds(2f);
ObjectPool.GetInstant().SaveObj(gameObject);
}
//Usethisforinitialization
voidStart(){
}
//Updateiscalledonceperframe
voidUpdate(){
}
}
ObjectPool腳本 ()注意 此腳本不繼承MonoBehaviour 否則保存到對象池不成功 為什么? 留給讀者自己思考一下
usingSystem.Collections;
usingSystem.Collections.Generic;
using UnityEngine ;
public class ObjectPool{
// 創(chuàng)建單例
public static ObjectPool _instant ;
public static ObjectPool GetInstant()
{
if(_instant ==null)
{
_instant = new ObjectPool() ;
}
return _instant ;
}
// 對象池 就是一個字典 鍵是預(yù)設(shè)體的名字string類型 值是一個數(shù)組存儲GameObject的數(shù)組
private Dictionary<string,List<GameObject>> pool ;
// 字典需要初始化 在構(gòu)造方法中初始化
public ObjectPool(){
pool = new Dictionary<string,List<GameObject>>();
}
// 獲取對象 也是判斷對象池是否有這個對象?
public GameObject GetObj(string objName,Vector3pos,Quaternionqua))
{
? ? ?// 要獲取的對象?
? ? GameObject currentObj = null ;
// 根據(jù)鍵去判斷字典是否有這個對象 也是判斷對象池中是否有
if(pool.ContainsKey(objName))
? {
? ? ?// 對象池中有剩余 這句話的意思是說 當我射擊子彈很快很快或者需求子彈數(shù)大時 對象池存儲的對象是否夠 不夠就重新產(chǎn)生且添加到對象池
? ? ? if(pool[objName].count>0)
? {
? ? ? //獲取當前的對象
currentObj = pool[objName][0] ;
// ? 一個對象利用完取出去后 就要移除 ?為啥培遵?不是添加嗎 怎么還要從對象池中移除呢 我們說了浙芙。有時候需求子彈數(shù)很大 利用過的在一定時間內(nèi)就不能利用了 在后面的方法會在此添加進來
pool[objeName].Remove(currentObj) ;
}
}
// 如果對象為空 意思是第一次程序運行 還沒有一個產(chǎn)生 或者是需求大 對象池中沒有這么多 對象池就增加對象?
if(currentObj==Null)
{
//實例化對象
currentObj = GameManager.instance.Load(objName) ;
// 設(shè)置好對象的位置和角度 就是子彈的位置和角度
currentObj.transform.position = pos ;
currentObj.transform.rotation = qua ;
//激活對象?
currentObj.SetActive(true);
}
// 保存對象
public void SaveObj(GameObject go)
{
go.setActive(false) ;
//獲取對象池名稱
stringobjPoolName=go.name.Replace("(Clone)","");
Debug.Log(objPoolName);
//如果該類型的對象池存在
if(pool.ContainsKey(objPoolName))
{
//將對象保存到對象池
pool[objPoolName].Add(go);
}
else
{
//創(chuàng)建對象池,并保存對象到對象池
pool.Add(objPoolName,newList()
{
go
});
Debug.Log(objPoolName);
}
}
2.GameManager腳本
using System.Collections ;
using System.Collections.Generic ;
using UnityEngine ;
public class GameManager:MonBehaviour
{
// 單例
public static GameManager instance ;
void Awake()
{
? ?instance = this ;
}
// 加載并聲稱對象
public GameObject LoadObj(string objName)
{
? ? // 加載預(yù)設(shè)體 "Prefab"是創(chuàng)建的文件夾
? ?GameObject currentPrefab = Resources.LoAD<GameObject>("Prefab/"+objName);
return Instantite(currentPregab) ;
}
void Start()
{
}
// 這里我們模擬 每按下空格 產(chǎn)生一個子彈
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
ObjectPool.GetInstant(),GetObj("Sphere",Vector3.zero,Quaternion.identity);
}
}
}
SphereObj腳本 這個是加到對象池中對象所帶的腳本 這里我們用到協(xié)程 每2s去調(diào)用一次 讀者可以自己去試一下 看自己按空格的手速有多快 最多能有幾個預(yù)設(shè)體產(chǎn)生 手速越快 對象池能提供的不足 就會重新產(chǎn)生一個來補充 并添加到對象池
usingSystem.Collections;
usingSystem.Collections.Generic;
usingUnityEngine;
publicclassSphereObj:MonoBehaviour{
voidOnEnable()
{
StartCoroutine(Recycle());
}
IEnumeratorRecycle()
{
yieldreturnnewWaitForSeconds(2f);
ObjectPool.GetInstant().SaveObj(gameObject);
}
//Usethisforinitialization
voidStart(){
}
//Updateiscalledonceperframe
voidUpdate(){
}
}