前言:警告!这可能是坨屎,空闲时间写成,仅作娱乐

在Unity中生成或销毁一个物体会占用较大的资源,如果是制作FPS射击游戏,子弹生成更是雪上加霜。所以我自己写了一个PoolManager,不能和网上的各位大佬作比较,仅作娱乐。

该实例主要是通过一个PoolUtil对象作为一类游戏的对象池,再通过PoolManager来管理诸多PoolUtil。

PoolUtil的功能,主要还是靠队列实现的。调用者每次”销毁“物体时,将物体放入池中,并隐藏起来。再次生成时,查看池中有无待用的物体,若有则直接显示出来。若无,则继续生成新物体。

public class PoolUtil:MonoBehaviour
{
public GameObject prefab;
public string poolName;
public Queue<GameObject> queue; /// <summary>
/// 初始化方法
/// </summary>
/// <param name="prefab">要生成的预制体</param>
/// <param name="poolName">池名</param>
/// <param name="preLoadCount">预加载的数量</param>
public void Init(GameObject prefab,string poolName, int preLoadCount)
{
queue = new Queue<GameObject>();
this.prefab = prefab;
gameObject.name = "PoolUtil_" + poolName;
this.poolName = poolName;
PreLoad(preLoadCount);
} /// <summary>
/// 预加载方法
/// </summary>
/// <param name="preLoadCount">预加载数量</param>
void PreLoad(int preLoadCount)
{
for (int i = preLoadCount; i > 0; i--)
{
GameObject newObj = Instantiate(prefab);
newObj.SetActive(false);
SetGameObject(newObj.transform,GameObject.Find("Canvas").transform);
queue.Enqueue(newObj);
}
} /// <summary>
/// 生成方法
/// </summary>
/// <param name="pos">生成位置</param>
/// <param name="rotation">生成时的旋转度数</param>
/// <param name="parent">生成物体的父物体</param>
/// <returns>返回生成的物体</returns>
public GameObject Spawn(Vector3 pos,Quaternion rotation,Transform parent)
{
GameObject newObj = null;
if (queue.Count!=0)
{
newObj = queue.Dequeue();
newObj.SetActive(true);
SetGameObject(newObj.transform, pos, rotation, parent);
return newObj;
} newObj = Instantiate(prefab);
SetGameObject(newObj.transform, pos, rotation, parent);
return newObj;
} /// <summary>
/// ”销毁“物体
/// </summary>
/// <param name="obj">要销毁的目标游戏物体</param>
public void DeSpawn(GameObject obj)
{
obj.SetActive(false);
queue.Enqueue(obj);
} /// <summary>
/// 设置物体的位置旋转和父物体
/// </summary>
/// <param name="obj"></param>
/// <param name="pos"></param>
/// <param name="rotation"></param>
/// <param name="parent"></param>
private void SetGameObject(Transform obj,Vector3 pos,Quaternion rotation,Transform parent)
{
obj.SetParent(parent);
obj.localRotation = rotation;
obj.localPosition = pos;
}
/// <summary>
/// 下面三个是重载
/// </summary>
/// <param name="obj"></param>
/// <param name="rotation"></param>
/// <param name="parent"></param>
private void SetGameObject(Transform obj,Quaternion rotation,Transform parent)
{
obj.SetParent(parent);
obj.localRotation = rotation;
obj.localPosition = Vector3.zero;
}
private void SetGameObject(Transform obj,Vector3 pos,Transform parent)
{
obj.SetParent(parent);
obj.localRotation = Quaternion.identity;
obj.localPosition = pos;
}
private void SetGameObject(Transform obj,Transform parent)
{
obj.SetParent(parent);
obj.localRotation = Quaternion.identity;
obj.localPosition = Vector3.zero;
}
}
public class PoolManager : MonoBehaviour
{
private Dictionary<string, PoolUtil> poolDic;
public static PoolManager Instance; private void Start()
{
//单例模式好调用
Instance = this;
DontDestroyOnLoad(gameObject);
poolDic = new Dictionary<string, PoolUtil>();
} /// <summary>
/// 暴露给调用者的生成方法
/// </summary>
/// <param name="needPool">是否需要生成池</param>
/// <param name="prefab">要生成的物体</param>
/// <param name="pos">位置</param>
/// <param name="rotation">旋转</param>
/// <param name="parent">父物体</param>
public void CreateObj(bool needPool,GameObject prefab,Vector3 pos,Quaternion rotation,Transform parent)
{
if (needPool)//需要对象池
{
QueryPool(prefab).Spawn(pos,rotation,GameObject.Find("Canvas").transform);
}
else
{
GameObject temp = Instantiate(prefab);
temp.transform.SetParent(parent);
temp.transform.localPosition = pos;
temp.transform.localRotation = rotation;
}
} /// <summary>
/// 暴露给调用者的“销毁”方法
/// </summary>
/// <param name="deleteObj">销毁的目标物体</param>
public void DestroyObj(GameObject deleteObj)
{
QueryPool(deleteObj).DeSpawn(deleteObj);
} /// <summary>
/// 查询字典中有无该物体的池
/// </summary>
/// <param name="prefab">目标物体</param>
/// <returns>返回该物体的池</returns>
private PoolUtil QueryPool(GameObject prefab)
{
string key = prefab.name.Split('(')[0];
if (!poolDic.ContainsKey(key))
{
CreatePool(prefab);
}
return poolDic[key];
} /// <summary>
/// 创建目标物体的池
/// </summary>
/// <param name="prefab">目标物体</param>
private void CreatePool(GameObject prefab)
{
GameObject obj = new GameObject();
PoolUtil util = obj.AddComponent<PoolUtil>();
util.Init(prefab,prefab.name,1);
poolDic.Add(prefab.name, util);
obj.transform.SetParent(transform);
}
}

PoolManager主要通过一个池的字典,每次创建物体时,根据调用者的实际情况,判断是否需要创建池?然后加入到字典。这样,调用者再次创建时,即可查找指定池,并将目标物体放入该池中,方便复用。

下面是测试代码

public class TestPool : MonoBehaviour
{
public GameObject prefab;
public void ButtonFunc()
{
PoolManager.Instance.CreateObj(true,prefab,Vector3.zero,Quaternion.identity,GameObject.Find("Canvas").transform);
}
}

在Unity新建一个Canvas,将该代码添加到Canvas上。新建一张图片改成红色,然后拖拽到Assets下作为预制体。为测试”销毁“功能,另外新建脚本:

public class ImageFunc : MonoBehaviour
{
private float timer = 0;
private float interval = 5f;
void OnEnable()
{
timer = Time.time;
} // Update is called once per frame
void Update()
{
if(Time.time-timer>=interval)
{
PoolManager.Instance.DestroyObj(this.gameObject);
}
}
}

此代码作为预制体自身的脚本,生成时就开始计时,到达五秒后销毁自己。再次生成时会重置时间为当前时间。

关于该对象池的优化方向:

1.可以从Hierachy面板上点击PoolUtil,观察其Insperctor面板,可查询场景中有哪些物体归这个池管?

2.添加功能销毁池本身,如果长时间不再新生成该对象,应该逐步销毁池中物体,直至池中物体数量归0,然后销毁池

目前就想到这么多了

Unity实现”对象池管理器“的更多相关文章

  1. Unity——对象池管理

    Unity对象池管理 一.Demo展示 二.逻辑 在游戏中会出现大量重复的物体需要频繁的创建和销毁:比如子弹,敌人,成就列表的格子等: 频繁的创建删除物体会造成很大的开销,像这种大量创建重复且非持续性 ...

  2. Unity中对象池的使用

    unity中用到大量重复的物体,例如发射的子弹,可以引入对象池来管理,优化内存. 对象池使用的基本思路是: 将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用.恰当地使用对象池,可以在 ...

  3. cocos2D-x 3.5 引擎解析之--引用计数(Ref),自己主动释放池(PoolManager),自己主动释放池管理器( AutoreleasePool)

    #include <CCRef.h> Ref is used for reference count manangement. If a classinherits from Ref. C ...

  4. Unity3D 游戏开发构架篇 —— 动态大场景生成 = 区域加载+对象池管理

    项目做一个类似无尽模式的场景,想了一想,其实方法很简单,做一个相关的总结. 主要先谈一谈构架,后期附上代码. 一.区域加载 其实无尽场景的实现很简单,因为屏幕限制,那么不论何时何地,我们只能看到自己的 ...

  5. Unity对象池管理

    链接: http://www.xuanyusong.com/archives/2925 http://www.xuanyusong.com/archives/2974 https://www.cnbl ...

  6. 使用java自带线程池管理器demo

    1.程序入口:DabianTest package com.lbh.myThreadPool.present; import java.util.concurrent.ExecutorService; ...

  7. Unity3d对象池

    Singleton.cs 12345678910111213 using UnityEngine;/// <summary>/// 单例模版类/// </summary>pub ...

  8. cocos2dx3.0 对象池

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdzE4NzY3MTA0MTgz/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  9. Unity 游戏框架搭建 (二十) 更安全的对象池

    上篇文章介绍了,只需通过实现IObjectFactory接口和继承Pool类,就可以很方便地实现一个SimpleObjectPool.SimpleObjectPool可以满足大部分的对象池的需求.而笔 ...

随机推荐

  1. mpvue打包没有app.json等配置文件的解决方法

    问题 一早上折腾了1个小时,小程序始终提示查找不到'app.json'文件.mpvue重新打包,光生成内容文件无配置文件. 解决办法 出错原因:版本问题 只需要把packpage.json里的mpvu ...

  2. es8(字符串,对象)

    es8(字符串,对象) 字符串补白: let str = "abc"; let a = str.padEnd(5); let b = str.padStart(5); let c ...

  3. 深入解析丨母婴App如何迅速收割2W新用户?

    在讲案例前,我们需要先说一下精细化分析. 我们常说的精细化分析,就是一个持续"解构"的过程,通过像漏斗.留存.细分等高级分析功能,将"整体"按照事件属性解构成& ...

  4. CSS样式写在JSP代码中的几种方法

    1.行内样式. 可以直接把css代码写在现有的HTML标签元素的开始标签里面,并且css样式代码要写在style=" "双引号中才可以, 如: <p style=" ...

  5. java读取xml文件并转换成对象,并进行修改

    1.首先要写工具类,处理读取和写入xml文件使用的工具.XMLUtil.javaimport java.io.FileInputStream; import java.io.FileWriter; i ...

  6. 适配手机端rpx像素

    <script src="static/js/adaptive.js"></script> <script type="text/javas ...

  7. 支付宝小程序中“<”号写法

    今天遇到一个小问题,记录一下 "<"号在h5页面都是可以直接显示的,但是在运行支付宝小程序时报错,找了一个解决办法 <text> {{char_lt}} 18.5 ...

  8. 数据库篇:mysql事务原理之MVCC视图+锁

    前言 数据库的事务特性 数据并发读写时遇到的一致性问题 mysql事务的隔离级别 MVCC的实现原理 锁和隔离级别 关注公众号,一起交流,微信搜一搜: 潜行前行 1 数据库的事务特性 原子性:同一个事 ...

  9. 记录Jenkins升级到最新版遇到的问题

    ​ 首先吐槽一下Jenkins: 1.安装插件的时候无法根据Jenkins的版本号安装对应的插件! 2.安装插件安装版本不一致的时候无法降低插件版本! 3.为啥要我们升级到最新版! 一.升级原因 我的 ...

  10. JDBC中常用的类和接口

    <零基础学Java> JDBC中常用的类和接口 利用JDBC的这些类和接口可以更方便地访问并处理存储在数据库中的数据. DriverManager类 DriverManager类 是JDB ...