Unity接入指引
本文是介绍Unity SDK的详细文档,包含了基本的接入流程,和高级的接口使用介绍,以及针对Unity引擎如何更早进行初始化等内容。 如果想快速接入,验证平台和SDK功能,建议查看项目菜单中的“接入指南”。引导中已经按项目具体的信息(平台,引擎,国内/海外,AppID)生成了针对此项目的初始化代码,可以直接复制使用。如下图所示:

项目创建:公司外部项目支持自助创建项目,但有免费试用时长。公司内部项目,企业微信联系“CrashSight小助手”开通。
本文档适用于CrashSight SDK 4.3.x版本。4.2.x版本接入请参考旧版本Unity SDK开发接入
1 Unity引擎C#接入方案
1.1 下载并导入Unity Plugin到Unity项目工程
在平台成功创建项目后,在侧边栏的“接入指南”中,可以下载到与项目平台和引擎相匹配的SDK。如下图所示:

1.2 初始化CrashSight
选择第一个场景,或者主场景(scene), 在尽可能较早加载的脚本中调用如下代码进行初始化:
// Debug开关,Debug模式下会打印更多便于问题定位的Log.
#if DEBUG
CrashSightAgent.ConfigDebugMode (true);
#endif
// 设置应用版本号 (必填)
CrashSightAgent.SetAppVersion("appVersion");
// 设置上报的目标域名,请根据项目需求进行填写。(必填)
CrashSightAgent.ConfigCrashServerUrl (CrashSightUploadUrl);
// 设置上报所指向的APP ID, 并进行初始化。APP ID可以在管理端更多->产品设置->产品信息中找到。
CrashSightAgent.InitWithAppId(CrashSightAppID);
上报域名
国内公有云:
- Android: https://android.crashsight.qq.com/pb/async
- iOS: https://ios.crashsight.qq.com/pb/sync
- Harmony: harmony.crashsight.qq.com
- Windows: pc.crashsight.qq.com
- Mac: https://mac.crashsight.qq.com/pb/sync
- PS5: https://ps5.crashsight.qq.com/pb/async
- Xbox: xbox.crashsight.qq.com
海外公有云
- Android: https://android.crashsight.wetest.net/pb/async
- iOS: https://ios.crashsight.wetest.net/pb/sync
- Windows: pc.crashsight.wetest.net
- Mac: https://mac.crashsight.wetest.net/pb/sync
- PS5: https://console.crashsight.wetest.net/pb/async
- Xbox: xbox.crashsight.wetest.net
1.3 集成配置
1.3.1 iOS集成配置
- 1)在Unity中修改项目的偏好设置(Build Settings) a. 按下 Ctrl+Shift+B打开Build Settings面板, 点击Player Settings切换到Setting for iOS选项卡,选择Other Settings栏,修改Optimization配置项Script Call Optimization的值为Slow and Safe
- 2)修改导出的Xcode工程的编译配置,切换到Build Phases选项卡, 在Link Binary With Libraries栏目下添加如下依赖性:
- libc++.dylib 或 libc++.tdb 用于引入c++标准库
- libz.dylib 或 libz.tdb 用于对上报的数据进行压缩
- Security.framework 用于存储keychain
- SystemConfiguration.framework 用于读取异常发生时的系统信息
- MetricKit.framework 用于获取apple提供的app诊断信息(弱引用,请选择“optional”)
- OSLog.framework 用于获取NSLog日志信息(弱引用,请选择“optional”)
- CFNetwork.framework 用于获取VPN 状态
注意:
- i. 如果项目已经添加过这些依赖项,不用重复添加。
- ii. 通过XUPorter集成无需在Xcode中添加配置。
1.3.2 安卓集成配置(配置native库提取)
未提取的native库会导致获取的崩溃堆栈无法还原。这种情况的表现为,堆栈中的崩溃模块是xx.apk而非xx.so,不能定位到具体的库。 为了避免未提取的native库对堆栈还原造成影响,请做如下配置:
(1)打包APK时,前往Project Settings -> Player -> Build,勾选Custom Main Manifest,并在AndroidManifest.xml中配置android:extractNativeLibs="true"
<application
...
android:extractNativeLibs="true">
(2)打包AAB时,前往Project Settings -> Player -> Build,勾选Custom Gradle Properties Template,并在gradleTemplate.properties中添加:
enableUncompressedNativeLibs = false
通过添加此参数,操作系统可以在应用程序崩溃时提供额外的信息,以帮助分析崩溃的原因。
1.3.3 鸿蒙集成配置
在导出Dev Eco工程以后,需要把CrashSightBridge.ts改名为CrashSightBridge.ets,然后再进行打包。
1.4 Unity 接入演示
- 1)双击下载好的插件中的CrashSightPlugin.unitypackage包,在Unity中出现如下界面,导入插件。

- 2)初始化。
private const string CrashSightAppIDForiOS = "685a68759e";
private const string CrashSightAppIDForAndroid = "e6af377f84";
private const string CrashSightUploadUrliOS = "https://ios.crashsight.qq.com/pb/sync";
private const string CrashSightUploadUrlAndroid = "https://android.crashsight.qq.com/pb/async";
CrashSightAgent.ConfigDebugMode (true);
CrashSightAgent.SetAppVersion("appVersion");
#if UNITY_IPHONE || UNITY_IOS
CrashSightAgent.ConfigCrashServerUrl(CrashSightUploadUrliOS);
CrashSightAgent.InitWithAppId(CrashSightAppIDForiOS);
#elif UNITY_ANDROID
CrashSightAgent.ConfigCrashServerUrl(CrashSightUploadUrlAndroid);
CrashSightAgent.InitWithAppId(CrashSightAppIDForAndroid);
#endif
1.5 接入结果测试
CrashSight测试接口
测试Java崩溃(Android)
static void TestJavaCrash();
测试Object-C崩溃(iOS)
static void TestOcCrash();
测试Native崩溃(Android&iOS,未来将支持全平台)
static void TestNativeCrash();
测试OOM崩溃(Android、iOS)
static void TestOomCrash();
测试ANR(仅Android)
static void TestANR();
测试释放后使用内存,仅GWP_Asan或MTE功能启用后生效(Android)
static void TestUseAfterFree();
强制Unity崩溃(全平台可用)
UnityEngine.Diagnostics.Utils.ForceCrash(ForcedCrashCategory.AccessViolation);
1.5.1 iOS测试方法
- a. 开启Debug模式,初始化CrashSight,并给定合适的配置参数
- b. 联网上报:检查测试设备日志中是否打印“begin to upload <CSAnalyticsLogic” 或者 “cmd: 641”
- c. 崩溃捕获:检查测试设备日志中是否打印“Handle the crash scene in callback”
- d. 上报异常:检查测试设备日志中是否打印“begin to upload <CSCrashLogic” 或者 “cmd: 631”
1.5.2 Android测试方法
- a. 开启Debug模式,初始化CrashSight,并给定合适的配置参数
- b. 联网上报:检查logcat日志是否打印“[Upload] Run upload task with cmd: 840”
- c. 崩溃捕获:检查logcat日志是否打印“HandleSignal start”
- d. 上报异常:检查logcat日志是否打印"[Upload] Run upload task with cmd: 830"
1.5.3 Windows测试方法
-
a.初始化CrashSight后,联网上报是否正常,具体验证方法如下:
- 初始化CrashSight;
- 5分钟后,在管理端页面的 异常概览 --> 崩溃趋势 --> 联网设备数 中可以看到统计数值大于等于1.
-
b.游戏发生崩溃,是否能正确上报,具体验证方法如下:
- 初始化CrashSight;
- 在游戏内可以由以下代码触发崩溃。(其他类似的坏内存访问也可以)
int* a = NULL;
a[10000] = 5; -
c.查看CrashSight64/dump目录(旧版本为TQM64/dump)下是否有dmp文件生成。如果没有,说明无法成功捕获崩溃,请联系CrashSight开发.
-
d.查看管理端页面 “崩溃分析”页上,是否有对应时间点的上报。如果3有,4没有,说明没有成功上报。请检查APPID配置(两个配置文件均要正确),以及APP KEY配置,是否对应且与应用设置中一样。如果配置正确,还无法上报,请联系CrashSight开发.
-
e.崩溃上报的版本号,用户名是否与设置一致.
-
f.错误上报的版本号,用户名是否与设置一致.
1.6 上 传符号表
以上内容介绍了SDK的接入,崩溃上报和验证,但要在页面上看到可读的还原堆栈,还需要上传对应的符号表,请见符号表上传工具使用说明
1.7 配置usym还原
此步骤可以为il2cpp模块的堆栈行补充C#文件名和行号信息。目前支持Android和iOS平台。
项目打包前
使用Unity6项目只需改变一个设置项。前往Project Settings->Player->Android->Other Settings->IL2CPP StackTrace Information,将选项设置为“Method Name, File Name, and Line Number”

使用Unity2022及以下的项目需要替换usymtool。由于只有Unity6版本的usymtool支持输出可用的usym文件,所以需要从Unity6复制一份usymtool到当前使用的引擎中。 在Windows平台上打包时,usymtool的位置是:PathToUnityEngine\Editor\Data\Tools\usymtool.exe 在Mac平台上打包时,usymtool的位置是:PathToUnityEngine/Contents/Tools/macosx/usymtool
对于使用Unity2022及以下的项目,替换usymtool可以支持对崩溃堆栈的usym还原,如果需要还原C#异常上报的堆栈或UnityLog错误上报的堆栈,则需额外修改部分引擎源 码。请参考下面的代码修改PathToUnityEngine/Data/il2cpp/libil2cpp/icalls/mscorlib/System.Diagnostics/StackTrace.cpp:
#if !IL2CPP_TINY
#include "il2cpp-config.h"
#include "il2cpp-class-internals.h"
#include "il2cpp-object-internals.h"
#include "gc/WriteBarrier.h"
#include "vm/Array.h"
#include "vm/Object.h"
#include "vm/Reflection.h"
#include "icalls/mscorlib/System.Diagnostics/StackTrace.h"
#include "vm-utils/DebugSymbolReader.h"
#include "vm/String.h"
namespace il2cpp
{
namespace icalls
{
namespace mscorlib
{
namespace System
{
namespace Diagnostics
{
static Il2CppArray* GetTraceInternal(Il2CppException* exc, int32_t skip, bool need_file_info)
{
Il2CppArray* trace_ips = exc->trace_ips;
Il2CppArray* nativetrace_ips = exc->native_trace_ips;
/* Exception is not thrown yet */
if (trace_ips == NULL)
return vm::Array::New(il2cpp_defaults.stack_frame_class, 0);
int len = vm::Array::GetLength(trace_ips);
Il2CppArray* stackFrames = vm::Array::New(il2cpp_defaults.stack_frame_class, len > skip ? len - skip : 0);
for (int i = skip; i < len; i++)
{
Il2CppStackFrame* stackFrame = NULL;
if (utils::DebugSymbolReader::DebugSymbolsAvailable())
{
stackFrame = il2cpp_array_get(trace_ips, Il2CppStackFrame*, i);
}
else
{
stackFrame = (Il2CppStackFrame*)vm::Object::New(il2cpp_defaults.stack_frame_class);
MethodInfo* method = il2cpp_array_get(trace_ips, MethodInfo*, i);
IL2CPP_OBJECT_SETREF(stackFrame, method, vm::Reflection::GetMethodObject(method, NULL));
uintptr_t fileNamePtr = il2cpp_array_get(nativetrace_ips, uintptr_t, i);
char buffer[32];
snprintf(buffer, sizeof(buffer), "0x%x", fileNamePtr);
stackFrame->filename = il2cpp::vm::String::New(buffer);
}
il2cpp_array_setref(stackFrames, i, stackFrame);
}
return stackFrames;
}
Il2CppArray* StackTrace::get_trace(Il2CppException *exc, int32_t skip, bool need_file_info)
{
// Exception.RestoreExceptionDispatchInfo() will clear trace_ips, so we need to ensure that we read it only once
return GetTraceInternal(exc, skip, need_file_info);
}
} /* namespace Diagnostics */
} /* namespace System */
} /* namespace mscorlib */
} /* namespace icalls */
} /* namespace il2cpp */
#endif