IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity3d 实现对象池 -> 正文阅读

[游戏开发]Unity3d 实现对象池

原文地址:https://app.gitbook.com/@galaxyzeta/s/unity3d/shi-xian-unity3d-dui-xiang-chi

为何需要对象池?

想像你的游戏中有一架飞机,它每秒钟射出 1000 个相同的子弹对象,但他们的存活时间都只有1s。如果引擎每秒钟新增,删除1000次同样的物体,对性能将会产生较大影响。

解决这个问题的一种办法就是引入池化技术:

  • 游戏开始前,将这些子弹全部存放到一个池子中;
  • 当我们需要这些物体的时候,直接拿出来初始化一下位置、属性等,就可以继续用;
  • 当我们需要从场景中移除某些被池化的对象,只需要将这些对象设置为 Inactive 即可,而不是将其删除。

池子中的对象永远就那么几个,场景中的对象并没有真正消失,它们只是暂时被 Inactivate 了。这一波操作下来,引擎无需反复执行创建、删除操作,性能就大大提升了。

对象池技术事实上就是设计模式中的享元模式(Flyweight Pattern)。

核心思想

  • 使用 List<GameObject> 数据结构管理对象。
  • 提供 GetReferenceFromPool 方法,方法有两种重载:
    • 无参数,直接拿第 0 号对象。
    • 有参数,拿 index 位置的对象。
  • 当我们需要从 pool 中拿指定 index 的对象时:
    • 如果 pool 中还没有对象,则创建对象,并返回给用户一个 active 的 gameObject。
    • 如果 pool 中已经有对象:
      • 需要先检查这个对象是不是空的(可能在别处调用 Destroy 删除了对象,因此这里得到了空的对象引用)
      • 如果对象是空的,需要创建对象,设置到 pool 中,并则设置 gameObject 为 active 并返回。
      • 如果提供的 index 有可能产生数组越界,则往 pool 中添加一个新的对象,并返回。
  • 当我们需要移除一个对象:
    • 如果选择使用 Destroy 删除,下次获取时将得到一个空引用。处理方法在上面讲过了。
    • 不使用 Destroy,而是直接置成 inactive。
      • 注意将对象置成初始化状态。(如果你决定在拿对象的时候初始化也行)
      • 可以写一个 PoolableMonoBehaviour 类继承 MonoBehaviour ,然后写一个 Dispose() 方法表示将该物体 “移除”(置 inactive)。

一种实现


using UnityEngine;
using System.Collections.Generic;

namespace Util {
	public class GameObjectPool {

		[SerializeField]
		private GameObject prefab;	// 这是池子里存放的对象 prefab
		[SerializeField]
		private List<GameObject> pool = new List<GameObject>(); // 使用 List 管理池子

		private GameObjectPool() {}

		public GameObjectPool(GameObject prefab) {
			this.prefab = prefab;
		}

		private GameObject GetAndSetActiveAtIndex(int index) {
			pool[index].SetActive(true);
			return pool[index];
		}

		private GameObject GetOrCreateAtIndex(int index) {
			if(pool[index] == null) {		// 注意判断空,因为对象可能已经被真的删除了
				pool[index] = CreatePrefab(true);
				return pool[index];
			} else {
				return GetAndSetActiveAtIndex(index);
			}
		}

		private GameObject CreatePrefab(bool setActive) {
			GameObject obj = Gamemanager.InstantiateWrapper<GameObject>(prefab);
			if(! setActive) {
				obj.SetActive(false);
			}
			return obj;
		}

		///<summary>
		/// 拿第0号对象,拿不到就创建。
		///</summary>
		public GameObject GetReference() {
			if(pool.Count > 0) {
				return GetOrCreateAtIndex(0);
			} else {
				return CreateAndRegister(true);
			}
		}
		
		///<summary>
		/// 拿第index号对象,拿不到就创建。
		///</summary>
		public GameObject GetReference(int index) {
			if(index >= pool.Count) {
				return CreateAndRegister(true);
			} else {
				return GetOrCreateAtIndex(index);
			}
		}

		///<summary>
		/// 创建并添加到 pool 中。
		///</summary>
		public GameObject CreateAndRegister(bool setActive) {
			GameObject reference = CreatePrefab(setActive);
			pool.Add(reference);
			return reference;
		}
	}
}
  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章           查看所有文章
加:2021-10-04 13:08:06  更:2021-10-04 13:09:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/28 2:45:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码