开发者社区> 二哈卖豆腐> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Unity中的通用对象池

简介: 从使用者视角给出需求首先,我所希望的这个内存池的代码最后使用应该是这样的。 Bullet a = Pool.Take(); //从池中立刻获取一个单元,如果单元不存在,则它需要为我立刻创建出来。返回一个Bullet脚本以便于后续控制。
+关注继续查看

从使用者视角给出需求
首先,我所希望的这个内存池的代码最后使用应该是这样的。

Bullet a = Pool.Take(); //从池中立刻获取一个单元,如果单元不存在,则它需要为我立刻创建出来。返回一个Bullet脚本以便于后续控制。注意这里使用泛型,也就是说它应该可以兼容任意的脚本类型。
Pool.restore(a);//当使用完成Bullet之后,我可以使用此方法回收这个对象。注意这里实际上我已经把Bullet这个组件的回收等同于某个GameObject(这里是子弹的GameObject)的回收。
  使用上就差不多是这样了,希望可以有极其简单的方法来进行获取和回收操作。
内存池单元结构
最简单的内存池形式,差不多就是两个List,一个处于工作状态,一个处于闲置状态。工作完毕的对象被移动到闲置状态列表,以便于后续的再次获取和利用,形成一个循环。我们这里也会设计一个结构来管理这两个List,用于处理同一类的对象。
  接下来是考虑内存池单元的形式,我们考虑到内存池单元要尽可能容易扩展,就是可以兼容任意数据类型,也就是说,假设我们的内存池单元定为Pool_Unit,那么它不能影响后续继承它的类型,那我们最好使用接口,一旦使用类,那么就已经无法兼容Unity组件,因为我们自定义的Unity组件全部继承自MonoBehavior。接下来考虑这个内存单元该具有的功能,差不多有两个基本功能要有:

restore();//自己主动回收,为了方便后续调用,回收操作最好自己就有。
getState();//获取状态,这里是指获取当前是处于工作状态还是闲置状态,也是一个标记,用于后续快速判断。因为接口中无法存储单元,这里使用变通的方法,就是留给实现去处理,接口中要求具体实现需要提供一个状态标记。
  综合内存池单元和状态标记,给出如下代码:
namespace AndrewBox.Pool
{
public interface Pool_Unit
{
Pool_UnitState state();
void setParentList(object parentList);
void restore();
}
public enum Pool_Type
{
Idle,
Work
}
public class Pool_UnitState
{
public Pool_Type InPool
{
get;
set;
}
}
}
单元组结构
接下来考虑单元组,也就是前面所说的针对某一类的单元进行管理的结构。它内部有两个列表,一个工作,一个闲置,单元在工作和闲置之间转换循环。它应该具有以下功能:

创建新单元;使用抽象方法,不限制具体创建方法。对于Unity而言,可能需要从Prefab克隆,那么最好有方法可以从指定的Prefab模板复制创建。
获取单元;从闲置表中查找,找不到则创建。
回收单元;将其子单元进行回收。
  综合单元组结构的功能,给出如下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AndrewBox.Pool
{
public abstract class Pool_UnitList where T:class,Pool_Unit
{
protected object m_template;
protected List m_idleList;
protected List m_workList;
protected int m_createdNum = 0;
public Pool_UnitList()
{
m_idleList = new List();
m_workList = new List();
}

///
/// 获取一个闲置的单元,如果不存在则创建一个新的
///
/// 闲置单元
public virtual T takeUnit() where UT:T
{
T unit;
if (m_idleList.Count > 0)
{
unit = m_idleList[0];
m_idleList.RemoveAt(0);
}
else
{
unit = createNewUnit();
unit.setParentList(this);
m_createdNum++;
}
m_workList.Add(unit);
unit.state().InPool = Pool_Type.Work;
OnUnitChangePool(unit);
return unit;
}
///
/// 归还某个单元
///
/// 单元
public virtual void restoreUnit(T unit)
{
if (unit!=null && unit.state().InPool == Pool_Type.Work)
{
m_workList.Remove(unit);
m_idleList.Add(unit);
unit.state().InPool = Pool_Type.Idle;
OnUnitChangePool(unit);
}
}
///
/// 设置模板
///
///
///
public void setTemplate(object template)
{
m_template = template;
}
protected abstract void OnUnitChangePool(T unit);
protected abstract T createNewUnit() where UT : T;
}
}
更多unity2018的功能介绍请到paws3d爪爪学院查找。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
游戏开发初级之游戏对象和组件关系(Unity3D)
Unity是一个基于组件的游戏引擎。本文将解释这是什么以及如何有效地使用它。
152 0
Unity中的多线程编程
Unity本身并不建议使用线程,推荐用协程来代替,但是很多情况下,协程并不能实现想要的功能,因此,Unity的多线程开发还是需要学习的。
237 0
关于Unity 2018的实体组件系统(通用名称ECS)
将介绍如何在Unity上使用实体组件系统(通常称为ECS)。这次的内容是Unity提供的ECS API的基本用法,一个小应用程序和并行化。它不包括与Unity的GameObject / Component的合作,以及实际使用。
1736 0
Unity中的平移 缩放 旋转
Unity中的平移 缩放 旋转 1.最近想实现Unity中的平移 缩放 旋转功能, 类似于Unity编辑器状态下的效果.尝试了好几个方式,效果都有瑕疵,网友们谁有好的实现方式,请教我. 下面是我的一种实现方式: using System.
1993 0
Unity中的网格与材质球合并
http://blog.csdn.net/dardgen2015/article/details/51517860
1240 0
Unity中的Path对应各平台中的Path
IOS:Application.dataPath :                    Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/DataApplication.
610 0
使用Unity做类的增强
我们已经实现了用户注册功能,现在想增加日志记录功能。具体来讲就是在用户注册前后,分别输出一条日志。
1341 0
使用Unity做类的增强(续)
我们已经实现了用户注册功能,现在想增加日志记录功能。具体来讲就是在用户注册前后,分别输出一条日志。
1249 0
112
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载