最近忙得不可开交,也不知道发点什么,正好想到之前背包被很多人吐槽,怎么没对象池呢?
那我就加个对象池上去吧。比较简单,只供参考。
效果展示:
(解释:背包三个tab,每个都一样,按键盘x键随机拾取物品,右键点击消耗一个物品)
首先,加一个右键点击消耗物品吧,创建一个脚本UConsume.cs
代码其实和拖拽类似,如下:
usingUnityEngine;
usingSystem.Collections;
usingUnityEngine.UI;
usingUnityEngine.EventSystems;
publicclass UConsume : MonoBehaviour,IPointerDownHandler,IPointerUpHandler {
GameObject InitCanvas = null;
GameObject item;
Text index; //Item数量
intIndexInt = 0; //数量转换为INT型
stringIndexStr = ""; //数量转换为STRING型
voidStart () {
InitCanvas = GameObject.Find ("Beibao").transform.Find ("InitCanvas").gameObject;
}
publicvoid OnPointerDown(PointerEventData eventData) { //鼠标按下
if(Input.GetMouseButtonDown (1)) {
//transform.localScale=new Vector3(0.7f,0.7f,0.7f);
index = transform.GetChild(0).GetComponent<Text>();
IndexInt = int.Parse(index.text);
if(IndexInt != 1) {
IndexInt -= 1;
IndexStr = IndexInt.ToString ();
index.text = IndexStr;
}else{
item = eventData.pointerCurrentRaycast.gameObject;
Destroy (item);
}
}
}
publicvoid OnPointerUp(PointerEventData eventData) { //鼠标放开
if(Input.GetMouseButtonUp (1)) {
//transform.localScale = new Vector3 (1f, 1f, 1f);
}
}
}
看过我之前背包的相信一看就懂,没什么难度,无非就是判断一下数字减去,最后destroy掉item而已,我不做过多陈述了。
然后,来写对象池吧!
创建一个脚本,名为ObjectPool.cs
对象池主要部分无非就两个,1、取,2、存。然后不用的设置为SetActive(false);用的设置为true;
代码如下:
usingUnityEngine;
usingSystem.Collections;
usingSystem.Collections.Generic;
publicclass ObjectPool : MonoBehaviour {
privatestatic Dictionary<string,ArrayList> pool = newDictionary<string, ArrayList>{ };
// Use this for initialization
voidStart () {
}
publicstatic Object Get(stringprefabName,Vector3 position,Quaternion rotation){
stringkey = prefabName + "(Clone)";
Object o;
if(pool.ContainsKey (key) && pool [key].Count > 0) {
ArrayList list = pool [key];
o = list [0] asObject;
list.RemoveAt (0);
//初始化相关状态
(oasGameObject).SetActive (true);
(oasGameObject).transform.position = position;
(oasGameObject).transform.rotation = rotation;
}else{
o = Instantiate (Resources.Load ("prefabs/"+ prefabName), position, rotation);
}
returno;
}
publicstatic Object Return(GameObject o){
stringkey = o.name;
if(pool.ContainsKey (key)) {
ArrayList list = pool [key];
list.Add (o);
}else{
pool [key] = newArrayList (){ o };
}
o.SetActive (false);
returno;
}
}
首先来看在取这个方法里,定义了字符串prefabName,还有position\rotation
prefabName是直接预制体的名称,调用时使用。其中需要判断的是是否池内有对象,没有就实例化一个,有就取池中的对象
然后存这个方法,这个简单,只是单纯的存在动态数组中然后设置为false
对象池写了,我们需要来用才行。
我写的背包主要有两部分使用,第一是随机拾取物品的时候,第二是右键点击消耗的地方
之前是这句话:item = Instantiate (instantiate, transform.position, transform.rotation) as GameObject;//获取预制物体
现在替换成这一句:item = ObjectPool.Get("UItem",transform.position, transform.rotation) as GameObject;
现在替换成这一句:item = ObjectPool.Get("UItem",transform.position, transform.rotation) as GameObject;
存的话写一个协程:
IEnumerator ReturnToPool(){
yieldreturn new WaitForSeconds (0f);
ObjectPool.Return (item);
}
在之前destroy的地方调用该协程就可以了。
ok,到此结束。效果很不错奥,看上面的展示吧!
奥,对了,注意一点,Item预制体的字对象text要把Raycast Target属性勾选去掉,为的就是不被射线检测到。