UGUI背包(对象池)

来源:互联网 发布:php 安装 sendmail 编辑:程序博客网 时间:2024/06/05 04:54
最近忙得不可开交,也不知道发点什么,正好想到之前背包被很多人吐槽,怎么没对象池呢?
那我就加个对象池上去吧。比较简单,只供参考。
效果展示:
(解释:背包三个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;
存的话写一个协程:
IEnumerator ReturnToPool(){                yieldreturn new WaitForSeconds (0f);                ObjectPool.Return (item);        }


在之前destroy的地方调用该协程就可以了。

ok,到此结束。效果很不错奥,看上面的展示吧!

奥,对了,注意一点,Item预制体的字对象text要把Raycast Target属性勾选去掉,为的就是不被射线检测到。
 
0 0
原创粉丝点击