Unity3d:GameFramework解析:实体,对象池,资源管理,获取计数,引用计数,自动释放
基本概念
1.GF万物基于引用池IReference
2.ObjectBase : IReference类的m_Target持有unity中Mono,资源,GameObejct
3.AssetObject : ObjectBase类m_Target持有Assetbundle中的Asset,具有获取,引用两个计数管理释放
4.ResourceObject : ObjectBase类m_Target持有Assetbundle,具有获取,引用两个计数管理释放
5.EntityInstanceObject : ObjectBase类m_Target指向Assetbundle中的Asset实例化后的GameObject,内部m_EntityAsset也是Assetbundle中的Asset
6.对象池具有按照间隔自动释放无用对象,对于实体,获取为0,即无用对象;对于AssetObject,ResourceObject要获取为0,父依赖(自己被别依赖)为0,即无用
7.引用的概念为资源被依赖,例如bundleA依赖bundleB,于是bundleB的引用=1
8.获取的概念:针对资源为对象再派生(关联)出别的对象,例如ResourceObjectA派生出AssetObjectA,即ResourceObjectA获取为1;AssetObjectA再派生出EntityInstanceObjectA,AssetObjectA的获取为1
对象池创建
InstancePool
只能单获取,即不能对一个对象反复Spawn
m_InstancePool = objectPoolManager.CreateSingleSpawnObjectPool<EntityInstanceObject>(Utility.Text.Format("Entity Instance Pool ({0})", name), instanceCapacity, instanceExpireTime, instancePriority);
AssetPool与ResourceObject
public void SetObjectPoolManager(IObjectPoolManager objectPoolManager)
{m_AssetPool = objectPoolManager.CreateMultiSpawnObjectPool<AssetObject>("Asset Pool");m_ResourcePool = objectPoolManager.CreateMultiSpawnObjectPool<ResourceObject>("Resource Pool");
}
EntityInstanceObject实体对象
1.每次使用看实体对象池中有无,有是指存在空闲未使用实体对象,取出来用
2.没有的话,需要从资源加载流程中走一遍
释放时
UnityGameFramework.Runtime.DefaultEntityHelper.ReleaseEntity
/// <summary>/// 释放实体。/// </summary>/// <param name="entityAsset">要释放的实体资源。</param>/// <param name="entityInstance">要释放的实体实例。</param>public override void ReleaseEntity(object entityAsset, object entityInstance){m_ResourceComponent.UnloadAsset(entityAsset);Destroy((Object)entityInstance);}
1.AssetPool中把entityAsset的获取-1
2.销毁asset实例出来的GameObject
ResourceObject
何时引用+1
在assetA加载完,assetA的依赖asset的bundle引用+1。注意是依赖的asset的bundle,自身的bundle并不会引用+1
GameFramework.Resource.ResourceManager.ResourceLoader.LoadResourceAgent.OnLoadResourceAgentHelperLoadComplete
foreach (object dependencyAsset in dependencyAssets)
{object dependencyResource = null;if (m_ResourceLoader.m_AssetToResourceMap.TryGetValue(dependencyAsset, out dependencyResource)){m_Task.ResourceObject.AddDependencyResource(dependencyResource); //所有依赖这个asset的resource引用+1}
同时被依赖的bundleB加入到主bundleA的ResourceObject依赖列表中
GameFramework.Resource.ResourceManager.ResourceLoader.ResourceObject.AddDependencyResource
m_DependencyResources.Add(dependencyResource);
何时引用-1
bundle被释放时,子依赖bundle引用-1
GameFramework.Resource.ResourceManager.ResourceLoader.ResourceObject.Release
foreach (object dependencyResource in m_DependencyResources)
{int referenceCount = 0;if (m_ResourceLoader.m_ResourceDependencyCount.TryGetValue(dependencyResource, out referenceCount)){m_ResourceLoader.m_ResourceDependencyCount[dependencyResource] = referenceCount - 1;//只会-1,不会对为 0 的Assetbundle进行卸载}
何时获取+1
bundleA中获取assetA时,获取+1。此时有有两种情况,
1.执行加载asset任务时,主bundle已加载,从ResourcePool中获取
GameFramework.Resource.ResourceManager.ResourceLoader.LoadResourceAgent.Start
ResourceObject resourceObject = m_ResourceLoader.m_ResourcePool.Spawn(resourceName);
if (resourceObject != null)
{GameFrameworkLog.Info("ResourcePool获取到了{0},说明asset:{1}的bundle已经加好了,返回bundle", resourceName, m_Task.AssetName);//从resource对象池中取出,说明之前加载过Assetbundle,任务可以接着执行OnResourceObjectReady(resourceObject);return StartTaskStatus.CanResume;
}
2.bundle未加载,加载完后注册入对象池,获取+1
GameFramework.Resource.ResourceManager.ResourceLoader.LoadResourceAgent.OnLoadResourceAgentHelperReadFileComplete
private void OnLoadResourceAgentHelperReadFileComplete(object sender, LoadResourceAgentHelperReadFileCompleteEventArgs e)
{GameFrameworkLog.Info("Assetbundle加载完成:{0}", m_Task.ResourceInfo.ResourceName.Name);ResourceObject resourceObject = ResourceObject.Create(m_Task.ResourceInfo.ResourceName.Name, e.Resource, m_ResourceHelper, m_ResourceLoader);m_ResourceLoader.m_ResourcePool.Register(resourceObject, true);s_LoadingResourceNames.Remove(m_Task.ResourceInfo.ResourceName.Name);OnResourceObjectReady(resourceObject);
}
何时获取-1
GameFramework.Resource.ResourceManager.ResourceLoader.AssetObject.Release
m_ResourceLoader.m_ResourcePool.Unspawn(m_Resource);
AssetObject
何时引用+1
assetA新加载完成时,创建AssetObjectA,把子依赖asset引用+1
GameFramework.Resource.ResourceManager.ResourceLoader.AssetObject.Create
//所有依赖的asset 引用+1,它自己次数不会+1
foreach (object dependencyAsset in dependencyAssets)
{int referenceCount = 0;GameFrameworkLog.Info("AssetObject创建-->{0}引用次数+1", dependencyAsset);if (resourceLoader.m_AssetDependencyCount.TryGetValue(dependencyAsset, out referenceCount)){resourceLoader.m_AssetDependencyCount[dependencyAsset] = referenceCount + 1;}else{resourceLoader.m_AssetDependencyCount.Add(dependencyAsset, 1);}
}
何时引用-1
AssetObjectA释放时,把所有子依赖资源-1。这里只会找直接子依赖(子节点),不会找到孙节点上
GameFramework.Resource.ResourceManager.ResourceLoader.AssetObject.Release
foreach (object dependencyAsset in m_DependencyAssets)
{int referenceCount = 0;if (m_ResourceLoader.m_AssetDependencyCount.TryGetValue(dependencyAsset, out referenceCount)){m_ResourceLoader.m_AssetDependencyCount[dependencyAsset] = referenceCount - 1;//子依赖的asset -1}
何时获取+1
AssetObject的获取,是为了给实例对象实例化。两种情况下
1.任务执行时,AssetPool有,直接返回,获取+1
GameFramework.Resource.ResourceManager.ResourceLoader.LoadResourceAgent.Start
//从对象池里拿一个
AssetObject assetObject = m_ResourceLoader.m_AssetPool.Spawn(m_Task.AssetName);
if (assetObject != null)
{//说明资源之前加载过,且在AssetObject缓存池中//一旦成功执行Spawn,Spawn+1,在释放资源时不为0会跳过GameFrameworkLog.Info("AssetPool获取到了{0},不需要加载,直接返回asset", m_Task.AssetName);//如果是实体,实例化asset,并且新建一个实体对象OnAssetObjectReady(assetObject);return StartTaskStatus.Done;
}
2.AssetPool没有,从Assetbundle中加载完成asset,创建新AssetObject,并注册进入AssetPool,获取+1
GameFramework.Resource.ResourceManager.ResourceLoader.LoadResourceAgent.OnLoadResourceAgentHelperLoadComplete
assetObject = AssetObject.Create(m_Task.AssetName, e.Asset, dependencyAssets, m_Task.ResourceObject.Target, m_ResourceHelper, m_ResourceLoader);GameFrameworkLog.Info("asset-->{0}加载完成,并且创建AssetObject到m_AssetPool缓冲池中", m_Task.AssetName);m_ResourceLoader.m_AssetPool.Register(assetObject, true);
何时获取-1
EntityInstanceObject释放时
UnityGameFramework.Runtime.DefaultEntityHelper.ReleaseEntity
/// <summary>/// 释放实体。/// </summary>/// <param name="entityAsset">要释放的实体资源。</param>/// <param name="entityInstance">要释放的实体实例。</param>public override void ReleaseEntity(object entityAsset, object entityInstance){m_ResourceComponent.UnloadAsset(entityAsset);Destroy((Object)entityInstance);}
加载实体创建各个asset任务
加载一个实体,一个asset作为主任务,asset依赖的各个asset作为依赖任务
单个asest任务加载任务执行
任务
任务派生LoadAssetTask,LoadDependencyAssetTask,LoadSceneTask
任务完成的标志
资源准备好,即任务完成。不管是是从AssetPool中获取,还是异步加载完成
private void OnAssetObjectReady(AssetObject assetObject)
{m_Helper.Reset();object asset = assetObject.Target;if (m_Task.IsScene){m_ResourceLoader.m_SceneToAssetMap.Add(m_Task.AssetName, asset);}m_Task.OnLoadAssetSuccess(this, asset, (float)(DateTime.UtcNow - m_Task.StartTime).TotalSeconds);m_Task.Done = true;
}
自动释放
隐藏某实体时,在对象池自动释放中,如果改实体池依赖的asset获取为0,再判断出bundle获取为0,触发assetbundle.Unload(true),释放内存
相关文章:

Unity3d:GameFramework解析:实体,对象池,资源管理,获取计数,引用计数,自动释放
基本概念 1.GF万物基于引用池IReference 2.ObjectBase : IReference类的m_Target持有unity中Mono,资源,GameObejct 3.AssetObject : ObjectBase类m_Target持有Assetbundle中的Asset,具有获取,引用两个计数管理释放 4.ResourceObj…...

Django基础6——数据模型关系
文章目录 一、基本了解二、一对一关系三、一对多关系3.1 增删改查3.2 案例:应用详情页3.2 案例:新建应用页 四、多对多关系4.1 增删改查4.2 案例:应用详情页4.3 案例:部署应用页 一、基本了解 常见数据模型关系: 一对一…...
【chrome扩展开发】如何在项目中判断插件是否已安装
由于安全限制,本文采取间接的方式实现 1、项目部分 比如通过cookie、localStorage等进行状态存储 1.1、初始化判断 function getCookie(name){let arr document.cookie.match(new RegExp("(^| )"name"([^;]*)(;|$)"))if(arr ! null){return u…...

Centos 7.6 安装mongodb
以下是在CentOS 7.6上安装MongoDB的步骤: 打开终端并以root用户身份登录系统。 创建一个新的MongoDB存储库文件 /etc/yum.repos.d/mongodb-org-4.4.repo 并编辑它。 sudo vi /etc/yum.repos.d/mongodb-org-4.4.repo在编辑器中,添加下面的内容到文件中并…...

Ubuntu下安装nginx服务,实现通过URL读取ubuntu下图片
1.安装nginx包 sudo apt update sudo apt install nginx 2.安装完成后系统自动启动nginx sudo systemctl status nginx 查看nginx服务的状态 3.开启防火墙上的HTTP服务端口80 sudo ufw allow ‘Nginx HTTP’ 4.在浏览器输入 http://localhost 看到nginx的欢迎界面,…...

本地部署 Stable Diffusion(Mac 系统)
在 Mac 系统本地部署 Stable Diffusion 与在 Windows 系统下本地部署的方法本质上是差不多的。 一、安装 Homebrew Homebrew 是一个流行的 macOS (或 Linux)软件包管理器,用于自动下载、编译和安装各种命令行工具和应用程序。有关说明请访问官…...

浪潮云海护航省联社金融上云,“一云多芯”赋能数字农业
农村金融是现代金融体系的重要组成部分,是农业农村发展的重要支撑力量,而统管全省农商行及农信社的省级农村信用社联合社(以下简称:省联社)在我国金融系统中占据着举足轻重的地位。省联社通常采用“大平台小法人”的发…...
MyCat的XA事务研究及字符集问题
MyCAT 1.4 开发版,初步实现了XA事务,关注这个高级技术的同学可以编译代码并测试其正确性。。 在手动事务模式下,可以执行 set xaon开启XA事务支持 目前实现了不跨分片的SQL的XA事务,测试过程如下 mysql> set autocommit0; Qu…...

9、监测数据采集物联网应用开发步骤(7)
监测数据采集物联网应用开发步骤(6) 串口(COM)通讯开发 本章节测试使用了 Configure Virtual Serial Port Driver虚拟串口工具和本人自写的串口调试工具,请自行baidu下载对应工具 在com.zxy.common.Com_Para.py中添加如下内容 #RS232串口通讯列表 串口号,波特率,…...
微信小程序开发教学系列(9)- 小程序页面优化
第9章 小程序页面优化 在开发小程序时,页面性能优化是非常重要的一项任务。优化页面性能可以提升用户体验,使小程序更加流畅和高效。本章将介绍一些常见的页面优化方法和技巧,帮助您提升小程序的性能。 9.1 页面性能优化的基本原则 页面性…...

如何将储存在Mac或PC端的PDF文件传输到移动设备呢?
iMazing是一款iOS设备管理软件,用户借助它可以将iPad或iPhone上的文件备份到PC或Mac上,还能实现不同设备之间的文件传输,能很大程度上方便用户进行文件管理。 在阅读方面,iPad和iPhone是阅读PDF的优秀选择,相较于Mac或…...

一图看懂架构划分原则:技术划分 OR 领域划分?
架构划分原则 技术划分 描述: 按技术用途组织系统组件典型示例: 分层(多层)架构 组件按技术层组织 用户界面: 与用户直接交互的部分业务规则和核心处理: 逻辑和算法与数据库交互: 数据存取和查询数据库层: 数据存储和管理 优点: 当大部分更改与技术层次对齐时适用 缺点: 域更…...

从零开始的Hadoop学习(二)| Hadoop介绍、优势、组成、HDFS架构
1. Hadoop 是什么 Hadoop是一个由Apache基金会所开发的分布式系统基础架构。主要解决,海量数据的存储和海量数据的分析计算问题。广义上来说,Hadoop通常是指一个更广泛的概念—Hadoop生态圈。 2. Hadoop 的优势 高可靠性:Hadoop底层维护多…...

问道管理:逾4600股飘红!汽车板块爆了,多股冲击涨停!
A股商场今天上午全体低开,但其后逐级上行,创业板指数上午收盘大涨超越3%,北向资金也完成净买入38亿元。 别的,A股商场半年报成绩发表如火如荼进行中,多家公司发表半年报后股价应声大涨,部分公司股价冲击涨停…...
Java 语言实现选择排序算法
【引言】 选择排序算法是一种简单但有效的排序算法。它的原理是每次从未排序的元素中选择最小(或最大)的元素,放在已排序的末尾(或开头),逐渐形成有序序列。本文将使用Java语言实现选择排序算法,…...
【C语言每日一题】05. 输出保留12位小数的浮点数
题目来源:http://noi.openjudge.cn/ch0101/05/ 05 输出保留12位小数的浮点数 总时间限制: 1000ms 内存限制: 65536kB 问题描述 读入一个双精度浮点数,保留12位小数,输出这个浮点数。 输入 只有一行,一个双精度浮点数。 输出 …...

科大讯飞永久免费GPT入口来了!!!
讯飞GPT永久免费使用入口注册链接:讯飞星火认知大模型-AI大语言模型-星火大模型-科大讯飞。 登录讯飞账号后,点击进入体验。 进入体验页面后,选择景点推荐。 笔者让其写一篇关于讯飞GPT介绍的文案。 讯飞GPT是一款由讯飞公司推出的人工智能语…...

亚马逊反馈和评论的区别
在亚马逊上,"反馈"(Feedback)和"评论"(Review)是两个不同的概念,它们分别用于描述购买者与商品或卖家之间的不同方面。 1、反馈(Feedback): 亚马逊的…...

Linux 查看当前文件夹下的文件大小
1.直接查看: ll 或者 ls -la #查看文件大小,以kb为单位 ll#查看文件大小,包含隐藏的文件,以kb为单位 ls -la2.以 M 或者 G 为单位查看,根据文件实际大小进行合适的单位展示 du -sh *...

玩转 PI 系列-看起来像服务器的 ARM 开发板矩阵-Firefly Cluster Server
前言 基于我个人的工作内容和兴趣,想要在家里搞一套服务器集群,用于容器/K8s 等方案的测试验证。 考虑过使用二手服务器,比如 Dell R730, 还搞了一套配置清单,如下: Dell R7303.5 尺寸规格硬盘CPU: 2686v4*2 内存&a…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...