22.Unity性能分析工具-Profiler窗口脚本控制
22.1 知识点
Profiler提供的重要API
使用以下 API 前需引用命名空间:using UnityEngine.Profiling;
Mono托管堆(C#层内存)
Profiler.GetMonoUsedSizeLong()
获取当前使用的 Mono 堆内存(单位:字节),用于关注脚本(C#)对象占用的内存。
示例:print("当前使用的Mono堆内存:" + Profiler.GetMonoUsedSizeLong());Profiler.GetMonoHeapSizeLong()
获取 Mono 堆的总大小,用来判断 Mono 内存是否接近上限。
示例:print("Mono堆的总大小:" + Profiler.GetMonoHeapSizeLong());
正常情况应满足:GetMonoUsedSizeLong() <= GetMonoHeapSizeLong()。Profiler.usedHeapSizeLong
当前堆中使用的内存总量,包括所有托管内存。表示 C# GC 堆当前被使用的内存(与 GetMonoUsedSizeLong 类似,但更底层),在某些平台下更准确。
示例:print("当前堆中使用的内存总量;包括所有托管内存" + Profiler.usedHeapSizeLong);
Unity 总体内存情况
Profiler.GetTotalAllocatedMemoryLong()
获取所有 Unity 正在使用的内存总量(包括 Mono、Native、图形资源等),常用于分析整体内存走势。
示例:long totalMemory = Profiler.GetTotalAllocatedMemoryLong();Profiler.GetTotalReservedMemoryLong()
返回 Unity 从操作系统申请的内存总量,不管是否已经用上。包含:当前使用中的内存(已分配)、尚未使用但已预留的空间(为减少频繁申请)。Profiler.GetTotalUnusedReservedMemoryLong()
返回 Unity 保留了但尚未分配出去的内存部分,即「空闲缓存池」。
三者关系:
正在使用中的内存总量 + 保留了但尚未分配出去的内存部分 ≈ Unity 从操作系统申请的内存总量
即:GetTotalAllocatedMemoryLong() + GetTotalUnusedReservedMemoryLong() ≈ GetTotalReservedMemoryLong()。
针对某个对象分析内存
- Profiler.GetRuntimeMemorySizeLong(object)
获取某个对象占用的内存(估算值),包括纹理、网格等对象的实际内存占用。
示例:Profiler.GetRuntimeMemorySizeLong(obj);(obj 可为 GameObject 等 Unity 对象)。
特定分析部分逻辑
- Profiler.BeginSample / Profiler.EndSample
开始/结束一个自定义采样区段,常用于标记性能热点段,二者需成对使用。
该区段会在 Unity Profiler 的 CPU 模块中显示为一条标记,建议仅在开发环境使用,可通过#if UNITY_EDITOR包裹避免构建时存在。
用法:在要分析的逻辑前写Profiler.BeginSample("标记名");,逻辑后写Profiler.EndSample();。
获取记录详细数据
- Profiler.logFile、Profiler.enableBinaryLog
可将 Profiler 数据写入文件,用于离线分析(例如上传给 QA 或分析工具)。即在运行时手动采集 Unity Profiler 的原始性能数据(.raw 文件),这些数据可以导入 Unity Profiler 界面中进行离线分析。
一般可在游戏中嵌入一个开启功能,采集一定时间的性能数据,再通过代码上传采样数据到服务器。
示例流程:设置Profiler.logFile = Application.persistentDataPath + "/myProfileData.raw",Profiler.enableBinaryLog = true开始记录,采集若干秒后设为false停止记录。
更多Profiler API
更完整的接口说明见官方文档:
https://docs.unity3d.com/cn/2022.3/ScriptReference/Profiling.Profiler.html
22.2 知识点代码
Lesson22_Unity性能分析工具_Profiler窗口_脚本控制.cs
using UnityEngine;
using UnityEngine.Profiling;
public class Lesson22_Unity性能分析工具_Profiler窗口_脚本控制 : MonoBehaviour
{
void Start()
{
#region 知识点一 Profiler提供的重要API
/* 需要引用命名空间 using UnityEngine.Profiling; */
#region Mono托管堆(C#层内存)
/* 1. 获取当前使用的 Mono 堆内存(单位:字节);关注脚本(C#)对象占用的内存 */
print("当前使用的Mono堆内存:" + Profiler.GetMonoUsedSizeLong());
/* 2. 获取 Mono 堆的总大小;用来判断 Mono 内存是否接近上限 */
print("Mono堆的总大小:" + Profiler.GetMonoHeapSizeLong());
/* 正常来说 GetMonoUsedSizeLong() <= GetMonoHeapSizeLong() */
/* 3. 当前堆中使用的内存总量,包括所有托管内存;
* C# GC 堆当前被使用的内存(与 GetMonoUsedSizeLong 类似,但更底层),在某些平台下更准确。 */
print("当前堆中使用的内存总量;包括所有托管内存" + Profiler.usedHeapSizeLong);
#endregion
#region Unity 总体内存情况
/* 4. 获取所有 Unity 正在使用的内存总量(包括 Mono、Native、图形资源等);常用于分析整体内存走势 */
long totalMemory = Profiler.GetTotalAllocatedMemoryLong();
print("Unity 正在使用的内存总量:" + totalMemory);
/* 5. 返回 Unity 从操作系统申请的内存总量,不管是否已经用上;
* 包含:当前使用中的内存(已分配)、尚未使用但已预留的空间(为减少频繁申请) */
print("Unity 从操作系统申请的内存总量:" + Profiler.GetTotalReservedMemoryLong());
/* 6. 返回 Unity 保留了但尚未分配出去的内存部分,即“空闲缓存池” */
print("Unity 保留了但尚未分配出去的内存部分:" + Profiler.GetTotalUnusedReservedMemoryLong());
/* 正在使用中的内存总量 + 保留了但尚未分配出去的内存部分 ≈ Unity 从操作系统申请的内存总量
* GetTotalAllocatedMemoryLong() + GetTotalUnusedReservedMemoryLong() ≈ GetTotalReservedMemoryLong() */
#endregion
#region 针对某个对象分析内存
/* 7. 获取某个对象占用的内存(估算值);包括纹理、网格等对象的实际内存占用 */
GameObject obj = new GameObject();
Profiler.GetRuntimeMemorySizeLong(obj);
#endregion
#region 特定分析部分逻辑
/* 8. 开始一个自定义采样区段;常用于标记性能热点段,配合 EndSample() 使用。
* 会在 Unity Profiler 的 CPU 模块中显示为一条标记,建议仅在开发环境使用。
* 可通过 #if UNITY_EDITOR 包裹避免构建时存在。 */
Profiler.BeginSample("MrTaoCode");
/* 做一些逻辑或渲染操作 */
for (int i = 0; i < 99999; i++)
{
float x = Mathf.Sqrt(i);
}
/* 结束采样区段 */
Profiler.EndSample();
#endregion
#region 获取记录详细数据
/* 9. 可将 Profiler 数据写入文件,用于离线分析(比如上传给 QA 或分析工具)。
* 在运行时手动采集 Unity Profiler 的原始性能数据(.raw 文件),可导入 Profiler 界面中离线分析。
* 一般可在游戏中嵌入开启功能,采集一定时间的性能数据,再主动上传采样数据到服务器。 */
Profiler.logFile = Application.persistentDataPath + "/myProfileData.raw";
Profiler.enableBinaryLog = true; /* 开始记录 */
/* yield return new WaitForSeconds(10f); */
Profiler.enableBinaryLog = false; /* 停止记录 */
#endregion
#endregion
#region 知识点二 更多Profiler API
/* https://docs.unity3d.com/cn/2022.3/ScriptReference/Profiling.Profiler.html */
#endregion
}
void Update()
{
Profiler.BeginSample("MrTaoCode");
/* 做一些逻辑或渲染操作 */
for (int i = 0; i < 99999; i++)
{
float x = Mathf.Sqrt(i);
}
/* 结束采样区段 */
Profiler.EndSample();
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com