using System; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using UnityEngine; namespace TracyProfiler { /// /// Tracy 性能分析器的 Unity 封装 /// 提供简单易用的 C# API 来使用 Tracy 性能分析功能 /// public static class Tracy { #if UNITY_IOS && !UNITY_EDITOR private const string DLL_NAME = "__Internal"; #else private const string DLL_NAME = "UnityTracyPlugin"; #endif #region Native Methods [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] private static extern void TracyInit(); [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] private static extern void TracyShutdown(); [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] private static extern void TracyFrameMark(); [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] private static extern void TracyPlotValue(string name, double value); [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] private static extern void TracySendMessage(string message); [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] private static extern void TracySetThreadName(string name); [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] private static extern void TracyZoneScopedBegin(string name, string function = "", string file = "", int line = 0); [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] private static extern void TracyZoneScopedEnd(string name); #endregion private static bool s_initialized = false; private static bool s_enabled = true; /// /// Tracy 是否已启用 /// public static bool Enabled { get => s_enabled; set => s_enabled = value; } /// /// Tracy 是否已初始化 /// public static bool IsInitialized => s_initialized; /// /// 初始化 Tracy /// public static void Initialize() { if (s_initialized) return; try { #if TRACY_ENABLE TracyInit(); s_initialized = true; Debug.Log("[Tracy] 性能分析器已初始化"); #else Debug.Log("[Tracy] 性能分析器已禁用(编译时未定义 TRACY_ENABLE)"); #endif } catch (DllNotFoundException e) { Debug.LogWarning($"[Tracy] 未找到 Tracy Plugin DLL: {e.Message}"); s_enabled = false; } catch (Exception e) { Debug.LogError($"[Tracy] 初始化失败: {e.Message}"); s_enabled = false; } } /// /// 关闭 Tracy /// public static void Shutdown() { if (!s_initialized) return; try { TracyShutdown(); s_initialized = false; Debug.Log("[Tracy] 性能分析器已关闭"); } catch (Exception e) { Debug.LogError($"[Tracy] 关闭失败: {e.Message}"); } } /// /// 标记帧边界(通常在每帧末尾调用) /// [System.Diagnostics.Conditional("TRACY_ENABLE")] public static void MarkFrame() { if (!s_initialized || !s_enabled) return; TracyFrameMark(); } /// /// 绘制数值(用于实时监控变量) /// [System.Diagnostics.Conditional("TRACY_ENABLE")] public static void Plot(string name, double value) { if (!s_initialized || !s_enabled) return; TracyPlotValue(name, value); } /// /// 绘制整数值 /// [System.Diagnostics.Conditional("TRACY_ENABLE")] public static void Plot(string name, int value) { Plot(name, (double)value); } /// /// 绘制浮点数值 /// [System.Diagnostics.Conditional("TRACY_ENABLE")] public static void Plot(string name, float value) { Plot(name, (double)value); } /// /// 发送消息到 Tracy /// [System.Diagnostics.Conditional("TRACY_ENABLE")] public static void Message(string message) { if (!s_initialized || !s_enabled) return; TracySendMessage(message); } /// /// 设置当前线程名称 /// [System.Diagnostics.Conditional("TRACY_ENABLE")] public static void SetThreadName(string name) { if (!s_initialized || !s_enabled) return; TracySetThreadName(name); } /// /// Tracy Zone 的作用域包装器 /// 使用 using 语句自动管理生命周期 /// public struct ZoneScope : IDisposable { private bool isValid; private string zoneName; public ZoneScope(string name, string function = "", string file = "", int line = 0) { zoneName = name; isValid = s_initialized && s_enabled; #if TRACY_ENABLE if (isValid) { TracyZoneScopedBegin(name, function, file, line); } #endif } public void Dispose() { #if TRACY_ENABLE if (isValid && s_initialized && s_enabled) { TracyZoneScopedEnd(zoneName); } #endif } } /// /// 创建一个 Tracy Zone(性能追踪区域) /// 使用 using 语句确保自动结束 /// /// /// using (Tracy.Zone("MyFunction")) /// { /// // 要追踪的代码 /// } /// public static ZoneScope Zone(string name, [CallerMemberName] string function = "", [CallerFilePath] string file = "", [CallerLineNumber] int line = 0) { return new ZoneScope(name, function, file, line); } } /// /// Tracy Zone 的属性标记版本 /// 可以标记在方法上,自动追踪整个方法 /// 注意:需要配合 AOP 或代码生成工具使用 /// [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class TracyZoneAttribute : Attribute { public string Name { get; set; } public TracyZoneAttribute(string name = null) { Name = name; } } }