如何自动为 Unity 类中的所有方法添加 Profiler 采样?
可以实现。如果只想自动查看方法级耗时,可以使用 Deep Profiling。如果要求只处理指定类,并严格使用 MyClass.MyMethodA 这样的自定义采样名称,就需要为该类插入采样代码,通常在编译或程序集后处理阶段完成。
使用 Deep Profiling 自动记录方法调用
Deep Profiling 会自动为脚本方法添加性能分析插桩,无需逐个编写 Profiler.BeginSample 和 Profiler.EndSample。在支持该功能的 Unity 环境中,可以按以下步骤操作:
- 打开
Window > Analysis > Profiler。 - 在工具栏中启用
Deep Profile。 - 运行需要分析的场景并记录数据,然后在 CPU Usage 的 Hierarchy 或 Timeline 中查看方法调用。
分析构建后的 Player 时,还需要在构建配置中启用相应的开发构建和 Deep Profiling 支持。菜单名称及支持情况应以所用 Unity 版本、目标平台和脚本后端为准。Unity 官方说明
Deep Profiling 自动生成的采样名称不保证与手写的 "MyClass.MyMethodA" 完全相同。它通常用于分析更广泛的方法调用,启用该功能也不等于只为指定类生成指定名称的 sample。
只对指定类自动插桩
如果指定类和采样名称都是硬性要求,可以采用编译期插桩或 IL weaving:
- 用配置或自定义 Attribute 标记需要分析的类。
- 在编译处理阶段找到该类中具有方法体的目标方法。
- 根据类型名和方法名生成采样名称。
- 在方法入口插入
Profiler.BeginSample,并通过finally保证退出时调用Profiler.EndSample。
对于普通同步方法,插桩后的逻辑应类似下面这样:
using UnityEngine.Profiling;
public class MyClass
{
public void MyMethodA()
{
Profiler.BeginSample("MyClass.MyMethodA");
try
{
// Original method body
}
finally
{
Profiler.EndSample();
}
}
}
finally 可以在方法提前 return 或抛出异常时结束采样。
自定义 Attribute 是元数据,还需要工具读取标记并改写方法,才能实现自动采样。仅用反射枚举方法也不会改变原有调用的执行过程。
这种方式可以让日常使用简化为在类上添加标记,但需要先建立插桩工具,并核对它与 Unity 编译流程、目标平台和脚本后端的兼容性。原问题没有提供这些环境信息,因此无法直接给出适用于该项目的具体插件配置。
用 ProfilerMarker.Auto 减少手写代码
如果可以接受在每个方法中保留一个采样作用域,ProfilerMarker.Auto() 可以省去显式的结束调用。在提供该 API 的 Unity 版本中,可以这样写:
using Unity.Profiling;
public class MyClass
{
private static readonly ProfilerMarker MethodAMarker =
new ProfilerMarker("MyClass.MyMethodA");
public void MyMethodA()
{
using (MethodAMarker.Auto())
{
// Code here
}
}
}
Auto() 返回一个作用域辅助结构,进入时开始采样,释放时结束采样。在普通同步代码中,提前返回或抛出异常时也能正确结束作用域。它自动处理的是开始和结束的配对,每个需要分析的方法仍要添加相应代码。ProfilerMarker.Auto API
使用时需要注意什么?
- Deep Profiling 会增加执行时间和内存开销,适合用于定位调用热点。确定可疑方法后,可以关闭它,再用少量明确的采样点复查耗时,避免把插桩开销当成业务开销。Unity 性能分析建议
- 对于方法重载,仅使用
类名.方法名可能无法区分不同签名。自动插桩时应明确是否把参数类型加入名称。 async方法和 coroutine 需要单独设计插桩规则。不要直接用普通同步作用域跨越await或yield;应区分实际执行片段与包含等待时间的整体耗时。- CPU 采样中的执行时间、
GC Alloc和对象长期保留的内存是不同指标。添加 sample 不等于测出了某个方法占用的全部内存。
备注:内容仅供参考。
