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;
}
}
}