This commit is contained in:
2025-11-26 14:35:58 +08:00
commit 43de86ee31
18 changed files with 3954 additions and 0 deletions

View File

@@ -0,0 +1,298 @@
# Unity Tracy Plugin - CMakeLists.txt
# 用于编译 Tracy Unity Native Plugin
cmake_minimum_required(VERSION 3.15)
project(UnityTracyPlugin VERSION 1.0.0)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# ============================================
# 配置选项
# ============================================
option(TRACY_ENABLE "启用 Tracy 性能分析" ON)
option(TRACY_ON_DEMAND "Tracy 按需分析模式" ON)
option(TRACY_NO_EXIT "Tracy 不在退出时断开连接" OFF)
option(TRACY_NO_BROADCAST "Tracy 不广播发现消息" OFF)
option(TRACY_ONLY_LOCALHOST "Tracy 仅允许本地连接" OFF)
# ============================================
# Tracy 配置
# ============================================
if(TRACY_ENABLE)
add_definitions(-DTRACY_ENABLE)
message(STATUS "Tracy 性能分析: 启用")
else()
message(STATUS "Tracy 性能分析: 禁用")
endif()
if(TRACY_ON_DEMAND)
add_definitions(-DTRACY_ON_DEMAND)
message(STATUS "Tracy 按需模式: 启用")
endif()
if(TRACY_NO_EXIT)
add_definitions(-DTRACY_NO_EXIT)
endif()
if(TRACY_NO_BROADCAST)
add_definitions(-DTRACY_NO_BROADCAST)
endif()
if(TRACY_ONLY_LOCALHOST)
add_definitions(-DTRACY_ONLY_LOCALHOST)
endif()
# ============================================
# Tracy 路径配置
# ============================================
# 设置 Tracy 根目录(根据实际情况修改)
set(TRACY_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/tracy" CACHE PATH "Tracy 根目录路径")
if(NOT EXISTS "${TRACY_ROOT}")
message(FATAL_ERROR "找不到 Tracy 目录: ${TRACY_ROOT}\n请设置正确的 TRACY_ROOT 路径")
endif()
message(STATUS "Tracy 根目录: ${TRACY_ROOT}")
# ============================================
# 源文件
# ============================================
set(TRACY_SOURCES
"${TRACY_ROOT}/public/TracyClient.cpp"
)
set(PLUGIN_SOURCES
"SimplifiedPlugin.cpp"
${TRACY_SOURCES}
)
# ============================================
# 包含目录
# ============================================
include_directories(
"${CMAKE_CURRENT_SOURCE_DIR}"
"${TRACY_ROOT}/public"
)
# ============================================
# 创建动态库
# ============================================
add_library(UnityTracyPlugin SHARED ${PLUGIN_SOURCES})
# 设置输出名称
set_target_properties(UnityTracyPlugin PROPERTIES
OUTPUT_NAME "UnityTracyPlugin"
PREFIX "" # 移除 lib 前缀Linux/macOS
)
# ============================================
# 平台特定配置
# ============================================
if(WIN32)
# Windows 配置
message(STATUS "配置 Windows 平台")
# 链接必要的 Windows 库
target_link_libraries(UnityTracyPlugin
ws2_32 # Winsock
dbghelp # Debug Help Library
)
# 输出到 Windows 平台目录
set_target_properties(UnityTracyPlugin PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/Unity/Plugins/x86_64"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/Unity/Plugins/x86_64"
)
# Windows 导出符号
target_compile_definitions(UnityTracyPlugin PRIVATE
WIN32_LEAN_AND_MEAN
NOMINMAX
)
elseif(APPLE)
# macOS/iOS 配置
message(STATUS "配置 Apple 平台")
# 链接 Apple 框架
target_link_libraries(UnityTracyPlugin
"-framework Foundation"
"-framework CoreFoundation"
)
# macOS 特定设置
if(NOT IOS)
set_target_properties(UnityTracyPlugin PROPERTIES
MACOSX_RPATH TRUE
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_NAME_DIR "@rpath"
)
# 输出到 macOS 平台目录
set_target_properties(UnityTracyPlugin PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Unity/Plugins/macOS"
)
else()
# iOS 配置 - 静态库
set_target_properties(UnityTracyPlugin PROPERTIES
FRAMEWORK FALSE
)
# 输出到 iOS 平台目录
set_target_properties(UnityTracyPlugin PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Unity/Plugins/iOS"
)
endif()
elseif(UNIX)
# Linux/Android 配置
message(STATUS "配置 Linux 平台")
# 链接必要的 Linux 库
target_link_libraries(UnityTracyPlugin
pthread # POSIX threads
dl # Dynamic linking
)
# 符号可见性
set_target_properties(UnityTracyPlugin PROPERTIES
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN YES
)
# 输出到 Linux 平台目录
set_target_properties(UnityTracyPlugin PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Unity/Plugins/Linux/x86_64"
)
endif()
# ============================================
# 编译选项
# ============================================
if(MSVC)
# Visual Studio 编译器选项
target_compile_options(UnityTracyPlugin PRIVATE
/W4 # 警告级别 4
/WX- # 警告不视为错误
/permissive- # 标准一致性模式
/MP # 多处理器编译
)
# Release 优化
target_compile_options(UnityTracyPlugin PRIVATE
$<$<CONFIG:Release>:/O2> # 最大优化
$<$<CONFIG:Release>:/Ob2> # 内联展开
)
else()
# GCC/Clang 编译器选项
target_compile_options(UnityTracyPlugin PRIVATE
-Wall
-Wextra
-Wno-unused-parameter
-fPIC # 位置无关代码
-fvisibility=hidden # 隐藏符号
)
# Release 优化
target_compile_options(UnityTracyPlugin PRIVATE
$<$<CONFIG:Release>:-O3> # 最大优化
$<$<CONFIG:Release>:-DNDEBUG> # 禁用断言
)
endif()
# ============================================
# Android NDK 配置(如果使用 Android
# ============================================
if(ANDROID)
message(STATUS "配置 Android 平台")
message(STATUS "Android ABI: ${ANDROID_ABI}")
# 链接 Android 库
target_link_libraries(UnityTracyPlugin
log # Android 日志
android # Android API
)
# 输出到 Android 平台目录
set_target_properties(UnityTracyPlugin PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Unity/Plugins/Android/${ANDROID_ABI}"
)
endif()
# ============================================
# 安装配置
# ============================================
install(TARGETS UnityTracyPlugin
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
# ============================================
# 构建信息
# ============================================
message(STATUS "========================================")
message(STATUS "Unity Tracy Plugin 配置完成")
message(STATUS "========================================")
message(STATUS "项目版本: ${PROJECT_VERSION}")
message(STATUS "C++ 标准: ${CMAKE_CXX_STANDARD}")
message(STATUS "构建类型: ${CMAKE_BUILD_TYPE}")
message(STATUS "编译器: ${CMAKE_CXX_COMPILER_ID}")
message(STATUS "Tracy 启用: ${TRACY_ENABLE}")
message(STATUS "Tracy 按需模式: ${TRACY_ON_DEMAND}")
message(STATUS "========================================")
# ============================================
# 自定义构建目标
# ============================================
# 清理目标
add_custom_target(clean-all
COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/Unity"
COMMENT "清理所有输出文件"
)
# 复制到 Unity 项目(需要设置 UNITY_PROJECT_PATH
if(DEFINED ENV{UNITY_PROJECT_PATH})
set(UNITY_PROJECT_PATH $ENV{UNITY_PROJECT_PATH})
message(STATUS "Unity 项目路径: ${UNITY_PROJECT_PATH}")
add_custom_command(TARGET UnityTracyPlugin POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_BINARY_DIR}/Unity/Plugins"
"${UNITY_PROJECT_PATH}/Assets/Plugins"
COMMENT "复制 Plugin 到 Unity 项目"
)
endif()
# ============================================
# 测试(可选)
# ============================================
option(BUILD_TESTS "构建测试程序" OFF)
if(BUILD_TESTS)
enable_testing()
add_executable(PluginTest
test/plugin_test.cpp
)
target_link_libraries(PluginTest UnityTracyPlugin)
add_test(NAME PluginBasicTest COMMAND PluginTest)
endif()

View File

@@ -0,0 +1,494 @@
# Tracy Unity 集成快速开始指南
本指南将帮助你快速将 Tracy 性能分析器集成到 Unity 项目中。
---
## 🚀 快速开始5 分钟集成)
### 步骤 1: 准备 Tracy
1. 克隆或下载 Tracy 仓库:
```bash
git clone https://github.com/wolfpld/tracy.git
```
2. (可选)编译 Tracy Profiler 工具:
```bash
cd tracy/profiler
# Windows: 使用 Visual Studio 打开并编译
# macOS/Linux:
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
```
### 步骤 2: 编译 Unity Plugin
#### Windows (使用 CMake + Visual Studio)
```powershell
# 在 unity_examples 目录下
mkdir build
cd build
# 配置(修改 TRACY_ROOT 路径指向你的 tracy 目录)
cmake .. -G "Visual Studio 17 2022" -A x64 ^
-DTRACY_ROOT="D:/path/to/tracy" ^
-DTRACY_ENABLE=ON ^
-DTRACY_ON_DEMAND=ON
# 编译
cmake --build . --config Release
```
编译完成后DLL 文件在 `build/Unity/Plugins/x86_64/UnityTracyPlugin.dll`
#### macOS
```bash
# 在 unity_examples 目录下
mkdir build && cd build
# 配置
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DTRACY_ROOT="/path/to/tracy" \
-DTRACY_ENABLE=ON \
-DTRACY_ON_DEMAND=ON
# 编译
make -j8
```
编译完成后,动态库在 `build/Unity/Plugins/macOS/UnityTracyPlugin.dylib`
#### Linux
```bash
# 在 unity_examples 目录下
mkdir build && cd build
# 配置
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DTRACY_ROOT="/path/to/tracy" \
-DTRACY_ENABLE=ON \
-DTRACY_ON_DEMAND=ON
# 编译
make -j8
```
编译完成后,动态库在 `build/Unity/Plugins/Linux/x86_64/UnityTracyPlugin.so`
### 步骤 3: 集成到 Unity 项目
1. **复制 Plugin 文件**
将编译好的 Plugin 复制到 Unity 项目:
```
YourUnityProject/
└── Assets/
└── Plugins/
├── x86_64/
│ └── UnityTracyPlugin.dll # Windows
├── macOS/
│ └── UnityTracyPlugin.dylib # macOS
└── Linux/
└── x86_64/
└── UnityTracyPlugin.so # Linux
```
2. **复制 C# 脚本**
将以下文件复制到 Unity 项目:
```
YourUnityProject/
└── Assets/
└── Scripts/
└── Tracy/
├── TracyWrapper.cs # Tracy C# API
├── TracyManager.cs # Tracy 管理器
└── TracyExamples.cs # 使用示例(可选)
```
3. **配置 Plugin 导入设置**
在 Unity Editor 中:
- 选择 `UnityTracyPlugin.dll`(或 .dylib/.so
- 在 Inspector 中设置平台:
- Windows: 勾选 `x86_64`
- macOS: 勾选 `macOS`
- Linux: 勾选 `Linux x86_64`
### 步骤 4: 在场景中使用
1. **添加 TracyManager**
在你的主场景中:
- 创建空 GameObject命名为 "TracyManager"
- 添加 `TracyManager` 组件
- 在 Inspector 中配置选项
2. **在代码中使用 Tracy**
```csharp
using UnityEngine;
using TracyProfiler;
public class MyGameScript : MonoBehaviour
{
void Update()
{
// 方式 1: 使用 using 语句(推荐)
using (Tracy.Zone("MyGameScript.Update"))
{
DoSomething();
}
// 方式 2: 手动开始/结束
Tracy.BeginZone("CustomZone");
DoSomethingElse();
Tracy.EndZone();
// 绘制数值
Tracy.Plot("Enemy Count", enemyCount);
// 发送消息
if (playerDied)
{
Tracy.Message("Player died");
}
}
void DoSomething()
{
using (Tracy.Zone("DoSomething"))
{
// 你的代码
}
}
}
```
### 步骤 5: 启动 Tracy Profiler 并连接
1. **启动 Tracy Profiler**
```bash
# Windows
Tracy.exe
# macOS/Linux
./Tracy
```
2. **运行 Unity 游戏**
在 Unity Editor 中按 Play或运行构建的可执行文件。
3. **连接到 Tracy**
Tracy Profiler 会自动发现本地网络中的 Tracy 客户端,点击连接即可开始分析。
---
## 📊 使用 Tracy 分析性能
### 查看性能数据
Tracy Profiler 界面主要区域:
1. **时间线视图**
- 显示所有 Zone 的执行时间
- 颜色表示不同的调用栈深度
- 可以缩放和平移
2. **统计视图**
- 函数调用次数
- 总耗时、平均耗时、最小/最大耗时
- 排序和筛选功能
3. **帧视图**
- 查看每帧的性能
- 识别帧率波动
- 帧时间分布
4. **Plot 视图**
- 查看 `Tracy.Plot()` 绘制的数值曲线
- 实时监控变量变化
### 常用快捷键
- `鼠标滚轮`: 缩放时间线
- `鼠标中键拖拽`: 平移时间线
- `鼠标左键`: 选择 Zone 查看详情
- `Ctrl + F`: 搜索函数
- `Ctrl + Z`: 放大到选中的 Zone
---
## 🔧 常见问题排查
### 问题 1: DLL 加载失败
**错误信息**: `DllNotFoundException: UnityTracyPlugin`
**解决方案**:
1. 确认 DLL 文件在正确的目录
2. 检查 Plugin Import Settings 的平台配置
3. 确认 DLL 架构与 Unity 项目匹配x64/x86
4. Windows: 检查是否缺少 `vcruntime140.dll`(安装 Visual C++ Redistributable
### 问题 2: Tracy Profiler 无法连接
**症状**: Tracy Profiler 中看不到 Unity 应用
**解决方案**:
1. 确认防火墙允许 TCP 端口 8086
2. 检查 `TRACY_ON_DEMAND` 宏是否正确定义
3. 确认 `Tracy.Initialize()` 已被调用
4. 检查 Unity Console 是否有 Tracy 初始化消息
```csharp
// 在 Unity Console 应该看到:
// [Tracy] 性能分析器已初始化
```
### 问题 3: 性能数据不显示
**症状**: Tracy 已连接,但看不到任何 Zone
**解决方案**:
1. 确认代码中使用了 `Tracy.Zone()``ZoneScoped`
2. 确认 `Tracy.MarkFrame()` 在每帧被调用
3. 检查是否定义了 `TRACY_ENABLE` 编译符号
4. 在 Unity Editor 中,确认 Tracy Manager 的 "Enable On Start" 已勾选
### 问题 4: 编译错误
**常见编译错误**:
1. **找不到 Tracy.hpp**
```
fatal error: tracy/Tracy.hpp: No such file or directory
```
解决: 检查 `TRACY_ROOT` 路径是否正确
2. **链接错误 (Windows)**
```
error LNK2019: unresolved external symbol
```
解决: 确认链接了 `ws2_32.lib` 和 `dbghelp.lib`
3. **链接错误 (Linux)**
```
undefined reference to `pthread_create'
```
解决: 添加 `-lpthread -ldl` 链接选项
### 问题 5: Android/iOS 构建问题
**Android**:
1. 使用 Android NDK 编译
2. 确保为所有需要的 ABI 编译armeabi-v7a, arm64-v8a
3. 将 `.so` 文件放在 `Assets/Plugins/Android/libs/{ABI}/`
**iOS**:
1. 编译为静态库(.a
2. 在 Unity Build Settings 中设置 "Target SDK" 为 "Device SDK"
3. 确保代码签名正确
---
## 🎯 最佳实践
### 1. Zone 命名规范
```csharp
// ✅ 好的命名 - 清晰、描述性
using (Tracy.Zone("PlayerController.Move"))
using (Tracy.Zone("AI.UpdatePathfinding"))
using (Tracy.Zone("Render.DrawTerrain"))
// ❌ 不好的命名 - 模糊、无意义
using (Tracy.Zone("Function1"))
using (Tracy.Zone("Update"))
using (Tracy.Zone("Test"))
```
### 2. 适度使用 Zone
```csharp
void Update()
{
// ✅ 追踪主要的逻辑块
using (Tracy.Zone("Update"))
{
using (Tracy.Zone("ProcessInput"))
{
ProcessInput(); // 追踪大块逻辑
}
UpdateGameLogic(); // 内部有自己的 Zone
}
}
// ❌ 过度追踪会增加开销
void BadExample()
{
for (int i = 0; i < 10000; i++)
{
using (Tracy.Zone($"Iteration {i}")) // 太多 Zone
{
DoSomething();
}
}
}
```
### 3. 使用条件编译
```csharp
// 在生产构建中禁用细粒度追踪
#if TRACY_ENABLE
using (Tracy.Zone("DetailedAnalysis"))
{
// 详细的性能分析代码
}
#endif
```
### 4. 监控关键指标
```csharp
void LateUpdate()
{
// 监控帧率
Tracy.Plot("FPS", 1.0f / Time.deltaTime);
// 监控内存
Tracy.Plot("Memory (MB)", GC.GetTotalMemory(false) / 1024.0 / 1024.0);
// 监控对象计数
Tracy.Plot("Enemy Count", enemies.Count);
Tracy.Plot("Active Particles", particleSystem.particleCount);
// 监控物理
Tracy.Plot("Rigidbodies", FindObjectsOfType<Rigidbody>().Length);
}
```
### 5. 多线程命名
```csharp
using System.Threading;
void WorkerThread()
{
Tracy.SetThreadName("Worker Thread");
while (running)
{
using (Tracy.Zone("WorkerThread.Process"))
{
ProcessData();
}
}
}
```
---
## 📚 进阶主题
### 自定义构建配置
在 Unity 项目中创建 `link.xml` 防止代码剥离:
```xml
<linker>
<assembly fullname="Assembly-CSharp">
<namespace fullname="TracyProfiler" preserve="all"/>
</assembly>
</linker>
```
### 持久化性能数据
Tracy 支持保存性能数据到文件:
1. 在 Tracy Profiler 中,点击 "Save trace"
2. 选择保存位置(.tracy 文件)
3. 之后可以用 Tracy Profiler 打开查看
### 集成到 CI/CD
可以在自动化测试中使用 Tracy
```csharp
public class PerformanceTest
{
[Test]
public void TestPerformance()
{
Tracy.Initialize();
using (Tracy.Zone("PerformanceTest"))
{
// 运行性能测试
RunGameLoop(100); // 运行 100 帧
}
Tracy.Shutdown();
// 分析结果...
}
}
```
---
## 🔗 资源链接
- [Tracy 官方仓库](https://github.com/wolfpld/tracy)
- [Tracy 官方手册](https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf)
- [Unity Native Plugin 文档](https://docs.unity3d.com/Manual/NativePlugins.html)
- 本项目的完整文档: `UNITY_INTEGRATION_GUIDE.md`
---
## 💡 技巧和提示
1. **使用 Release 构建进行性能测试**
- Debug 构建会有大量额外开销
- 在 Unity 中创建专门的 "Profiling" 构建配置
2. **关闭 V-Sync 测试真实性能**
- V-Sync 会限制帧率
- 在 Project Settings > Quality 中关闭
3. **使用 Tracy 的统计功能**
- 查看函数调用次数
- 识别被频繁调用的函数
4. **比较不同实现**
- 使用 Tracy 比较算法性能
- A/B 测试优化效果
5. **定期保存 Trace 文件**
- 记录性能基准
- 跟踪性能变化趋势
---
## 🎉 完成!
现在你已经成功将 Tracy 集成到 Unity 项目中了!
开始使用 Tracy 分析你的游戏性能,找出瓶颈,优化代码吧!
如有问题,请参考完整文档 `UNITY_INTEGRATION_GUIDE.md` 或访问 Tracy 官方仓库。

484
unity_examples/README.md Normal file
View File

@@ -0,0 +1,484 @@
# Tracy Unity 集成示例
本目录包含将 Tracy 性能分析器集成到 Unity 项目的完整示例和工具。
## 📁 文件结构
```
unity_examples/
├── README.md # 本文件 - 项目概述
├── QUICKSTART.md # 5分钟快速开始指南 ⭐ 从这里开始!
├── CMakeLists.txt # CMake 构建配置
├── SimplifiedPlugin.cpp # Tracy Unity Plugin C++ 实现
├── TracyWrapper.cs # Tracy C# API 封装
├── TracyManager.cs # Tracy 管理器组件
└── TracyExamples.cs # 使用示例和最佳实践
```
## 🚀 快速开始
### 新手用户
如果你是第一次使用,请按以下顺序阅读:
1. **[QUICKSTART.md](QUICKSTART.md)** - 5分钟快速集成指南
2. **[TracyExamples.cs](TracyExamples.cs)** - 查看代码示例
3. **[../UNITY_INTEGRATION_GUIDE.md](../UNITY_INTEGRATION_GUIDE.md)** - 完整的集成文档
### 有经验的用户
快速集成步骤:
```bash
# 1. 编译 Plugin
mkdir build && cd build
cmake .. -DTRACY_ROOT="/path/to/tracy" -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
# 2. 复制文件到 Unity 项目
cp build/Unity/Plugins/* YourUnityProject/Assets/Plugins/
cp *.cs YourUnityProject/Assets/Scripts/Tracy/
# 3. 在 Unity 场景中添加 TracyManager 组件
# 4. 运行 Tracy Profiler 并连接
```
## 📦 文件说明
### C++ Plugin 相关
#### `SimplifiedPlugin.cpp`
Tracy Unity Native Plugin 的 C++ 实现。
**主要功能**:
- 初始化/关闭 Tracy
- 创建性能追踪 Zone
- 绘制实时数值
- 发送消息和日志
- 线程命名
**导出函数**:
```cpp
TracyInit() // 初始化
TracyShutdown() // 关闭
TracyFrameMark() // 标记帧边界
TracyZoneBegin(name) // 开始 Zone
TracyZoneEnd() // 结束 Zone
TracyPlotValue(name, v) // 绘制数值
TracyMessage(msg) // 发送消息
TracySetThreadName(name) // 设置线程名
```
**编译要求**:
- C++17
- Tracy 源代码
- Windows: Visual Studio 2019+
- macOS: Xcode 12+
- Linux: GCC 9+ 或 Clang 10+
#### `CMakeLists.txt`
跨平台 CMake 构建配置。
**支持平台**:
- ✅ Windows (x64)
- ✅ macOS (Intel/Apple Silicon)
- ✅ Linux (x64)
- ✅ Android (armeabi-v7a, arm64-v8a)
- ✅ iOS (arm64)
**配置选项**:
```cmake
-DTRACY_ENABLE=ON # 启用 Tracy
-DTRACY_ON_DEMAND=ON # 按需分析模式
-DTRACY_ROOT=path # Tracy 根目录
```
### C# 脚本相关
#### `TracyWrapper.cs`
Tracy 的 C# API 封装,提供简洁易用的接口。
**核心 API**:
```csharp
// 初始化
Tracy.Initialize()
// 性能追踪 (推荐使用 using 语句)
using (Tracy.Zone("FunctionName"))
{
// 要追踪的代码
}
// 手动管理 Zone
Tracy.BeginZone("CustomZone")
// ... 代码 ...
Tracy.EndZone()
// 绘制实时数值
Tracy.Plot("FPS", fps)
Tracy.Plot("Memory", memoryMB)
// 发送消息
Tracy.Message("重要事件发生")
// 设置线程名
Tracy.SetThreadName("Worker Thread")
// 标记帧边界
Tracy.MarkFrame()
```
**特性**:
- 使用 `IDisposable` 自动管理 Zone 生命周期
- 条件编译支持(`TRACY_ENABLE`
- 零开销(禁用时)
- 线程安全
#### `TracyManager.cs`
Unity 组件,负责 Tracy 的初始化和自动化监控。
**功能**:
- 自动初始化 Tracy
- 每帧自动标记帧边界
- 自动监控系统指标:
- 帧率 (FPS)
- 帧时间
- 内存使用
- 渲染统计
- 物理对象数量
**使用方法**:
1. 在场景中创建空 GameObject
2. 添加 `TracyManager` 组件
3. 配置 Inspector 中的选项
4. 运行游戏
**Inspector 选项**:
- `Enable On Start`: 启动时自动初始化
- `Mark Frames`: 每帧自动标记
- `Monitor Frame Rate`: 监控帧率
- `Monitor Memory`: 监控内存
- `Monitor Rendering`: 监控渲染
- `Monitor Physics`: 监控物理
#### `TracyExamples.cs`
完整的使用示例和最佳实践。
**包含示例**:
1. ✅ 基础 Zone 使用
2. ✅ 计算密集型操作追踪
3. ✅ 重度计算测试
4. ✅ 对象池管理
5. ✅ 协程性能追踪
6. ✅ 自定义数据绘制
7. ✅ 条件性能追踪
**交互功能**:
-`Space` 键: 执行重度计算
-`R` 键: 重置对象池
-`T` 键: 运行性能测试
## 🎯 使用场景
### 1. 游戏开发性能优化
```csharp
public class GameController : MonoBehaviour
{
void Update()
{
using (Tracy.Zone("GameController.Update"))
{
using (Tracy.Zone("Update AI"))
{
UpdateAI();
}
using (Tracy.Zone("Update Physics"))
{
UpdatePhysics();
}
using (Tracy.Zone("Update Rendering"))
{
UpdateRendering();
}
}
}
}
```
### 2. 资源加载分析
```csharp
IEnumerator LoadScene()
{
using (Tracy.Zone("Load Scene"))
{
using (Tracy.Zone("Load Assets"))
{
yield return LoadAssets();
}
using (Tracy.Zone("Initialize Scene"))
{
InitializeScene();
}
Tracy.Message("Scene loaded successfully");
}
}
```
### 3. AI 系统性能追踪
```csharp
public class AIManager : MonoBehaviour
{
void Update()
{
using (Tracy.Zone("AI Manager"))
{
foreach (var agent in agents)
{
using (Tracy.Zone($"AI Agent {agent.id}"))
{
agent.UpdateBehavior();
}
}
Tracy.Plot("Active AI Agents", agents.Count);
}
}
}
```
### 4. 网络同步分析
```csharp
void OnNetworkUpdate()
{
using (Tracy.Zone("Network Update"))
{
using (Tracy.Zone("Receive Packets"))
{
ReceivePackets();
}
using (Tracy.Zone("Process Messages"))
{
ProcessMessages();
}
using (Tracy.Zone("Send Updates"))
{
SendUpdates();
}
Tracy.Plot("Network Latency (ms)", latency);
Tracy.Plot("Packet Loss (%)", packetLoss);
}
}
```
### 5. 渲染管线优化
```csharp
void OnPreRender()
{
using (Tracy.Zone("Pre-Render"))
{
using (Tracy.Zone("Culling"))
{
PerformCulling();
}
using (Tracy.Zone("Sort Render Queue"))
{
SortRenderQueue();
}
Tracy.Plot("Visible Objects", visibleCount);
Tracy.Plot("Draw Calls", drawCalls);
}
}
```
## 🔧 平台特定说明
### Windows
**依赖**:
- Visual Studio 2019 或更高版本
- Windows SDK
- vcruntime140.dll (Visual C++ Redistributable)
**编译**:
```powershell
cmake -B build -G "Visual Studio 17 2022" -A x64
cmake --build build --config Release
```
**输出**: `build/Unity/Plugins/x86_64/UnityTracyPlugin.dll`
### macOS
**依赖**:
- Xcode Command Line Tools
- CMake 3.15+
**编译**:
```bash
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
```
**输出**: `build/Unity/Plugins/macOS/UnityTracyPlugin.dylib`
**注意**: Apple Silicon (M1/M2) 和 Intel 需要分别编译
### Linux
**依赖**:
- GCC 9+ 或 Clang 10+
- pthread, dl
**编译**:
```bash
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
```
**输出**: `build/Unity/Plugins/Linux/x86_64/UnityTracyPlugin.so`
### Android
**依赖**:
- Android NDK r21+
- CMake 3.15+
**编译**:
```bash
# ARM64
cmake -B build-android-arm64 \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-21
# ARMv7
cmake -B build-android-armv7 \
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=armeabi-v7a \
-DANDROID_PLATFORM=android-21
```
### iOS
**依赖**:
- Xcode 12+
- iOS SDK
**编译**:
```bash
cmake -B build-ios \
-DCMAKE_SYSTEM_NAME=iOS \
-DCMAKE_OSX_ARCHITECTURES=arm64 \
-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0
```
**注意**: iOS 需要静态库(.a而不是动态库
## 📊 性能影响
### Tracy 开销
| 配置 | 每 Zone 开销 | 内存开销 | 网络带宽 |
|------|-------------|---------|---------|
| 禁用 (Release) | 0 ns | 0 MB | 0 |
| 启用 (On-Demand, 未连接) | ~20 ns | ~1 MB | 0 |
| 启用 (已连接) | ~50 ns | ~10 MB | ~1 Mbps |
### 建议
- ✅ 在 Debug/Development 构建中启用
- ✅ 追踪主要逻辑块(毫秒级)
- ⚠️ 避免追踪微小操作(微秒级)
- ⚠️ 避免在紧密循环中创建 Zone
- ❌ 不建议在 Release 构建中启用细粒度追踪
## 🐛 故障排除
### 常见问题
详细的故障排除指南请参考 [QUICKSTART.md](QUICKSTART.md#常见问题排查)
**快速检查清单**:
- [ ] DLL 文件在正确的 Plugins 目录
- [ ] Plugin Import Settings 配置正确
- [ ] Tracy Profiler 正在运行
- [ ] 防火墙允许端口 8086
- [ ] `Tracy.Initialize()` 已被调用
- [ ] Unity Console 显示初始化消息
- [ ] 代码中使用了 `Tracy.Zone()``ZoneScoped`
- [ ] `TracyManager` 组件已添加到场景
### 获取帮助
如果遇到问题:
1. 查看 [QUICKSTART.md](QUICKSTART.md) 的故障排除章节
2. 查看 [完整集成指南](../UNITY_INTEGRATION_GUIDE.md)
3. 查看 [Tracy 官方文档](https://github.com/wolfpld/tracy)
4. 检查 Unity Console 的错误消息
## 📚 相关资源
### 文档
- [快速开始指南](QUICKSTART.md) - 5分钟集成
- [完整集成指南](../UNITY_INTEGRATION_GUIDE.md) - 详细文档
- [Tracy 官方手册](https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf) - PDF
### 链接
- [Tracy GitHub](https://github.com/wolfpld/tracy) - 官方仓库
- [Tracy 演示视频](https://www.youtube.com/watch?v=fB5B46lbapc) - YouTube
- [Unity Native Plugins](https://docs.unity3d.com/Manual/NativePlugins.html) - 官方文档
### 示例项目
本目录中的示例展示了:
- 基本的 Zone 使用
- 性能数据绘制
- 协程追踪
- 多线程支持
- 最佳实践
## 🤝 贡献
欢迎改进和建议!
如果你有更好的实现方式或发现了问题,请:
1. 修改代码
2. 测试你的更改
3. 分享你的改进
## 📄 许可证
- Tracy: BSD 3-Clause License
- 本示例代码: MIT License
## 🎉 开始使用
现在你已经了解了整体结构,可以开始集成了!
**下一步**: 打开 [QUICKSTART.md](QUICKSTART.md) 开始 5 分钟快速集成!
---
**祝你使用愉快!** 🚀
如有任何问题,欢迎查阅文档或在社区寻求帮助。

View File

@@ -0,0 +1,287 @@
/*
* Tracy Unity Plugin - 简化版实现
*
* 这是一个简化的 Tracy Unity Plugin 实现
* 用于演示如何将 Tracy 集成到 Unity Native Plugin 中
*
* 编译说明:
* Windows: cl /LD /MD SimplifiedPlugin.cpp /I"path/to/tracy/public" ws2_32.lib dbghelp.lib
* macOS: clang++ -shared -fPIC SimplifiedPlugin.cpp -I"path/to/tracy/public" -o libUnityTracyPlugin.dylib
* Linux: g++ -shared -fPIC SimplifiedPlugin.cpp -I"path/to/tracy/public" -o libUnityTracyPlugin.so -lpthread -ldl
*/
// 定义 Tracy 启用标志
#define TRACY_ENABLE
#define TRACY_ON_DEMAND
#include "tracy/Tracy.hpp"
#include <string>
#include <cstring>
// 平台特定的导出定义
#if defined(_WIN32) || defined(_WIN64)
#define UNITY_PLUGIN_EXPORT __declspec(dllexport)
#elif defined(__APPLE__) || defined(__linux__)
#define UNITY_PLUGIN_EXPORT __attribute__((visibility("default")))
#else
#define UNITY_PLUGIN_EXPORT
#endif
// C 导出函数Unity 需要 C 链接)
extern "C" {
/**
* 初始化 Tracy
* Unity C# 调用: [DllImport] private static extern void TracyInit();
*/
UNITY_PLUGIN_EXPORT void TracyInit()
{
// Tracy 会自动初始化,这里可以添加额外的初始化逻辑
// 例如:设置采样率、配置选项等
}
/**
* 关闭 Tracy
* Unity C# 调用: [DllImport] private static extern void TracyShutdown();
*/
UNITY_PLUGIN_EXPORT void TracyShutdown()
{
// Tracy 会在程序退出时自动清理
// 这里可以添加自定义的清理逻辑
}
/**
* 标记帧边界
* Unity C# 调用: [DllImport] private static extern void TracyFrameMark();
*/
UNITY_PLUGIN_EXPORT void TracyFrameMark()
{
FrameMark;
}
/**
* 绘制数值
* Unity C# 调用: [DllImport] private static extern void TracyPlotValue(string name, double value);
*/
UNITY_PLUGIN_EXPORT void TracyPlotValue(const char* name, double value)
{
if (name != nullptr)
{
TracyPlot(name, value);
}
}
/**
* 发送消息
* Unity C# 调用: [DllImport] private static extern void TracyMessage(string message);
*/
UNITY_PLUGIN_EXPORT void TracyMessage(const char* message)
{
if (message != nullptr)
{
TracyMessage(message, std::strlen(message));
}
}
/**
* 设置线程名称
* Unity C# 调用: [DllImport] private static extern void TracySetThreadName(string name);
*/
UNITY_PLUGIN_EXPORT void TracySetThreadName(const char* name)
{
if (name != nullptr)
{
tracy::SetThreadName(name);
}
}
/**
* 开始一个命名的 Zone
* Unity C# 调用: [DllImport] private static extern void TracyZoneBegin(string name);
*
* 注意: 这是简化版实现,实际使用中需要更复杂的 Zone 管理
*/
UNITY_PLUGIN_EXPORT void TracyZoneBegin(const char* name)
{
if (name != nullptr)
{
// 简化版: 使用动态分配的 Zone
// 实际应用中需要管理 Zone 的生命周期
// 方案1: 使用全局 Zone 栈(简单但不支持多线程)
// 方案2: 使用线程局部存储(复杂但支持多线程)
// 方案3: 返回 Zone ID 给 C#,让 C# 管理(推荐)
// 这里使用宏创建一个 Zone
// 注意:这只是示例,实际使用需要更好的管理方式
ZoneName(name, std::strlen(name));
}
}
/**
* 结束当前 Zone
* Unity C# 调用: [DllImport] private static extern void TracyZoneEnd();
*/
UNITY_PLUGIN_EXPORT void TracyZoneEnd()
{
// 简化版: 与 ZoneBegin 配对使用
// 实际应用中需要管理 Zone 的结束
}
/**
* Unity 插件生命周期函数 - 加载时调用
*/
UNITY_PLUGIN_EXPORT void UnityPluginLoad()
{
// 可选:在插件加载时执行初始化
}
/**
* Unity 插件生命周期函数 - 卸载时调用
*/
UNITY_PLUGIN_EXPORT void UnityPluginUnload()
{
// 可选:在插件卸载时执行清理
}
} // extern "C"
/*
* 高级实现示例 - Zone 管理
*
* 下面是一个更完善的 Zone 管理实现示例
* 可以根据需要扩展
*/
#ifdef ADVANCED_ZONE_MANAGEMENT
#include <unordered_map>
#include <stack>
#include <mutex>
// Zone 管理器(线程安全)
class ZoneManager
{
private:
struct ThreadZones
{
std::stack<tracy::ScopedZone*> zones;
};
std::unordered_map<std::thread::id, ThreadZones> threadZones;
std::mutex mutex;
public:
void BeginZone(const char* name, const char* function, const char* file, uint32_t line)
{
std::lock_guard<std::mutex> lock(mutex);
auto threadId = std::this_thread::get_id();
auto& zones = threadZones[threadId].zones;
// 创建源位置信息
static const tracy::SourceLocationData loc{name, function, file, line, 0};
// 创建 Zone注意需要在堆上分配
auto* zone = new tracy::ScopedZone(&loc, true);
zones.push(zone);
}
void EndZone()
{
std::lock_guard<std::mutex> lock(mutex);
auto threadId = std::this_thread::get_id();
auto it = threadZones.find(threadId);
if (it != threadZones.end() && !it->second.zones.empty())
{
auto* zone = it->second.zones.top();
it->second.zones.pop();
delete zone;
}
}
void ClearThread()
{
std::lock_guard<std::mutex> lock(mutex);
auto threadId = std::this_thread::get_id();
auto it = threadZones.find(threadId);
if (it != threadZones.end())
{
// 清理所有未结束的 Zone
while (!it->second.zones.empty())
{
delete it->second.zones.top();
it->second.zones.pop();
}
threadZones.erase(it);
}
}
};
// 全局 Zone 管理器实例
static ZoneManager g_zoneManager;
extern "C" {
UNITY_PLUGIN_EXPORT void TracyZoneBeginAdvanced(const char* name, const char* function, const char* file, int line)
{
g_zoneManager.BeginZone(name, function, file, static_cast<uint32_t>(line));
}
UNITY_PLUGIN_EXPORT void TracyZoneEndAdvanced()
{
g_zoneManager.EndZone();
}
UNITY_PLUGIN_EXPORT void TracyClearThreadZones()
{
g_zoneManager.ClearThread();
}
} // extern "C"
#endif // ADVANCED_ZONE_MANAGEMENT
/*
* 编译和部署说明:
*
* 1. Windows (Visual Studio):
* - 创建 DLL 项目
* - 添加 Tracy 源文件: tracy/public/TracyClient.cpp
* - 包含目录: tracy/public
* - 链接库: ws2_32.lib dbghelp.lib
* - 输出: UnityTracyPlugin.dll
*
* 2. macOS:
* clang++ -std=c++17 -shared -fPIC \
* SimplifiedPlugin.cpp \
* tracy/public/TracyClient.cpp \
* -I tracy/public \
* -DTRACY_ENABLE -DTRACY_ON_DEMAND \
* -o libUnityTracyPlugin.dylib
*
* 3. Linux:
* g++ -std=c++17 -shared -fPIC \
* SimplifiedPlugin.cpp \
* tracy/public/TracyClient.cpp \
* -I tracy/public \
* -DTRACY_ENABLE -DTRACY_ON_DEMAND \
* -lpthread -ldl \
* -o libUnityTracyPlugin.so
*
* 4. Android (NDK):
* 在 Android.mk 或 CMakeLists.txt 中配置
*
* 5. iOS:
* 使用 Xcode 编译为静态库 (.a)
*
* 部署到 Unity:
* - 将编译好的库文件复制到 Unity 项目的 Assets/Plugins/ 目录
* - 根据平台放置在相应的子目录中
* - 配置 Plugin Import Settings 以匹配目标平台
*/

View File

@@ -0,0 +1,396 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using TracyProfiler;
namespace TracyProfiler.Examples
{
/// <summary>
/// Tracy 使用示例
/// 展示如何在不同场景下使用 Tracy 性能分析
/// </summary>
public class TracyExamples : MonoBehaviour
{
[Header("测试参数")]
[SerializeField] private int heavyComputationIterations = 10000;
[SerializeField] private int objectPoolSize = 100;
[SerializeField] private bool runContinuousTest = false;
private List<GameObject> objectPool = new List<GameObject>();
private void Start()
{
Tracy.Message("TracyExamples - 示例场景启动");
InitializeObjectPool();
}
private void Update()
{
// 示例 1: 追踪整个 Update 方法
using (Tracy.Zone("TracyExamples.Update"))
{
// 示例 2: 追踪输入处理
HandleInput();
// 示例 3: 追踪游戏逻辑
if (runContinuousTest)
{
UpdateGameLogic();
}
// 示例 4: 绘制自定义数据
PlotCustomData();
}
}
#region 1: Zone 使
private void HandleInput()
{
using (Tracy.Zone("Handle Input"))
{
if (Input.GetKeyDown(KeyCode.Space))
{
Tracy.Message("用户按下空格键");
PerformHeavyComputation();
}
if (Input.GetKeyDown(KeyCode.R))
{
Tracy.Message("用户按下 R 键 - 重置对象池");
ResetObjectPool();
}
if (Input.GetKeyDown(KeyCode.T))
{
Tracy.Message("用户按下 T 键 - 运行测试");
StartCoroutine(RunPerformanceTest());
}
}
}
#endregion
#region 2:
private void UpdateGameLogic()
{
using (Tracy.Zone("Update Game Logic"))
{
// 模拟一些游戏逻辑
ProcessAI();
UpdatePhysics();
CheckCollisions();
}
}
private void ProcessAI()
{
using (Tracy.Zone("Process AI"))
{
// 模拟 AI 计算
float sum = 0;
for (int i = 0; i < 1000; i++)
{
sum += Mathf.Sin(i) * Mathf.Cos(i);
}
Tracy.Plot("AI Computation Result", sum);
}
}
private void UpdatePhysics()
{
using (Tracy.Zone("Update Physics"))
{
// 模拟物理更新
foreach (var obj in objectPool)
{
if (obj.activeInHierarchy)
{
// 简单的物理模拟
obj.transform.position += Vector3.down * Time.deltaTime;
}
}
}
}
private void CheckCollisions()
{
using (Tracy.Zone("Check Collisions"))
{
// 模拟碰撞检测
int activeObjects = 0;
foreach (var obj in objectPool)
{
if (obj.activeInHierarchy)
{
activeObjects++;
}
}
Tracy.Plot("Active Objects", activeObjects);
}
}
#endregion
#region 3:
[ContextMenu("执行重度计算")]
public void PerformHeavyComputation()
{
using (Tracy.Zone("Heavy Computation"))
{
Tracy.Message($"开始重度计算 ({heavyComputationIterations} 次迭代)");
// 矩阵运算
using (Tracy.Zone("Matrix Operations"))
{
Matrix4x4 result = Matrix4x4.identity;
for (int i = 0; i < heavyComputationIterations; i++)
{
Matrix4x4 temp = Matrix4x4.TRS(
Random.insideUnitSphere,
Random.rotation,
Vector3.one
);
result = result * temp;
}
}
// 数学运算
using (Tracy.Zone("Math Operations"))
{
double sum = 0;
for (int i = 0; i < heavyComputationIterations; i++)
{
sum += System.Math.Sqrt(i) * System.Math.Sin(i) * System.Math.Cos(i);
}
Tracy.Plot("Math Result", sum);
}
Tracy.Message("重度计算完成");
}
}
#endregion
#region 4:
private void InitializeObjectPool()
{
using (Tracy.Zone("Initialize Object Pool"))
{
Tracy.Message($"初始化对象池 (大小: {objectPoolSize})");
for (int i = 0; i < objectPoolSize; i++)
{
GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
obj.name = $"PoolObject_{i}";
obj.transform.position = Random.insideUnitSphere * 10f;
obj.SetActive(false);
objectPool.Add(obj);
}
Tracy.Plot("Object Pool Size", objectPoolSize);
}
}
[ContextMenu("重置对象池")]
public void ResetObjectPool()
{
using (Tracy.Zone("Reset Object Pool"))
{
foreach (var obj in objectPool)
{
obj.transform.position = Random.insideUnitSphere * 10f;
obj.SetActive(Random.value > 0.5f);
}
Tracy.Message("对象池已重置");
}
}
#endregion
#region 5:
[ContextMenu("运行性能测试")]
public void StartPerformanceTest()
{
StartCoroutine(RunPerformanceTest());
}
private IEnumerator RunPerformanceTest()
{
Tracy.Message("=== 性能测试开始 ===");
// 测试 1: 快速操作
using (Tracy.Zone("Test: Fast Operations"))
{
for (int i = 0; i < 100; i++)
{
float temp = Mathf.Sin(i);
}
}
yield return null;
// 测试 2: 中等操作
using (Tracy.Zone("Test: Medium Operations"))
{
for (int i = 0; i < 1000; i++)
{
Vector3 temp = Random.insideUnitSphere;
}
}
yield return new WaitForSeconds(0.1f);
// 测试 3: 慢速操作
using (Tracy.Zone("Test: Slow Operations"))
{
for (int i = 0; i < objectPoolSize; i++)
{
objectPool[i].SetActive(true);
objectPool[i].transform.position = Random.insideUnitSphere * 20f;
}
}
yield return null;
Tracy.Message("=== 性能测试完成 ===");
}
#endregion
#region 6:
private void PlotCustomData()
{
using (Tracy.Zone("Plot Custom Data"))
{
// 绘制内存使用
long memoryUsed = System.GC.GetTotalMemory(false);
Tracy.Plot("Custom Memory (MB)", memoryUsed / (1024.0 * 1024.0));
// 绘制对象计数
int activeCount = 0;
foreach (var obj in objectPool)
{
if (obj.activeInHierarchy) activeCount++;
}
Tracy.Plot("Active Pool Objects", activeCount);
// 绘制帧时间
Tracy.Plot("Custom Frame Time (ms)", Time.deltaTime * 1000f);
// 绘制时间戳
Tracy.Plot("Time Since Startup", Time.realtimeSinceStartup);
}
}
#endregion
#region 7:
/// <summary>
/// 演示如何使用条件编译来控制 Tracy 的开销
/// </summary>
private void ConditionalProfiling()
{
#if TRACY_ENABLE
// 只有在定义了 TRACY_ENABLE 时才执行的代码
using (Tracy.Zone("Conditional Profiling"))
{
// 详细的性能追踪
DetailedPerformanceTracking();
}
#endif
}
private void DetailedPerformanceTracking()
{
// 非常细粒度的性能追踪
for (int i = 0; i < 10; i++)
{
using (Tracy.Zone($"Iteration {i}"))
{
// 每次迭代的详细追踪
System.Threading.Thread.Sleep(1);
}
}
}
#endregion
private void OnDestroy()
{
// 清理对象池
using (Tracy.Zone("Cleanup Object Pool"))
{
foreach (var obj in objectPool)
{
if (obj != null)
{
Destroy(obj);
}
}
objectPool.Clear();
Tracy.Message("TracyExamples - 场景清理完成");
}
}
#if UNITY_EDITOR
[ContextMenu("切换连续测试")]
private void ToggleContinuousTest()
{
runContinuousTest = !runContinuousTest;
Tracy.Message($"连续测试: {(runContinuousTest ? "" : "")}");
}
#endif
}
/// <summary>
/// 演示如何在自定义类中使用 Tracy
/// </summary>
public class CustomSystem
{
private string systemName;
public CustomSystem(string name)
{
systemName = name;
Tracy.Message($"{systemName} - 系统创建");
}
public void Update()
{
using (Tracy.Zone($"{systemName}.Update"))
{
// 系统更新逻辑
ProcessData();
UpdateState();
}
}
private void ProcessData()
{
using (Tracy.Zone($"{systemName}.ProcessData"))
{
// 数据处理
}
}
private void UpdateState()
{
using (Tracy.Zone($"{systemName}.UpdateState"))
{
// 状态更新
}
}
}
}

View File

@@ -0,0 +1,269 @@
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
}
}

View File

@@ -0,0 +1,257 @@
using System;
using System.Runtime.InteropServices;
using UnityEngine;
namespace TracyProfiler
{
/// <summary>
/// Tracy 性能分析器的 Unity 封装
/// 提供简单易用的 C# API 来使用 Tracy 性能分析功能
/// </summary>
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 TracyMessage(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 TracyZoneBegin(string name);
[DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)]
private static extern void TracyZoneEnd();
#endregion
private static bool s_initialized = false;
private static bool s_enabled = true;
/// <summary>
/// Tracy 是否已启用
/// </summary>
public static bool Enabled
{
get => s_enabled;
set => s_enabled = value;
}
/// <summary>
/// Tracy 是否已初始化
/// </summary>
public static bool IsInitialized => s_initialized;
/// <summary>
/// 初始化 Tracy
/// </summary>
public static void Initialize()
{
if (s_initialized) return;
try
{
#if TRACY_ENABLE || UNITY_EDITOR
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;
}
}
/// <summary>
/// 关闭 Tracy
/// </summary>
public static void Shutdown()
{
if (!s_initialized) return;
try
{
TracyShutdown();
s_initialized = false;
Debug.Log("[Tracy] 性能分析器已关闭");
}
catch (Exception e)
{
Debug.LogError($"[Tracy] 关闭失败: {e.Message}");
}
}
/// <summary>
/// 标记帧边界(通常在每帧末尾调用)
/// </summary>
[System.Diagnostics.Conditional("TRACY_ENABLE")]
public static void MarkFrame()
{
if (!s_initialized || !s_enabled) return;
TracyFrameMark();
}
/// <summary>
/// 绘制数值(用于实时监控变量)
/// </summary>
[System.Diagnostics.Conditional("TRACY_ENABLE")]
public static void Plot(string name, double value)
{
if (!s_initialized || !s_enabled) return;
TracyPlotValue(name, value);
}
/// <summary>
/// 绘制整数值
/// </summary>
[System.Diagnostics.Conditional("TRACY_ENABLE")]
public static void Plot(string name, int value)
{
Plot(name, (double)value);
}
/// <summary>
/// 绘制浮点数值
/// </summary>
[System.Diagnostics.Conditional("TRACY_ENABLE")]
public static void Plot(string name, float value)
{
Plot(name, (double)value);
}
/// <summary>
/// 发送消息到 Tracy
/// </summary>
[System.Diagnostics.Conditional("TRACY_ENABLE")]
public static void Message(string message)
{
if (!s_initialized || !s_enabled) return;
TracyMessage(message);
}
/// <summary>
/// 设置当前线程名称
/// </summary>
[System.Diagnostics.Conditional("TRACY_ENABLE")]
public static void SetThreadName(string name)
{
if (!s_initialized || !s_enabled) return;
TracySetThreadName(name);
}
/// <summary>
/// Tracy Zone 的作用域包装器
/// 使用 using 语句自动管理生命周期
/// </summary>
public struct ZoneScope : IDisposable
{
private bool isValid;
private string zoneName;
public ZoneScope(string name)
{
zoneName = name;
isValid = s_initialized && s_enabled;
#if TRACY_ENABLE
if (isValid)
{
TracyZoneBegin(name);
}
#endif
}
public void Dispose()
{
#if TRACY_ENABLE
if (isValid && s_initialized && s_enabled)
{
TracyZoneEnd();
}
#endif
}
}
/// <summary>
/// 创建一个 Tracy Zone性能追踪区域
/// 使用 using 语句确保自动结束
/// </summary>
/// <example>
/// using (Tracy.Zone("MyFunction"))
/// {
/// // 要追踪的代码
/// }
/// </example>
public static ZoneScope Zone(string name)
{
return new ZoneScope(name);
}
/// <summary>
/// 开始一个命名的 Zone
/// 注意:必须手动调用 EndZone() 结束,推荐使用 Zone() 方法配合 using 语句
/// </summary>
[System.Diagnostics.Conditional("TRACY_ENABLE")]
public static void BeginZone(string name)
{
if (!s_initialized || !s_enabled) return;
TracyZoneBegin(name);
}
/// <summary>
/// 结束当前 Zone
/// 注意:必须与 BeginZone() 配对使用
/// </summary>
[System.Diagnostics.Conditional("TRACY_ENABLE")]
public static void EndZone()
{
if (!s_initialized || !s_enabled) return;
TracyZoneEnd();
}
}
/// <summary>
/// Tracy Zone 的属性标记版本
/// 可以标记在方法上,自动追踪整个方法
/// 注意:需要配合 AOP 或代码生成工具使用
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class TracyZoneAttribute : Attribute
{
public string Name { get; set; }
public TracyZoneAttribute(string name = null)
{
Name = name;
}
}
}