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…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏
一、引言 在深度学习中,我们训练出的神经网络往往非常庞大(比如像 ResNet、YOLOv8、Vision Transformer),虽然精度很高,但“太重”了,运行起来很慢,占用内存大,不适合部署到手机、摄…...
【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...
