22.Profiler窗口脚本控制

22.Unity性能分析工具-Profiler窗口脚本控制


22.1 知识点

Profiler提供的重要API

使用以下 API 前需引用命名空间:using UnityEngine.Profiling;

Mono托管堆(C#层内存)

  1. Profiler.GetMonoUsedSizeLong() — 获取当前使用的 Mono 堆内存(单位:字节),用于关注脚本(C#)对象占用的内存。
  2. Profiler.GetMonoHeapSizeLong() — 获取 Mono 堆的总大小,用来判断 Mono 内存是否接近上限。正常情况应满足:GetMonoUsedSizeLong() <= GetMonoHeapSizeLong()
  3. Profiler.usedHeapSizeLong — 当前堆中使用的内存总量,包括所有托管内存;与 GetMonoUsedSizeLong 类似但更底层,在某些平台下更准确。
using UnityEngine.Profiling;

// 1. 当前使用的 Mono 堆内存(字节)
print("当前使用的Mono堆内存: " + Profiler.GetMonoUsedSizeLong());

// 2. Mono 堆总大小
print("Mono堆的总大小: " + Profiler.GetMonoHeapSizeLong());

// 3. 当前堆使用总量(托管内存,部分平台更准确)
print("当前堆中使用的内存总量: " + Profiler.usedHeapSizeLong);

Unity 总体内存情况

  1. Profiler.GetTotalAllocatedMemoryLong() — 获取所有 Unity 正在使用的内存总量(Mono、Native、图形资源等),常用于分析整体内存走势。
  2. Profiler.GetTotalReservedMemoryLong() — 返回 Unity 从操作系统申请的内存总量(已分配 + 已预留未用)。
  3. Profiler.GetTotalUnusedReservedMemoryLong() — 返回「空闲缓存池」,即保留了但尚未分配出去的部分。

三者关系:已使用 + 未使用但已预留从系统申请的总量

using UnityEngine.Profiling;

long allocated = Profiler.GetTotalAllocatedMemoryLong();   // 正在使用的内存总量
long reserved = Profiler.GetTotalReservedMemoryLong();    // 从操作系统申请的总量
long unused = Profiler.GetTotalUnusedReservedMemoryLong(); // 保留但未分配的部分
// allocated + unused ≈ reserved
print($"已使用: {allocated}, 已预留: {reserved}, 空闲缓存: {unused}");

针对某个对象分析内存

  1. Profiler.GetRuntimeMemorySizeLong(object) — 获取某个 Unity 对象占用的内存(估算值),包括纹理、网格、GameObject 等。
using UnityEngine.Profiling;

GameObject obj = new GameObject("Test");
long size = Profiler.GetRuntimeMemorySizeLong(obj);  // 单位:字节
print($"该对象占用内存约: {size} 字节");

特定分析部分逻辑

  1. Profiler.BeginSample / Profiler.EndSample — 开始/结束一个自定义采样区段,在 Profiler 的 CPU 模块中显示为一条标记;二者需成对使用。建议仅在开发环境使用,可用 #if UNITY_EDITOR 包裹避免打进正式包。
using UnityEngine.Profiling;

Profiler.BeginSample("我的热点逻辑");
// 要分析的代码
for (int i = 0; i < 1000; i++) { /* ... */ }
Profiler.EndSample();

获取记录详细数据

  1. Profiler.logFile、Profiler.enableBinaryLog — 将 Profiler 数据写入 .raw 文件,用于离线分析(可导入 Unity Profiler 或上传给 QA)。一般在游戏中做「开始采集 / 停止采集」功能,采集一段时间后再上传或本地分析。
using UnityEngine.Profiling;

// 指定输出路径
Profiler.logFile = Application.persistentDataPath + "/myProfileData.raw";
Profiler.enableBinaryLog = true;   // 开始记录
// 运行一段时间后……
// yield return new WaitForSeconds(10f);
Profiler.enableBinaryLog = false;  // 停止记录
// 之后可上传 myProfileData.raw 或导入 Profiler 查看

更多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

×

喜欢就点赞,疼爱就打赏