真正学懂一个知识的时候是要传授给别人这个知识的时候让对方也能轻而易举的理解。
遇到需要频繁加载和销毁的游戏对象(例如子弹,特效,贴图),使用对象池可以节约内存的开销,尤其对于移动设备尤为显著。
所以,研究了一天的对象池。 其中有半天没找到对象,徘徊在找对象的路上。最后发现是把对象的名字找错了。
首先 得有个对象池。其实本质就是一个列表(ArrayList)(还有很多,堆栈 队列呀 你玩的花咋样都行,能存东西就行) 在程序运行开始把prefebs加载进去,但是active为false,用的时候拿出来激活就好, 。要销毁prefebs的时候 就把prefebs的active设置成false 再把它弄回列表里。
using System.Collections;using System.Collections.Generic;using UnityEngine;
public class Pool : MonoBehaviour { private static Dictionarydic = new Dictionary();
// 字典 key等于要存的预制体的名字 value是一个Arraylist列表
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public static GameObject Get(string key, Vector3 position, Quaternion rotation)
{
print(key); //用于测试的标志位
GameObject go; //临时变量
string GameObiectName = key + "(Clone)"; //key获取的是prefebs的名字 但实例化的时候会加上(Clone);
print(GameObiectName);//测试标志
if (dic.ContainsKey(GameObiectName)&& dic[GameObiectName].Count>0) //如果能取到pefebs的Key 并且 value的list数据大于0
{
print("第一位");
ArrayList list = dic[GameObiectName]; // 获取列表
go = list[0] as GameObject;
list.RemoveAt(0); //将预制体移出列表
go.SetActive(true); //设置预制体为激活状态
go.transform.position = position;
go.transform.rotation = rotation;
}
else
{
print("第二位");
go = Instantiate(Resources.Load("Sphere"), position, rotation) as GameObject; //池中没有东西时候会执行这一句来创建预制体
}
return go;
}
public static void Return(GameObject g) {
string key = g.name;
print(key);
if (dic.ContainsKey(key)) //如果有这个Key 就把这个物体放进这个Value(List)里
{
print("已经有列表,添加进去");
dic[key].Add(g);
}
else {
print("创建一个列表");
dic[key] = new ArrayList() { g }; //创建这个键值。(第一次调用)
}
g.SetActive(false);
}
}
有了对象池就可以在别处使用了。就是执行对象池的get方法就可以拿出来一个对象 return方法就可以把对象放回去。代替了load和destroy
public class Main : MonoBehaviour {
RaycastHit Hit; //射线碰撞监测到的点
public GameObject sphere; //预制体是一个sphere
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); //将鼠标点击的屏幕坐标空间转换为射线
Debug.DrawLine(ray.origin, Hit.point, Color.red); //绘制射线
if (Input.GetMouseButtonDown(0))
{
if (Physics.Raycast(ray, out Hit, 1000f))
{
Pool.Get(sphere.name, Hit.point, Hit.transform.rotation); //调用对象池中的Get方法获取返回。返回是将prefebs的active设置成true
//传入位置参数和旋转角度。
// print(Hit.transform.name);
}
}
}
}
return方法写在预制体上面,根据具体需求到点了就执行就可以了
private float time;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
time += Time.deltaTime; //计时器
if (time > 3)
{
Pool.Return(this.gameObject); //调用对象池中的Return方法 将预制体设置为false;
time= 0;
}
// StartCoroutine(dest());
}
//IEnumerator dest() {
// yield return new WaitForSeconds(3f);
// Pool.Return(this.transform.gameObject);
//}
}
网友评论