您的位置:首页 > 移动开发 > Unity3D

Unity 对象池简单使用

2016-05-23 12:28 543 查看
在 unity 中,我们会遇到一种情况,就是需要不断的创建一些对象,然后又要不断的销毁这些对象。例如:射击游戏里的子弹,这需要我们不断的大量产生,又要大量的销毁。

我们知道 unity 实例化一个 GameObject,它就会占用一定内存,而当他被 Destroy 时,其实它并不会立即销毁,还存在内存中,而是会等到下一次 垃圾回收(GC)时才会真正的销毁。

所以在这个过程中就会出现一个问题,当我们需要大量创建一些对象,又要销毁对象时,游戏就有可能因为资源不足而卡顿一下。这在游戏中是绝对不允许出现的情况。为了解决这样的问题,我们需要事先把这些对象创建好,使用的时候在来调用这些对象。就要用到一个对象池的概念。

我们做一个简单的例子来看一下效果。打开unity新建一个3D工程。在场景中新建一个cube,然后把它作为prefab删掉面板上的cube,在新建一个空物体,我们要让它作为要生产的物体的父物体。新建一个SimplePool脚本添加给摄像机

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class SimplePool : MonoBehaviour {
public Transform parent;  //父物体
public GameObject cube;   //要生产的对象
public int poolSize;    //容量池的容量大小
private List<GameObject> poolList = new List<GameObject>();   //用来存放生产的对象

/// <summary>
/// 创建对象
/// </summary>
/// <param name="count">创建的数量</param>
/// <returns></returns>
public List<GameObject> CreateObject (int count)
{
//用来接收创建的对象列表
List<GameObject> tempObject = new List<GameObject>();
//循环创建
for (int i = 0; i < count; i ++)
{
//接收单个对象
GameObject go = Instantiate(cube);
//默认设置不显示
go.SetActive(false);
//设置父物体
go.transform.parent = parent;
//添加到临时列表
tempObject.Add(go);
}
//把创建好的对象全部添加到对象列表中
poolList.AddRange(tempObject);
return tempObject;
}

/// <summary>
/// 得到对象
/// </summary>
/// <param name="count">要得到的数量</param>
/// <returns></returns>
public List<GameObject> GetObject (int count)
{
//返回所有 对象列表 poolList 中的未激活的对象
List<GameObject> tempObject = poolList.FindAll(g => !g.activeSelf);
//如果需要得到的数量大于未激活的数量
if (count > tempObject.Count)
{
//创建不足的对象
List<GameObject> newTempObject = CreateObject(count - tempObject.Count);
//把创建的不足的对象添加到临时对象列表
tempObject.AddRange(newTempObject);
//循环把需要得到的对象设为显示
foreach (var gg in tempObject)
{
gg.SetActive(true);
}
return tempObject;
}
//如果需要的数量不大于对象列表中的未激活的对象  直接返回临时对象列表
else
{
return tempObject;
}
}

/// <summary>
/// 销毁对象
/// </summary>
/// <param name="destroyGo">要销毁的列表</param>
public void DestroyObject (List<GameObject> destroyGo)
{
//循环设置为不显示
foreach (GameObject gg in destroyGo)
{
gg.SetActive(false);
}
}

}


然后再写一个 TestPool 脚本给摄像机添加:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class TestPool : MonoBehaviour {
public GameObject cube;   //要创建的对象
public Transform parent;   //父物体
public SimplePool simplePool;
public int loopCount;   //循环次数
List<GameObject> testList = new List<GameObject>();   //存放创建的对象

// Use this for initialization
void Start () {
//得到现在的系统时间作为开始时间
System.DateTime startTime = System.DateTime.Now;
TestCreate(loopCount, simplePool.poolSize);
TestDestroy(testList);
System.DateTime endTime = System.DateTime.Now;
//输出调用方法所用的时长
Debug.Log("不用对象池使用的时长为:" + (endTime - startTime).TotalMilliseconds + ".ms");

System.DateTime startTime2 = System.DateTime.Now;
TestPoolScripts(loopCount, simplePool.poolSize);
System.DateTime endTime2 = System.DateTime.Now;
//输出调用方法所用的时长
Debug.Log("使用对象池使用的时长为:" + (endTime2 - startTime2).TotalMilliseconds + ".ms");
}

/// <summary>
/// 测试方法,测试同时创建 n 个对象
/// </summary>
/// /// <param name="loopCount">循环次数</param>
/// <param name="count">每次生成的数量</param>
void TestCreate (int loopCount, int count)
{
for (int i = 0; i < loopCount; i ++)
{
for (int j = 0; j < count; j++)
{
GameObject go = Instantiate(cube);
go.transform.parent = parent;
testList.Add(go);
}
}

}

/// <summary>
/// 销毁独享
/// </summary>
/// <param name="destroyGO">要销毁的列表</param>
void TestDestroy (List<GameObject> destroyGO)
{
for (int i = 0; i < destroyGO.Count; i ++)
{
Destroy(destroyGO[i]);
}
}

/// <summary>
/// 使用对象池
/// </summary>
/// /// <param name="loopCount">循环次数</param>
/// <param name="count">每次生成的数量</param>
void TestPoolScripts (int loopCount, int count)
{
for (int i = 0; i < loopCount; i++)
{
List<GameObject> t = simplePool.GetObject(count);
simplePool.DestroyObject(t);
}
}

}


最后设置好相应的参数:



然后运行程序 ;



我们可以看见差距是非常大的,差不多有8倍之大。

最后,我写的那个还只是简单的对象池脚本,更复杂的我目前也不会,但是,现在这个应该也能在平时练习中进行使用,大家可以把它当作模板进行适当的修改,就可以修改成自己的版本了。

工程地址:http://pan.baidu.com/s/1i49XsG1 密码:wa3g

本博客用作新手学习讨论,如有不好或错误的地方也请指出来,谢谢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  unity 对象 内存