유니티에서 제공하는 Debug.Log를 커스터마이징 하고 싶을 때가 많다. 자체적으로 제공하는 콜백이나 로거를 커스텀하여 사용할 수도 있지만 Debug 클래스를 자체 제작하여 덮어 씌우는 방법을 많이 사용할 것이다.
public static class Debug {
public static void Log(object message){
// ~~~~
// CUSTOM!!!
// ~~~~
UnityEngine.Debug.Log(message);
}
}
이때, 유니티 에디터의 콘솔에서 찍힌 로그를 더블 클릭할 경우 해당 로그가 시작한 부분, 즉 커스텀 로그를 찍은 부분의 파일이 열리는 것이 아니라 커스텀한 로그 파일 자체가 열리게 된다. (위의 코드의 경우 2번째 줄)
이를 피하기 위해 로그를 더블 클릭할 시 경로를 추적하여 실제 열리기를 바랐던 파일을 열 수 있다.
static string LoggerName = "CustomDebug";
[OnOpenAsset(0)]
static bool OnOpenAsset(int instance, int line) {
string name = EditorUtility.InstanceIDToObject(instance).name;
if (name != LoggerName) return false;
string stack_trace = GetStackTrace();
if(!string.IsNullOrEmpty(stack_trace)) {
Match matches = Regex.Match(stack_trace, @"\(at(.+)\)", RegexOptions.IgnoreCase);
if (matches.Success) {
matches = matches.NextMatch();
if (matches.Success) {
string pathline;
pathline = matches.Groups[1].Value;
pathline = pathline.Replace(" ", "");
int split_index = pathline.LastIndexOf(":");
string path = pathline.Substring(0, split_index);
line = Convert.ToInt32(pathline.Substring(split_index + 1));
string fullpath = Application.dataPath.Substring(0, Application.dataPath.LastIndexOf("Assets"));
fullpath = fullpath + path;
UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(fullpath, line);
}
}
return true;
}
return false;
}
콘솔에서 더블클릭으로 에셋을 열 경우 유니티에서 제공한 OnOpenAsset Attribute가 붙은 함수가 불리게 된다. 이 이벤트가 불렸을 때, 부른 오브젝트를 추적하여 커스텀한 오브젝트가 아닐 경우 원래 동작으로 돌아간다.
커스텀 로그에서 불렀을 경우 스택을 추적하여 한 단계 위의 경로를 얻어낸다.
그 후 유니티에서 제공하는 OpenFileAtLineExternal 함수를 통해 실제 파일을 열 수 있다.
해당 함수는 Editor 스크립트에서만 동작한다.
스택을 추적하는 함수 GetStackTrace는 아래와 같이 구현한다.
static string GetStackTrace() {
var assembly_unity_editor = Assembly.GetAssembly(typeof(EditorWindow));
if (assembly_unity_editor == null) return null;
var type_console_window = assembly_unity_editor.GetType("UnityEditor.ConsoleWindow");
if (type_console_window == null) return null;
var field_console_window = type_console_window.GetField("ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic);
if (field_console_window == null) return null;
var instance_console_window = field_console_window.GetValue(null);
if (instance_console_window == null) return null;
if ((object)EditorWindow.focusedWindow == instance_console_window) {
var type_list_view_state = assembly_unity_editor.GetType("UnityEditor.ListViewState");
if (type_list_view_state == null) return null;
var field_list_view = type_console_window.GetField("m_ListView", BindingFlags.Instance | BindingFlags.NonPublic);
if (field_list_view == null) return null;
var value_list_view = field_list_view.GetValue(instance_console_window);
if (value_list_view == null) return null;
var field_active_text = type_console_window.GetField("m_ActiveText", BindingFlags.Instance | BindingFlags.NonPublic);
if (field_active_text == null) return null;
string value_active_text = field_active_text.GetValue(instance_console_window).ToString();
return value_active_text;
}
return null;
}
참고 및 출처 : Double-click the redirect script in Unity's Console window.
'Develop > Unity' 카테고리의 다른 글
[HiddenCity] 역 (0) | 2020.10.13 |
---|---|
[Unity] UGUI로 말풍선 만들기 (1) | 2017.03.13 |
[Unity] Unity ScrollRect에서 사용할 수 있는 동적 List 구현하기 (0) | 2017.03.06 |