最近都在忙别的事了,今天忙里偷闲了解了一下对象池是啥玩意,简单记录一下。

还是个正在学习的萌新,如果写的不好请见谅。

对象池是啥

在了解对象池之后,我才意识到以前写的代码有多么蠢,当场景中有一些重复的需要生成和销毁的物体时(比如地上可拾取的金币),我们常常调用Instantiate和Destroy函数去实现,这造成了大量的性能开销,尤其是当游戏物体挂载脚本时,脚本中的Awake()、OnEnable()、OnDestroy()等方法不断被调用,对性能造成了很大的负担,所以在复用性强的游戏中缓存池是十分重要的。

对象池的原理就是我们把需要复用的物体存在池子里,需要“销毁物体”时,通过SetActive方法暂时让物体隐藏而不是真的销毁,需要“生成物体”时,先看看池子里有没有之前隐藏的物体,如果有就直接将其激活,没有的话再去生成物体,这样我们真正需要去生成物体的次数永远是场景中同时存在该物体的最大值,而不是每次使用都去生成和销毁。

对象池实现

我在unity中简单实现了一个对象池,用字典的形式存储每种物体对应的池子(也就是List),取出物体时使用一个字符串代表该物体,然后将该物体的预制体放在Resources目录下,注意预制体的名字要和传入的参数相同。

需要注意的是,我们只是隐藏了物体,而物体的位置、旋转等信息并没有改变,所以当我们下次取出它时,它的数据还和原来一样,这种数据通常称为“脏数据”,所以我们可以让复用的物体都继承一个父类,提供两个抽象方法,让子物体去重写,当把物体取出和放回池子时调用这两个方法去处理数据。

public abstract class RecyclableObject:MonoBehaviour
{
public abstract void OnSpawn(); public abstract void OnUnspawn();
}

取出和放回物体时,可以使用SendMessage来调用子类身上的方法处理脏数据,比如调整位置之类的。

using System.Collections;
using System.Collections.Generic;
using UnityEngine; public class ObjectPool
{
//单例
private static ObjectPool _instance;
public static ObjectPool Instance
{
get
{
if (_instance == null)
{
_instance = new ObjectPool();
}
return _instance;
}
} public Dictionary<string, List<GameObject>> poolsDict = new Dictionary<string, List<GameObject>>(); //取出物体
public void Spawn(string name,Transform parent)
{
//如果没有这个类型的池子就创建一个
if(!poolsDict.ContainsKey(name))
{
poolsDict.Add(name, new List<GameObject>());
} //得到池子
List<GameObject> ObjList;
poolsDict.TryGetValue(name, out ObjList); //在池子里寻找被隐藏的游戏物体
GameObject go = null;
foreach(var obj in ObjList)
{
if(!obj.activeSelf)
{
go = obj;
}
} if(go==null)//不存在隐藏的游戏物体
{
go = Object.Instantiate(Resources.Load<GameObject>(name));
ObjList.Add(go);
}
else//存在隐藏的游戏物体
{
go.SetActive(true);
} go.transform.parent = parent;
go.SendMessage("OnSpawn", SendMessageOptions.DontRequireReceiver);
} //回收物体
public void Unspawn(GameObject go)
{
foreach(List<GameObject> list in poolsDict.Values)
{
if(list.Contains(go)&&go.activeSelf)
{
go.SendMessage("OnUnspawn", SendMessageOptions.DontRequireReceiver);
go.SetActive(false);
}
}
} //销毁池子
public void ClearPool(string name)
{
if(poolsDict.ContainsKey(name))
{
foreach(GameObject go in poolsDict[name])
{
Object.Destroy(go);
}
poolsDict.Remove(name);
}
} }

马上要参加计算机设计大赛的省赛和蓝桥杯的国赛,所以暂时没时间学游戏开发了,希望比赛能有个好结果,加油吧。

Unity日记—对象缓存池的更多相关文章

  1. Unity中对象池的使用

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

  2. cocos2d 缓存池 对象的再利用

    1.简单的叙述说明池 例如,我们知道,游戏的游戏类型跑酷,游戏元素都在不断重复.游戏的内容将继续从屏幕右侧的创建,当元件在屏幕的左侧的,将消失.假设不变new 对象.release 对象 性能影响.怎 ...

  3. Unity3d 动态加载场景物件与缓存池的使用

    聊聊Unity3d动态加载场景物件那些事儿. 众所周知,在策划或美术设计完游戏场景地图后,一个场景中可能会存在成千上万个小的物件,比如石头,木箱子,油桶,栅栏等等等等,这些物件并不是游戏中的道具,仅仅 ...

  4. MemCache分布式内存对象缓存系统

    MemCache超详细解读 MemCache是一个自由.源码开放.高性能.分布式的分布式内存对象缓存系统,用于动态Web应用以减轻数据库的负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而 ...

  5. 深入剖析Java中的装箱和拆箱(缓存池技术)

    以下是本文的目录大纲: 一.什么是装箱?什么是拆箱? 简单一点说,装箱就是  自动将基本数据类型转换为包装器类型:拆箱就是  自动将包装器类型转换为基本数据类型. 二.装箱和拆箱是如何实现的 1:反编 ...

  6. iOS开发:一个瀑布流的设计与实现(已实现缓存池功能,该功能使得瀑布流cell可以循环利用)

    一个瀑布流的实现有三种方式: 继承自UIScrollView,仿写UITableView的dataSource和delegate,创造一个缓存池用来实现循环利用cell 写多个UITableview( ...

  7. 管理ceph缓存池

    目录 缓存池简介 缓存池原理 缓存池的工作模式 配置缓存池 1. 创建一个缓存池 2. 设置缓存层 3. 缓存层相关参数说明 4. 测试缓存池 删除缓存池 1. 删除read-only缓存池 2. 删 ...

  8. [Java] 缓存池

    new Integer(123) 与 Integer.valueOf(123) 的区别在于: new Integer(123) 每次都会新建一个对象: Integer.valueOf(123) 会使用 ...

  9. MonoBehaviour生命周期与对象数据池应用

    预热游戏对象: tempObject = Instantiate(cubePrefab) as GameObject ; tempObject .SetActive( false ); 游戏对象tem ...

随机推荐

  1. ELF文件结构描述

    ELF目标文件格式最前部ELF文件头(ELF Header),它包含了描述了整个文件的基本属性,比如ELF文件版本.目标机器型号.程序入口地址等.其中ELF文件与段有关的重要结构就是段表(Sectio ...

  2. Windows Server 2012 R2 创建AD域

        前言 我们按照下图来创建第一个林中的第一个域.创建方法为先安装一台Windows服务器,然后将其升级为域控制器.然后创建第二台域控制器,一台成员服务器与一台加入域的Win8计算机. 环境 网络 ...

  3. Will Georgia Tech's $7K online M.S. in computer science program make the grade?

    https://newatlas.com/georgia-tech--graduate-computer-science-degree-mooc/28763/ Georgia Tech to offe ...

  4. 一、HttpServletRequest接口 二、HttpServletReponse接口 三、POST和GET请求方式及其乱码处理 四、ServletContext对象和ServletConfig对象

    一.HttpServletRequest接口 内部封装了客户端请求的数据信息 接收客户端的请求参数.HTTP请求数据包中配置参数 ###<1>常用方法 getContextPath()重要 ...

  5. SP--report存储过程

    USE [edison_prc] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ),),),),),@day1 int,@day2 int) ...

  6. [python]python官方原版编码规范路径

    1.进入python官方主页:https://www.python.org/ 2.按如下图进入PEP Index ​ 3.选择第8个,即为python的规范 ​

  7. ES6标准入门之正则表达式的拓展

    所谓正则表达式,又称规则表达式.(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念.正则表达式通常被用来检索.替换那些符合某个模式(规 ...

  8. Android 打造属于自己的照片选择器

    前言 在做第一个项目时照片选择器使用了开源的PhotoPicker 渐渐无法满足需求,就想着打造一款属于自己的照片选择器. 花了一周的时间完成了该项目,其实代码有一大半并非自己写的,在阅读PhotoP ...

  9. js 对于jquery each 多层循环的问题和原生js多层循环问题

    一.在jquery中,我们使用循环的时候,提供两种方式:jquery.each 和(循环体).each  两种方式不是同. 对于return 在作用这两个的函数的时候需要注意: 首先我们需要知道我们的 ...

  10. Android MD5算法

    package com.example.myapi.md5; import java.io.UnsupportedEncodingException; import java.security.Mes ...