博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Unity中的通用对象池
阅读量:7260 次
发布时间:2019-06-29

本文共 2419 字,大约阅读时间需要 8 分钟。

从使用者视角给出需求

首先,我所希望的这个内存池的代码最后使用应该是这样的。

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爪爪学院查找。

转载地址:http://fqkdm.baihongyu.com/

你可能感兴趣的文章
折纸带
查看>>
真实世界的Windows Azure:使用Windows Azure社交游戏开发商享有更低的成本和改进的扩展性...
查看>>
云时代的海外扩张
查看>>
hdu1078 记忆化搜索
查看>>
2017 清北济南考前刷题Day 3 afternoon
查看>>
洛谷P2326 AKN’s PPAP
查看>>
WERKZEUG之WSGI阅读笔记
查看>>
一个初学者C#编写帐号密码保存软件的思考过程
查看>>
【软件解决】解决VS环境中出现虚线问题
查看>>
laravel 实现增 与查
查看>>
一种排序
查看>>
Linux实战教学笔记44:NoSQL数据库开篇之应用指南
查看>>
springmvc(2)处理器设配器和映射器
查看>>
PAT 1003
查看>>
switch gnome-terminal tabs
查看>>
怎样理解Functor与Monad
查看>>
DRF教程4-视图集和路由类
查看>>
javascript向上滚动(放上鼠标就停)
查看>>
python的编码问题
查看>>
获取下拉框的值
查看>>