🐼
VRChatのエラーログからUdonSharpソースコードの位置を調べる
背景
UdonSharpで例外が発生したとき、ClientSimで動かしている場合やUnityとVRCクライアントが繋がっている場合であれば、UnityのコンソールからUdonSharpソースコードのエラー箇所を知ることができます。
そうでない場合はVRChatエラーログからUdonSharpソースコード位置を算出することになります。
ソースコードが短い場合はこちらの記事を参考にUdonAssemblyとソースコードを照らし合わせて算出できますが、ソースコードが長くなるとだんだんと面倒になります。
本記事はこれについての対応の備忘録。
結論
対象のUdonSharpProgramAsset
とプログラムカウンタから、ソースコード位置を算出するエディタ拡張作ったのでコード公開します。
UdonSharpEditorの内部処理呼び出しているので、バージョンアップで動かなくなると思います。
少なくともUdon2.0では完全に。
出来る限り本記事のメンテします。
確認バージョン
バージョン | |
---|---|
Unity | 2019.4.31f1 |
VRChat SDK - Base | 3.1.10 |
VRChat SDK - Worlds | 3.1.10 |
UdonSharp | 1.1.5 |
エディタ拡張ソースコード
適当なEditorフォルダに格納してください。
UdonErrorAnalyzer.cs
using System;
using UnityEditor;
using UnityEngine;
using UdonSharp;
using UdonSharp.Compiler;
public class UdonErrorAnalyzer : EditorWindow
{
private UdonSharpProgramAsset _asset;
private int _programCounter;
private string _info = "";
[MenuItem("Test/UdonErrorAnalyzer")]
static void ShowWindow()
{
GetWindow<UdonErrorAnalyzer>("UdonErrorAnalyzer");
}
void OnGUI()
{
//UdonSharpProgramAsset指定
_asset = (UdonSharpProgramAsset)EditorGUILayout
.ObjectField($"Udon Asset", _asset, typeof(UdonSharpProgramAsset), true);
//プログラムカウンタ指定
_programCounter = EditorGUILayout.IntField("ProgramCounter", _programCounter);
if(_asset != null) {
//実行
if (GUILayout.Button("Analyze")) {
GUIUtility.keyboardControl = 0;
//UdonSharpEditor内部のデバッグ情報取得処理をReflectionで呼び出し
var type = Type.GetType("UdonSharp.UdonSharpEditorCache, UdonSharp.Editor");
var obj = type.GetProperty("Instance").GetValue(null);
var debugInfo = type.GetMethod("GetDebugInfo")
.Invoke(obj, new object[] { _asset, 0 }) as AssemblyDebugInfo;
debugInfo.GetPositionFromProgramCounter(
_programCounter,
out string filePath,
out string methodName,
out int line,
out int lineChar);
//表示するTextField用の文字列構築
_info = $"{filePath}, line:{line+1}, char:{lineChar}, func:{methodName} (pc:0x{_programCounter.ToString("X8")})";
//ついでにコンソールにも表示
type = Type.GetType("UdonSharp.UdonSharpUtils, UdonSharp.Editor");
type.GetMethod("LogRuntimeError").Invoke(null, new object[] {
$"(pc:0x{_programCounter.ToString("X8")})",
"[<color=#00FFFF>UdonErrorAnalyzer</color>]",
filePath,
line,
lineChar
});
}
EditorGUILayout.TextField("C# code info", _info);
}
}
}
使い方
- エラーログから対象のUdonSharpクラス名とプログラムカウンタを取得
-
エディタ拡張にクラス名に対応するUdonSharpProgramAssetとプログラムカウンタを指定して実行
-
ソースコード位置を取得
ついでにコンソールにも表示されます。ダブルクリックでソースコードの該当行を開いてくれます。
備考
Heap Dumpの情報とUdonAssemblyのdataセクション突き合わせればエラー発生時の各変数の情報がわかる。
この辺もツールで可視化できたら便利そう。
Discussion