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

unity 对象池

2016-01-29 15:39 399 查看
对象池背后的理念其实是非常简单的。我们将对象存储在一个池子中,当需要时在再次使用,而不是每次都实例化一个新的对象。池的最重要的特性,也就是对象池设计模式的本质是允许我们获取一个“新的”对象而不管它真的是一个新的对象还是循环使用的对象。

这是网上找的解释。
我们游戏中大量用到了对象池。
今天看了下对象池底层的代码。下面这篇文章写得挺好

http://www.cnblogs.com/mezero/p/3955130.html

废话不多说,上我们自己的对象池代码。

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

// 清0操作由调用者负责编写
// 提供对非unity对象的缓存,即逻辑对象缓存
// 注意必须是class哈
// 提供接口 IObjectClear, Release时自动调用

public interface IObjectClear
{
void Clear();
}

public class ObjectPool
{
class ObjectGroup
{
public Stack<object> m_freeStack;
public int m_iMaxNum;  // 最大数量,为0表示不限制,否则超过最大数量,Release时直接delete

public ObjectGroup()
{
m_freeStack = new Stack<object>();
m_iMaxNum = 0;
}
}

Dictionary< Type,   ObjectGroup > m_typeDic;
object m_locker = new object();
bool m_bIsthreadSafe;

public ObjectPool(bool bIsthreadSafe = false)
{
m_typeDic = new Dictionary< Type,   ObjectGroup >();
m_bIsthreadSafe = bIsthreadSafe;
}

public void Register<T>( int iInitNum, int iMaxNum = 0 ) where T : class, new()
{
if (iInitNum < 0)
{
throw new ArgumentException("Init num < 0");
}

ObjectGroup group = null;
if ( m_typeDic.TryGetValue(typeof(T), out group) )
{
// 已存在
return;
}

group = new ObjectGroup();
group.m_iMaxNum = iMaxNum;

if (iInitNum > 0)
{
for (int i = 0; i < iInitNum; i++)
{
T obj = new T();
if (m_bIsthreadSafe)
{
lock (m_locker)
{
group.m_freeStack.Push(obj);
}
}
else
{
group.m_freeStack.Push(obj);
}
}
}

m_typeDic[typeof(T)] = group;
}

public T Get<T>() where T : class, new()
{
ObjectGroup group = null;
if (!m_typeDic.TryGetValue(typeof(T), out group))
{
Register<T>(1);
return Get<T>();
}

T obj = null;
if (0 == group.m_freeStack.Count)
{
obj = new T();
}else
{
if (m_bIsthreadSafe)
{
lock (m_locker)
{
obj = group.m_freeStack.Pop() as T;
}
}
else
{
obj = group.m_freeStack.Pop() as T;
}
}

return obj;
}

public void Release<T>(T obj) where T : class, new()
{
if (null == obj)
{
throw new ArgumentException("obj is null!!");
}

ObjectGroup group = null;
Type t = ((object)obj).GetType();
if (!m_typeDic.TryGetValue(t, out group))
{
throw new ArgumentException("obj's type is not registered!");
}

if (obj is IObjectClear)
{
((IObjectClear)obj).Clear();
}

if (group.m_iMaxNum > 0 && group.m_freeStack.Count >= group.m_iMaxNum)
{
if (obj is IDisposable)
{
((IDisposable)obj).Dispose();
}

obj = null;
System.GC.Collect();
}
else
{
// add to free list
if (m_bIsthreadSafe)
{
lock (m_locker)
{
group.m_freeStack.Push(obj);
}
}
else
{
group.m_freeStack.Push(obj);
}
}
}

private void _DestroyGroup( ObjectGroup group )
{
object obj = null;
while (group.m_freeStack.Count > 0)
{
if (m_bIsthreadSafe)
{
lock (m_locker)
{
obj = group.m_freeStack.Pop();
}
}
else
{
obj = group.m_freeStack.Pop();
}

if (obj is IDisposable)
{
((IDisposable)obj).Dispose();
}
obj = null;
}
if (m_bIsthreadSafe)
{
lock (m_locker)
{
group.m_freeStack.Clear();
}
}
else
{
group.m_freeStack.Clear();
}
}

public void DestroyType<T>() where T : class, new()
{
ObjectGroup group = null;
if (!m_typeDic.TryGetValue(typeof(T), out group))
{
throw new ArgumentException("obj's type is not registered!");
}

this._DestroyGroup(group);
}

// destroy所有实列
public void DestroyAll()
{
foreach (var it in m_typeDic)
{
ObjectGroup group = it.Value;
this._DestroyGroup(group);
group = null;
}

m_typeDic.Clear();

System.GC.Collect();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: