Unity内存与资源管理

2023-11-09

内存管理是程序开发的核心问题,而资源的使用又与内存息息相关,因此本章想要梳理整个开发流程中Unity对于内存与资源的管理方式。

一、内存基础

1.1 基础概念

内存是暂时存放CPU中的运算数据,与硬盘等外部存储器交换的数据。在操作系统中,内存分为物理内存与虚拟内存。

CPU读取数据

CPU进行数据处理时,从内存或缓存中取出指令,放入指令寄存器,并对指令译码进行分解,进而对数据进行处理。从内存中读取数据很慢,通常CPU会将之前读取的数据缓存在多级Cache中,提升数据访问效率。因此,CPU会先从Cache中查找数据,若没有找到(Cache Miss),才会访问内存。

物理内存:物理内存可以理解为运行时内存,其对应于实际的存储硬件。

虚拟内存:管理不同进程使用的进程内部内存地址和物理内存地址的映射体系。

页:内存管理、映射中的基本单位。

内存交换(页面交换):当系统内存不足时,操作系统会创建交换文件(Swap file)或者分页文件(Paging file)记录暂时不用的物理内存页面中的数据,并将这部分数据交换到硬盘上,节省更多的物理内存。

1.2 移动设备与PC差异

  • 没有独立显卡,显存与CPU数据会存储在同一区域。
  • CPU的Cache与内存更小。因此移动端会严格限制资源大小。
  • 没有内存交换(IO速度慢、可擦写次数少)
  • IOS可以进行内存压缩:将不活跃的内存压缩到特定空间。

1.3 Android内存分布

上图可以看出运行时内存包括:方法区、堆栈以及线程内存。

Android中对内存有4种统计方式:VSS(虚拟内存)、RSS(实际物理内存:APP+所有共享内存)、PSS(APP+平均共享库内存)、USS(APP内存)。通常使用PSS来统计。

Android对进程的管理策略称为LMK(Low Memory Killer),kill优先级如下:

1.4 IOS内存分布

IOS内存分布

Clear Memory包括系统框架数据、可执行的二进制数据以及内存映射文件。Clear Memory以外的内存都是Dirty Memory。

当系统存在内存压力时,会先卸载一部分Clear Memory,当再次需要时会对其重新创建。但系统无法对Dirty Memory进行卸载,直到到达App的限制才会被终止回收。内存不足时,IOS会对Dirty Memory做压缩处理。

IOS中Resident Memory指的是App分配的物理内存。当App向系统申请内存时,虚拟内存是直接增长的。但如果申请完的内存并没有向里面写入数据,它并不会产生实际的物理内存分配。

iOS的进程管理策略称为Jetsam,GitHub有人测试了其kill进程的优先级:

Jetsam优先级

二、Unity内存与GC

从Editor与Runtime比较,在Runtime时,只有Load资源才会影响内存,而Editor模式下,为了方便开发,只要打开Unity资源就会被加载(Unity打开很慢,2019.3的Asset Pipeline 2.0做了优化)。

2.1 Mono与IL2CPP的跨平台

Mono与IL2CPP是Unity的两种跨平台解决方案,目前官方推荐使用IL2CPP。

Mono跨平台流程

Mono的跨平台方案:编译器mcs将代码编译为IL,通过Mono运行时中的编译器将IL编译成对应平台的原生码。

Unity Mono是针对每个特定平台做了处理,因此才能跨平台。若出现新的硬件平台,则需要额外造轮子,其可移植性很差,因此Unity给出了IL2CPP方案。并且IL2CPP相比Mono有一定的性能提升。

IL2CPP方案流程(来自官方文档)

编译工程时,IL2CPP将Unity Scripting API 代码编译为常规 .NET DLL(托管程序集)。将所有托管程序集转换为标准C++代码。使用本机平台编译器编译生成的C++代码和IL2CPP的运行时部分。最后将代码链接到可执行文件或 DLL,具体取决于目标平台。

IL2PP相比于Mono,最大的变化在于由JIT编译变为了AOT编译。由此带来的变化体现在:(1)开发编译时间变长;(2)无法动态生成代码;(3)应用程序体积变小;(4)应用程序启动时间短。

在开发过程中可以选择Mono,提升开发效率,发布应用时使用IL2CPP得到更好的程序性能。

2.2 Unity VM GC

当Unity VM需要分配内存时,会检查当前内存。若内存足够时,可以直接分配内存,但内存不足时会触发GC,再次检测内存。若此时内存仍然不足,VM会向操作系统申请内存。

触发GC时,VM会暂停所有线程,可能引起程序卡顿。Unity采用了BOEHM处理GC,其为标记清除法。在标记阶段通过访问根节点,并遍历到叶子节点,最终将所有存在引用的内存都标记出来,清除未被标记的托管内存。

Unity的VM以Block管理内存,当一个Block连续6次GC没有被访问到(很难触发),这块内存会被返回给系统。

由于此种处理方式没有内存压缩,并且可能出现内存黑名单,因此容易出现内存碎片。在开发过程中,要尽量减少内存的申请,申请的内存尽量保持连续,对于资源加载应该优先加载较大的资源。

2.3 Unity内存分布

Unity内存分布

Unity内存分为Native堆内存、第三方库、虚拟机以及GfxDriver。Native堆内存中存储由Unity底层管理的数据,如音频、视频、Texture、Mesh、GameObject等。第三库常见的如tolua、Wwise。虚拟机通常指C#所产生的内存。GfxDriver是指当前驱动使用的Textures、RenderTargets、Shaders和Mesh数据内存。

三、Editor Asset

Unity 中的资源工作流程(来自官方文档)

Unity中的资源通常是指3D模型、音频文件、图像等用于程序使用的数据(代码数据也是一种资源)。程序开发阶段,将外部资源导入或复制到Asset目录下,Unity会监听到所导入的数据,并生成相应的Unity默认资源。

3.1 创建asset

Unity检测到新资源(文件夹)时会向此资源分配GUID,这是Unity在内部使用的ID,用于索引资源,以便Unity移动或重命名此资源不会破坏引用关系。

Unity对导入的外部文件格式不会进行修改,对内置格式资源(prefab/material/unity等),Unity以YAML格式进行存储。

prefab在Unity中的存储格式

文件前两行是文件格式版本注释,后续以--- !u!classID &fileID对组件数据进行标记。classID是Unity为组件类型分配的id,fileID为prefab中组件实例化的局部id,由此可以进行索引。上图GameObject挂载了3个组件,所以可以看到m_Component通过fileID映射到相应的组件实例。由于EventSystem是自定义组件,由此可以看到m_Script通过guid来引用到相应的代码资源。

由于这种格式化的存储方式,在非Unity Editor情况下处理或者查找带有特定参数的资源,可以通过纯文本替换或查找处理。(需要以下设置)

以文本格式存储序列化资源

3.2 监听资源导入

Unity提供了用于监听资源导入的基类,方便开发者对资源做标准化处理,具体基类如下:

来自Unity用户手册

3.3 资源处理

Unity在导入资源后,会在Library文件夹下生成真正用于Unity处理的资源。例如,Unity 将 .png 图像文件导入为纹理时,在运行时不会使用原始的 .png 格式数据,而是创建新的图形格式,将其存储在项目的Library文件夹中。Unity的Texture类会使用此导入版本,然后Unity将其上传到GPU进行实时显示。

除了Library,Unity会在Asset文件夹相同位置生成资源的.meta文件,用以记录资源设置参数与GUID。

meta文件

在Unity 2020以前的版本可以通过guid,在Library下搜索到Unity生成的资源。在Unity 2020之后的版本,会在Library下生成ArtifactDB和SourceAssetDB文件。

SourceAssetDB包含.meta相关数据(上次修改日期、文件内容哈希、GUID和其他元数据信息),由此判断是否需要重新导入资源。

ArtifactDB包含每个源资源的导入结果的信息。每个Artifact都包含导入依赖项信息、Artifact元数据信息和 Artifact文件列表。

从上述资源加载流程来看,项目中经常遇到资源引用丢失:(1)美术资源与meta没有一起上传,导致prefab无法通过guid找到资源。(2)美术替换资源时,先删除原有资源,再导入创建新资源,导致原有的prefab引用的guid失效。

对于漏传meta的情况,可在提交版本文件时做强制检测,若Asset下新增资源必须要有对应的meta文件。对于美术资源的替换,不能在Unity Editor下直接删除文件,需要通过import替换,或者在文件夹中替换资源再打开Unity。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity内存与资源管理 的相关文章

  • Unity中UI框架的使用1-添加面板、显示Loading页面

    其中BasePanel和Canvas都是挂在面板的预制物上的 1 导入我们的UI框架 本篇文章中有用的是两个UIPanelType NUIManager和NBasePanel 会放在文章最后供大家使用 2 先将我们做好的Panel设置成预制
  • unity的LOD组件

    本文转载自http blog csdn net huutu article details 52106468 LOD是Level Of Detais 的简称 多细节层次 在游戏场景中 根据摄像机与模型的距离 来决定显示哪一个模型 一般距离近
  • unity中创建询问弹出窗口

    在开发过程中进程会遇到需要弹出一个窗口询问用户是否进行的操作 今天就来制作一个这样弹出窗口 然后根据弹出窗口的选择内容不同进行不同的操作 本例中主要是为了删除一个数据 而在删除数据操作前需要得到用户的一个确认操作 这里面主要用到了Notif
  • C/C++内存泄漏与检测

    该死系统存在内存泄漏问题 项目中由于各方面因素 总是有人抱怨存在内存泄漏 系统长时间运行之后 可用内存越来越少 甚至导致了某些服务失败 内存泄漏是最难发现的常见错误之一 因为除非用完内存或调用malloc失败 否则都不会导致任何问题 实际上
  • unity后台加密时间锁

    前言 在做一些项目的时候 有些不良甲方在给完项目后会有不给尾款的情况 之前都是加一些水印啥的 感觉不是很方便 第一不美观 第二如果甲方给完尾款后还得重新打包去水印 然后又做过一个本地的时间锁 等到时间 程序直接退出 但是感觉还是不方便 有时
  • 【IMGUI】 各种辅助类 EditorGUIUtility、EditorUtility、GUIUtility、GUILayoutUtility

    EditorGUIUtility class in Editor 继承自 GUIUtility EditorGUI 的各种辅助程序 EditorGUIUtility currentViewWidth 我尝试打印了下这个值和position
  • Unity 键盘控制人物移动——之输入方式代码的编写

    键盘输入 控制人物移动 在我们制作游戏中最常见的需求之一就是使用键盘移动游戏角色 那么我们首先需要获取键盘输入 以下提供两种方法获取键盘 这里尽量通过截图解释让大家理解代码的含义 GetInput void FixedUpdate Move
  • Unity保存图片到相册

    Unity保存图片到Android相册 Java 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
  • Unity打包WebGL的优化常用操作?

    1 贴图部分优化 如果贴图格式时2048 在不影响画面效果的情况下 改成1024或者5 12 还可以缩小包体 2 压缩和解压缩问题 WebGL打包的时候分三种压缩情况 gzip 比Brotli文件打 但打包快 http和https都支持 B
  • Mecanim Any State

    Any State表示任意状态 任意状态是 一个一直存在的特殊状态 他的存在是为了保证你在无意转移至某个你当前正处于的特殊状态而准备的 为你的状态机中的每个状态设置相同的对外转移是一个快捷的方式 假如有Walk Run Fly Die这四个
  • java中Keytool的使用总结

    java中Keytool的使用总结 2011 02 26 15 30 15 分类 在申请Android Map API Key的时候使用到了java中Keytool 下面转一篇介绍java中Keytool的文章 http blog csdn
  • 作用域和内存问题

    文章目录 一 基本类型和引用类型的值 基本类型和引用类型的区别 1 动态的属性 2 复制变量值 3 传递参数 4 监测类型 二 执行环境及作用域 1 延长作用域链 2 没有块级作用域 一 基本类型和引用类型的值 变量可能包括两种不同的数据类
  • Unity旋转以及万向锁问题

    我之前研读了一些关于unity旋转相关的博客 一直想抽个时间写个总结 但是由于实习太忙一直没有写 趁着今天请了假晚上有时间把这段时间一些学习心得写出来 Unity inspector面板中的Rotation 在unity中 想必大家最先接触
  • unity dots jobSystem 记录

    Looking for a way to get started writing safe multithreaded code Learn the principles behind our Job System and how it w
  • 【原神游戏开发日志1】缘起

    原神游戏开发日志1 缘起 版权声明 本文为 优梦创客 原创文章 您可以自由转载 但必须加入完整的版权声明 文章内容不得删减 修改 演绎 相关学习资源见文末 大家好 最近看到原神在TGA上频频获奖 作为一个14年经验的游戏开发行业的老兵 我就
  • mixamo根动画导入UE5问题:滑铲

    最近想做一个跑酷游戏 从mixamo下载滑铲动作后 出了很多动画的问题 花了两周时间 终于是把所有的问题基本上都解决了 常见问题 1 动画序列 人物不移动 2 动画序列 人物移动朝向错误 3 蒙太奇 人物移动后会被拉回 4 蒙太奇 动画移动
  • 【Unity】如何让Unity程序一打开就运行命令行命令

    背景 Unity程序有时依赖于某些服务去实现一些功能 此时可能需要类似打开程序就自动运行Windows命令行命令的功能 方法 using UnityEngine using System Diagnostics using System T
  • 【转载】【Unity】WebSocket通信

    1 前言 Unity客户端常用的与服务器通信的方式有socket http webSocket 本文主要实现一个简单的WebSocket通信案例 包含客户端 服务器 实现了两端的通信以及客户端向服务器发送关闭连接请求的功能 实现上没有使用U
  • 【Unity】运行时创建曲线(贝塞尔的运用)

    Unity 运行时创建线 贝塞尔的运用 1 实现的目标 在运行状态下创建一条可以使用贝塞尔方法实时编辑的网格曲线 2 原理介绍 2 1 曲线的创建 unity建立网格曲线可以参考 Unity程序化网格体 的实现方法 主要分为顶点 三角面 U
  • 游戏开发常见操作梳理系列之——玩家信息的显示系统

    在游戏中 有不少游戏在左上角会出现玩家的头像和等级以及血量 这就是玩家的信息显示系统 那么这些是如何制作的呢 接下来我将讲讲代码的操作 其它操作我会在其它笔记中一一说明 敬请期待 信息的显示相当简单就是控制一些UI 然后在其它系统里面填写相

随机推荐

  • 算法题:(二分搜索)

    class Solution public int binarySearch vector
  • vue.js -- 动态组件&异步组件

    目录 动态组件 点击切换组件 优化点击切换组件 使用component标签优化代码 使用keep alive标签完善功能 异步组件 总结 动态组件 根据数据的变化 动态切换组件的显示 点击切换组件 首先定义两个子组件 子组件 app com
  • 读《游戏之旅--我的编程感悟》有感

    我不是学计算机的 但此书给我的感触颇深 此书成于2005年 我真希望自己能早6年读到这本书呀 2007年大学的时候就读到 作者叫云风 个人主页 www codingnow com 是个技术高手 网易游戏开发部门的重要人物 他书中有这样一段话
  • 【RabbitMQ教程】Work queues 工作队列模式

    目录 前言 Work queues工作模式介绍 消息模型 适用场景 消费策略 重要 消费策略选择 消费策略代码示例 轮询分发 1 定义生产者和消费者 2 运行程序 3 结果分析 公平分发 1 定义生产者和消费者 2 运行程序 3 结果分析
  • 憨批的语义分割3——unet模型详解以及训练自己的unet模型(划分斑马线)

    憨批的语义分割3 unet模型详解以及训练自己的unet模型 划分斑马线 学习前言 模型部分 什么是unet模型 unet模型的代码实现 1 主干模型Mobilenet 2 unet的Decoder解码部分 代码测试 训练部分 训练的是什么
  • 蓝桥杯-第六届蓝桥杯C语言A组/B组/C组-Python题解

    目录 方程整数解 星系炸弹 奇妙的数字 牌型种数 手链样式 饮料换购 奖券数目 三羊献瑞 加法变乘法 隔行变色 立方尾不变 方程整数解 方程 a 2 b 2 c 2 1000 这个方程有整数解吗 有 a b c 6 8 30 就是一组解 你
  • 猫眼美团滑块

    猫眼演场会下单会弹出美团的滑块验证码 使用js过滑块 想看演唱会但是又抢不到票 用python写一个猫眼自动下单
  • 2020年最常见的25个Web开发面试问题

    Java面试笔试面经 Java技术每天学习一点 Java面试 关注不迷路 作者 Team Codegiant 译者 王强 策划 李俊辰 本文最初发布于 Medium 网站 经原作者授权由 InfoQ 中文站翻译并分享 你把闹钟设定在了下午
  • 软件测试值不值得学,2023软件测试行情分析

    目录 1 人们的生活离不开软件 有软件的地方就有测试 2 测试工程师特别是自动化测试工程师的需求会越来越大 3 软件测试经验越丰富越受欢迎 不存在35岁限制 4 所有新兴行业比如chat gtp 车载系统等都需要测试工程师 薪资 就业 软件
  • Office2010安装步骤

    这是一篇我自己写于17年8月27日的office2010的安装教程 发现挺多人都不会安装或者激活 所以特地写了这篇文 安装office2010前请确保电脑中没有安装其它版本的office软件 否则可能造成两个版本的office不能正常使用
  • MATLAB:矩阵(基础知识)

    一 数组的创建和操作 1 矩阵的输入 gt gt A A gt gt B 6 5 3 B 6 5 3 gt gt C B C 6 5 3 2 调用矩阵 gt gt A 1 2 3 4 5 A 1 2 3 4 5 gt gt a1 A 1 访
  • kvm设置桥接网卡

    kvm默认的网卡模式为nat 虚拟主机可访问外网 但外部无法访问虚拟主机 将其改为桥接模式以实现内外互通 环境 centos6图形界面下 有virtual machine manager 程序 整个过程就两步 1 修改物理机网卡为桥接模式
  • SpringBoot报错:Cannot call isReadOnlyBeforeAttachedToSession when isReadOnlySettingAvailable == true

    错误后边会说明哪个实体类导致的 在实体类上加上 Proxy lazy false
  • Apache Beam实战指南

    https mp weixin qq com s biz MzU1NDA4NjU2MA mid 2247492538 idx 2 sn 9a2bd9fe2d7fd681c10ebd368ef81c9c chksm fbea5a75cc9dd
  • [原创]LoadRunner 12.02 录制脚本时提示无Internet访问,如何解决?

    在使用LoadRunner 12 02 进行录制脚本时提示无Internet访问 如下图 翻译中文如下 可以尝试以下方式解决 点击弹出框中的 Yes 即可 若还是有问题 尝试以下方式 1 LR12走的是证书机制 你按照我附件 图片1 中提供
  • springboot集成springsecurity + jwt的使用

    当项目中要用到用户的认证及权限的时候我们一般会使用 springSecurity来解决 引入 引入很简单
  • 学习若依框架----之----获取登录登录系统、ip、浏览器信息

    文章目录 1 导入需要用到的依赖 2 IP获取 3 AddressUtils 获取地址类 4 登录日志管理工具 4 SpringUtils获取bean工具 5 客户端工具 6 使用 7 测试 8 数据库记录 若依里面 创建登录日志是根据异步
  • USDT信用卡和转账入账接口

    class Usdtpay public function index data this gt request gt param uid data uid token data token type data type changeid
  • 经验模态分解(EMD)

    目录 1 背景 2 时间序列平稳性 3 EMD 方法 4 EMD 过程 5 EMD 方法的缺陷 6 Python 1 背景 实际工程测量中由于测量系统受外界环境影响经常在测量信号中产生趋势项 趋势项是指信号中周期大于采样长度的频率成分 通常
  • Unity内存与资源管理

    内存管理是程序开发的核心问题 而资源的使用又与内存息息相关 因此本章想要梳理整个开发流程中Unity对于内存与资源的管理方式 一 内存基础 1 1 基础概念 内存是暂时存放CPU中的运算数据 与硬盘等外部存储器交换的数据 在操作系统中 内存