Unity——对象池管理
Unity对象池管理
一、Demo展示

二.逻辑
在游戏中会出现大量重复的物体需要频繁的创建和销毁;比如子弹,敌人,成就列表的格子等;
频繁的创建删除物体会造成很大的开销,像这种大量创建重复且非持续性保持作用的对象我们会使用对象池将其管理起来,用空间换效率;
对象池的要对外提供创建销毁对象的接口,已经添加对象池的接口;
对内要提供创建对象,根据路径查找预制的接口;
整体逻辑如下:

二.加载/添加对象池
添加资源路径,分为Resources文件夹下和SteamingAssets文件下资源;
Resources加载时路径不需要后缀,SteamingAssets需要后缀,根据path路径开头的判断加载方式,同时对路径做处理;
SteamingAssets需要根据平台添加路径头Application.streamingAssetsPath;
Resources需要去掉格式后缀,如.perfab;
这里我测试只使用Resources路径,正式项目自行处理;
存放预创建好的对象:
private Dictionary<string,List<GameObject>> pool;
存放预制体路径:
private Dictionary<string, string> objPath;
public void InitPath()
{
//测试用,正常肯定要做字符串处理的,需要加后缀
objPath.Add("cube","Cube");
objPath.Add("sphere","Sphere");
}
public void Add(string key, int num)
{
if (pool.ContainsKey(key))
{
for (int i = 0; i < num; ++i)
{
//AssetBundle ab = AssetBundle.LoadFromFile($"{path}/{objPath[key]}");
//GameObject go = Instantiate(ab.LoadAsset<GameObject>(key));
//由于我的测试资源就放在Resources下,正式项目需要根据路径做个判断;
GameObject go = Instantiate(Resources.Load<GameObject>(objPath[key]));
go.SetActive(false);
pool[key].Add(go);
}
}
else
{
List<GameObject> goList = new List<GameObject>();
pool.Add(key, goList);
for (int i = 0; i < num; ++i)
{
//AssetBundle ab = AssetBundle.LoadFromFile(objPath[key]);
//GameObject go = Instantiate(ab.LoadAsset<GameObject>(key));
GameObject go = Instantiate(Resources.Load<GameObject>(objPath[key]));
go.SetActive(false);
pool[key].Add(go);
}
}
}
三.管理对象池
对象池管理需要对外提供创建对象,销毁对象,延迟销毁和清空池的方法;
创建对象时,需要提供key,坐标,旋转;
现查找是否有对象池,没有则添加;
这里提供了四元素和欧拉角的重载方法;
1.创建对象
public GameObject FindUsable(string key
{
if(pool.ContainsKey(key))
{
foreach (GameObject item in poo
{
if (!item.activeSelf)
return item;
}
Debug.Log($"{key}的对象池数量不够");
}
else
{
Debug.Log($"{key}未添加对象池");
}
return null;
}
/// <summary>创建一个游戏物体到场景 </summary>
public GameObject CreateObject(string k
{
GameObject tempGo = FindUsable(key)
if (tempGo == null)
{
Debug.Log($"{key}的对象池数量不够");
Add(key, 10);
tempGo = FindUsable(key);
}
tempGo.transform.position = positio
tempGo.transform.rotation = quatern
tempGo.SetActive(true);
return tempGo;
}
public GameObject CreateObject(string k
{
GameObject tempGo = FindUsable(key)
if (tempGo == null)
{
Debug.Log($"{key}的对象池数量不够");
Add(key, 10);
tempGo = FindUsable(key);
}
tempGo.transform.position = positio
tempGo.transform.rotation = Quatern
tempGo.SetActive(true);
return tempGo;
}
2.销毁对象
延时销毁可使用回调(invoke)或协程;
public void Destory(GameObject destoryGo)
{
destoryGo.SetActive(false);
}
/// <summary>将对象归入池中<summary>
public void Destory(GameObject tempGo, float delay)
{
StartCoroutine(DelayDestory(tempGo,delay));
}
/// <summary>延迟销毁</summary>
private IEnumerator DelayDestory(GameObject destoryGO, float delay)
{
yield return new WaitForSeconds(delay);
Destory(destoryGO);
}
3.清空池
/// <summary>清空某类游戏对象</summary>
public void Clear(string key)
{
pool.Remove(key);
}
/// <summary>清空池中所有游戏对象</summary>
public void ClearAll()
{
pool.Clear();
}
四、测试代码
两个按钮分别创建方块和球,每次创建更改一次位置;鼠标射线点击延迟1s销毁;
public class Test : MonoBehaviour
{
public Button btnCube;
public Button btnSphere;
void Start()
{
GameObjectPool.I.InitPath();
GameObjectPool.I.Add("cube",10);
GameObjectPool.I.Add("sphere",10);
btnCube.onClick.AddListener(OnBtnCube);
btnSphere.onClick.AddListener(OnBtnSphere);
}
private Vector3 deltaPos = new Vector3(1, 1, 1);
private Vector3 pos =new Vector3(-10,0,0);
private void OnBtnCube()
{
GameObject go = GameObjectPool.I.CreateObject("cube", pos, Vector3.zero);
go.transform.SetParent(null);
SceneManager.MoveGameObjectToScene(go, SceneManager.GetSceneByName("1"));
go.transform.position += deltaPos;
pos = go.transform.position;
}
private Vector3 pos1 =new Vector3(0,0,0);
private void OnBtnSphere()
{
GameObject go = GameObjectPool.I.CreateObject("sphere", pos1, Vector3.zero);
go.transform.SetParent(null);
SceneManager.MoveGameObjectToScene(go, SceneManager.GetSceneByName("1"));
go.transform.position += deltaPos;
pos1 = go.transform.position;
}
private void Update()
{
if(Input.GetMouseButtonDown(0)){
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
if(Physics.Raycast(ray,out hitInfo)){
Debug.DrawLine(ray.origin,hitInfo.point);
GameObject gameObj = hitInfo.collider.gameObject;
Debug.Log("click object name is " + gameObj.name);
GameObjectPool.I.Destory(gameObj,1);
}
}
}
}
Unity——对象池管理的更多相关文章
- Unity对象池管理
链接: http://www.xuanyusong.com/archives/2925 http://www.xuanyusong.com/archives/2974 https://www.cnbl ...
- Unity 对象池 生产 保存
Unity对象池主要是保存那些常用的物体,避免他们在不断销毁和创造中损坏性能. 主要思路为:创造物体时,判断是否存在,如果存在则调用并使其显示.如果不存在则创造一个新的. 当销毁时,调用协程延时隐藏物 ...
- Unity实现”对象池管理器“
前言:警告!这可能是坨屎,空闲时间写成,仅作娱乐 在Unity中生成或销毁一个物体会占用较大的资源,如果是制作FPS射击游戏,子弹生成更是雪上加霜.所以我自己写了一个PoolManager,不能和网上 ...
- Unity3D 游戏开发构架篇 —— 动态大场景生成 = 区域加载+对象池管理
项目做一个类似无尽模式的场景,想了一想,其实方法很简单,做一个相关的总结. 主要先谈一谈构架,后期附上代码. 一.区域加载 其实无尽场景的实现很简单,因为屏幕限制,那么不论何时何地,我们只能看到自己的 ...
- Unity ----- 对象池GameObjectPool
孙广东 2014.6.28 非常早之前看到的外国文章,认为不错,分享一下. 对象池在AssetStore中也是有非常多插件的,可是有些重了.自己写一个轻量的岂不是非常好. 当你须要创建大量某种类型对象 ...
- Unity 对象池的使用
在游戏开发过程中,我们经常会遇到游戏发布后,测试时玩着玩着明显的感觉到有卡顿现象.出现这种现象的有两个原因:一是游戏优化的不够好或者游戏逻辑本身设计的就有问题,二是手机硬件不行.好吧,对于作为程序员的 ...
- Unity对象池的实现
对象池是一个单例类: using System.Collections; using System.Collections.Generic; using UnityEngine; public cla ...
- 游戏设计模式——Unity对象池
对象池这个名字听起来很玄乎,其实就是将一系列需要反复创建和销毁的对象存储在一个看不到的地方,下次用同样的东西时往这里取,类似于一个存放备用物质的仓库. 它的好处就是避免了反复实例化个体的运算,能减少大 ...
- Unity 游戏框架搭建 (二十) 更安全的对象池
上篇文章介绍了,只需通过实现IObjectFactory接口和继承Pool类,就可以很方便地实现一个SimpleObjectPool.SimpleObjectPool可以满足大部分的对象池的需求.而笔 ...
随机推荐
- 理解java调试的工作目录 working directory
原文链接使用idea或者eclipse进行调试的时候会有Working directory配置: 我们创建工程,IDE会自动创建一个工程目录,假设工程名称为:TestProject,那么在会创建一个目 ...
- 使用Hugo和GitHub搭建博客
折腾了几天博客的框架终于搭建起来了.研究了一番之后,最终还是选择使用Hugo和GitHub来搭建博客.本文介绍了如何使用Hugo来搭建静态博客网站,并将其部署在GitHub上.使用https://&l ...
- easyexcel
导出: package com.example.demo.excel.demo0; import com.alibaba.excel.annotation.ExcelProperty; import ...
- 【XSS】XSS修炼之独孤九剑
题目地址 xcao.vip/test 题目作者给出的解题思路 http://xcao.vip/test/xss/XSS修炼之独孤九剑.pdf 独孤九剑-第一式 题目 过滤了等号 =.小括号 (),要求 ...
- Django的form组件——自定义校验函数
from django.shortcuts import render,HttpResponse from django import forms from django.core.exception ...
- K8S命令行工具——kubectl
1.kubectl概述 2.kubectl命令的语法 例子: 3.kubectl子命令使用分类 (1)基础命令 (2)部署和集群管理命令 (3)故障和调试命令 (4)其他命令 4.kubectl命令例 ...
- Excel导入保存附件和解析数据
Excel导入保存附件和解析数据 一,前端上传附件的组件 1.先给一个下载模板的按钮 // 下载Excel模板 downLoadExcel: function () { window.open(GLO ...
- Web GIS 航拍实现的智慧园区数字孪生应用
前言 随着智慧城市建设的不断发展,智慧园区作为智慧城市的先行区,其覆盖区域越来越大,产值越来越集中,对于园区数字化建设和智能化管理的诉求也愈加强烈.园区数字化管理是以实现园区多维度业务数据汇聚.融合. ...
- 如何在云效流水线 Flow中构建属于自己的NPM仓库
如何在云效流水线 Flow中构建属于自己的NPM仓库,Flow 通过各种构建组件,对各种语言提供了制品打包能力,让用户可以快速的使用流水线构建制品,并通过后续的部署任务进行部署.Flow 已经完成了与 ...
- Ubuntu 引导修复
Ubuntu 引导修复 前言 最近还在看 Docker 的教程,看到了"跨宿主机网络通信"的一节,于是想到去 Ubuntu 中 实践一番.结果发现 Ubuntu 进不去了.由于考虑 ...