270 lines
7.7 KiB
C#
270 lines
7.7 KiB
C#
|
|
using UnityEngine;
|
||
|
|
using UnityEngine.Profiling;
|
||
|
|
|
||
|
|
namespace TracyProfiler
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// Tracy 管理器 - 负责初始化和每帧更新
|
||
|
|
/// 在场景中添加此组件以启用 Tracy 性能分析
|
||
|
|
/// </summary>
|
||
|
|
[DefaultExecutionOrder(-9999)] // 确保最早执行
|
||
|
|
public class TracyManager : MonoBehaviour
|
||
|
|
{
|
||
|
|
[Header("Tracy 设置")]
|
||
|
|
[Tooltip("启动时自动初始化 Tracy")]
|
||
|
|
[SerializeField] private bool enableOnStart = true;
|
||
|
|
|
||
|
|
[Tooltip("每帧自动标记帧边界")]
|
||
|
|
[SerializeField] private bool markFrames = true;
|
||
|
|
|
||
|
|
[Header("性能监控")]
|
||
|
|
[Tooltip("监控帧率和帧时间")]
|
||
|
|
[SerializeField] private bool monitorFrameRate = true;
|
||
|
|
|
||
|
|
[Tooltip("监控内存使用")]
|
||
|
|
[SerializeField] private bool monitorMemory = true;
|
||
|
|
|
||
|
|
[Tooltip("监控渲染统计")]
|
||
|
|
[SerializeField] private bool monitorRendering = true;
|
||
|
|
|
||
|
|
[Tooltip("监控物理系统")]
|
||
|
|
[SerializeField] private bool monitorPhysics = true;
|
||
|
|
|
||
|
|
[Header("高级选项")]
|
||
|
|
[Tooltip("在编辑器中也启用 Tracy")]
|
||
|
|
[SerializeField] private bool enableInEditor = true;
|
||
|
|
|
||
|
|
[Tooltip("显示调试信息")]
|
||
|
|
[SerializeField] private bool showDebugInfo = false;
|
||
|
|
|
||
|
|
private static TracyManager instance;
|
||
|
|
|
||
|
|
public static TracyManager Instance => instance;
|
||
|
|
|
||
|
|
private void Awake()
|
||
|
|
{
|
||
|
|
// 单例模式
|
||
|
|
if (instance != null && instance != this)
|
||
|
|
{
|
||
|
|
Debug.LogWarning("[Tracy] 检测到多个 TracyManager 实例,销毁多余的实例");
|
||
|
|
Destroy(gameObject);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
instance = this;
|
||
|
|
DontDestroyOnLoad(gameObject);
|
||
|
|
|
||
|
|
// 编辑器检查
|
||
|
|
if (!Application.isPlaying)
|
||
|
|
return;
|
||
|
|
|
||
|
|
#if UNITY_EDITOR
|
||
|
|
if (!enableInEditor)
|
||
|
|
{
|
||
|
|
Debug.Log("[Tracy] 编辑器模式下已禁用");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
// 初始化 Tracy
|
||
|
|
if (enableOnStart)
|
||
|
|
{
|
||
|
|
Tracy.Initialize();
|
||
|
|
|
||
|
|
if (Tracy.IsInitialized)
|
||
|
|
{
|
||
|
|
Tracy.Message("Unity Application Started");
|
||
|
|
Tracy.SetThreadName("Main Thread");
|
||
|
|
|
||
|
|
if (showDebugInfo)
|
||
|
|
{
|
||
|
|
LogSystemInfo();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void Update()
|
||
|
|
{
|
||
|
|
using (Tracy.Zone("TracyManager.Update"))
|
||
|
|
{
|
||
|
|
// 监控帧率
|
||
|
|
if (monitorFrameRate)
|
||
|
|
{
|
||
|
|
MonitorFrameRate();
|
||
|
|
}
|
||
|
|
|
||
|
|
// 监控内存
|
||
|
|
if (monitorMemory)
|
||
|
|
{
|
||
|
|
MonitorMemory();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void LateUpdate()
|
||
|
|
{
|
||
|
|
using (Tracy.Zone("TracyManager.LateUpdate"))
|
||
|
|
{
|
||
|
|
// 在每帧末尾标记帧边界
|
||
|
|
if (markFrames)
|
||
|
|
{
|
||
|
|
Tracy.MarkFrame();
|
||
|
|
}
|
||
|
|
|
||
|
|
// 监控渲染统计
|
||
|
|
if (monitorRendering)
|
||
|
|
{
|
||
|
|
MonitorRendering();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void FixedUpdate()
|
||
|
|
{
|
||
|
|
using (Tracy.Zone("TracyManager.FixedUpdate"))
|
||
|
|
{
|
||
|
|
// 监控物理系统
|
||
|
|
if (monitorPhysics)
|
||
|
|
{
|
||
|
|
MonitorPhysics();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void OnDestroy()
|
||
|
|
{
|
||
|
|
if (instance == this)
|
||
|
|
{
|
||
|
|
Tracy.Message("Unity Application Shutting Down");
|
||
|
|
Tracy.Shutdown();
|
||
|
|
instance = null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void OnApplicationQuit()
|
||
|
|
{
|
||
|
|
Tracy.Message("Unity Application Quit");
|
||
|
|
Tracy.Shutdown();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void OnApplicationPause(bool pauseStatus)
|
||
|
|
{
|
||
|
|
if (pauseStatus)
|
||
|
|
{
|
||
|
|
Tracy.Message("Application Paused");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Tracy.Message("Application Resumed");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#region Performance Monitoring
|
||
|
|
|
||
|
|
private void MonitorFrameRate()
|
||
|
|
{
|
||
|
|
float fps = 1.0f / Time.unscaledDeltaTime;
|
||
|
|
float frameTime = Time.unscaledDeltaTime * 1000.0f;
|
||
|
|
|
||
|
|
Tracy.Plot("FPS", fps);
|
||
|
|
Tracy.Plot("Frame Time (ms)", frameTime);
|
||
|
|
Tracy.Plot("Time Scale", Time.timeScale);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void MonitorMemory()
|
||
|
|
{
|
||
|
|
// GC 内存
|
||
|
|
long totalMemory = System.GC.GetTotalMemory(false);
|
||
|
|
Tracy.Plot("GC Memory (MB)", totalMemory / (1024.0 * 1024.0));
|
||
|
|
|
||
|
|
// Unity Profiler 内存统计
|
||
|
|
long usedHeap = Profiler.usedHeapSizeLong;
|
||
|
|
long totalAllocated = Profiler.GetTotalAllocatedMemoryLong();
|
||
|
|
long totalReserved = Profiler.GetTotalReservedMemoryLong();
|
||
|
|
|
||
|
|
Tracy.Plot("Used Heap (MB)", usedHeap / (1024.0 * 1024.0));
|
||
|
|
Tracy.Plot("Total Allocated (MB)", totalAllocated / (1024.0 * 1024.0));
|
||
|
|
Tracy.Plot("Total Reserved (MB)", totalReserved / (1024.0 * 1024.0));
|
||
|
|
|
||
|
|
// 纹理内存
|
||
|
|
Tracy.Plot("Texture Memory (MB)", Profiler.GetAllocatedMemoryForGraphicsDriver() / (1024.0 * 1024.0));
|
||
|
|
}
|
||
|
|
|
||
|
|
private void MonitorRendering()
|
||
|
|
{
|
||
|
|
// 渲染统计
|
||
|
|
Tracy.Plot("SetPass Calls", Profiler.GetRuntimeMemorySizeLong(null));
|
||
|
|
Tracy.Plot("Draw Calls", UnityEngine.Rendering.FrameTimingManager.GetLatestTimings(1, null));
|
||
|
|
Tracy.Plot("Triangles", 0); // 需要通过 Stats 获取
|
||
|
|
Tracy.Plot("Vertices", 0); // 需要通过 Stats 获取
|
||
|
|
}
|
||
|
|
|
||
|
|
private void MonitorPhysics()
|
||
|
|
{
|
||
|
|
// 物理对象计数
|
||
|
|
int rigidbodyCount = FindObjectsOfType<Rigidbody>().Length;
|
||
|
|
int colliderCount = FindObjectsOfType<Collider>().Length;
|
||
|
|
|
||
|
|
Tracy.Plot("Rigidbody Count", rigidbodyCount);
|
||
|
|
Tracy.Plot("Collider Count", colliderCount);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void LogSystemInfo()
|
||
|
|
{
|
||
|
|
Tracy.Message($"Device: {SystemInfo.deviceModel}");
|
||
|
|
Tracy.Message($"OS: {SystemInfo.operatingSystem}");
|
||
|
|
Tracy.Message($"CPU: {SystemInfo.processorType} ({SystemInfo.processorCount} cores)");
|
||
|
|
Tracy.Message($"Memory: {SystemInfo.systemMemorySize} MB");
|
||
|
|
Tracy.Message($"GPU: {SystemInfo.graphicsDeviceName}");
|
||
|
|
Tracy.Message($"Graphics API: {SystemInfo.graphicsDeviceType}");
|
||
|
|
Tracy.Message($"Unity Version: {Application.unityVersion}");
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region Public API
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 手动触发帧标记(如果禁用了自动标记)
|
||
|
|
/// </summary>
|
||
|
|
public void ManualFrameMark()
|
||
|
|
{
|
||
|
|
Tracy.MarkFrame();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 发送自定义消息
|
||
|
|
/// </summary>
|
||
|
|
public void SendMessage(string message)
|
||
|
|
{
|
||
|
|
Tracy.Message(message);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 绘制自定义数值
|
||
|
|
/// </summary>
|
||
|
|
public void PlotValue(string name, double value)
|
||
|
|
{
|
||
|
|
Tracy.Plot(name, value);
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#if UNITY_EDITOR
|
||
|
|
private void OnValidate()
|
||
|
|
{
|
||
|
|
// 在编辑器中修改参数时的验证
|
||
|
|
if (!Application.isPlaying)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (enableOnStart && !Tracy.IsInitialized)
|
||
|
|
{
|
||
|
|
Tracy.Initialize();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|