유니티 XR Plug-in Management #Initialize XR on Startup

VR개발을 하다 보면 에디터를 실행할 때 에어링크로 연결된 기기가 재생이 되지 않고 PC를 이용한 에디터 디버깅이 필요할 때가 종종 생깁니다.

Initialize XR on Startup

 

에어링크가 연결된 상태임에도 불구하고 PC로 에디터를 컨트롤 하기 위해서는 프로젝트 세팅에 있는 XR 플러그인 매니지먼트의 Initialize XR on Startup부분을 비활성화해주면 됩니다.

 

하지만, 매번 저 윈도우창에 들어가서 껐다 켰다 하기란 매우 불편한 과정입니다.


모습

토글

 

그래서 에디터 상단에 토글을 이용하여 저 부분을 껐다 켰다 할 수 있는 기능을 만들어 보았습니다.

큰 문제는 되지 않으나 윈도우 창에서 토글을 건드려도 에디터 상단 토글은 업데이트 되지 않습니다.

 

따라서, 에디터 상단 토글을 이용하시길 추천드립니다.

 


코드

using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.XR.Management;
using UnityToolbarExtender;

[InitializeOnLoad]
public class InitializeXREditorToggle : EditorWindow
{
    private const string InitManagerPrefKey = "InitXRManagerOnStart";
    private static bool InitManagerOnStart;

    static InitializeXREditorToggle()
    {
        // EditorPrefs에서 초기값 불러오기
        InitManagerOnStart = EditorPrefs.GetBool(InitManagerPrefKey, false);
        // XRGeneralSettings.asset과 동기화
        SyncWithXRGeneralSettings();
        // 툴바에 토글 추가
        ToolbarExtender.RightToolbarGUI.Add(ShowToggle);
    }

    private static void ShowToggle()
    {
        XRGeneralSettings generalSettings = XRGeneralSettings.Instance;
        if (generalSettings != null)
        {
            InitManagerOnStart = generalSettings.InitManagerOnStart;
        }
        else
        {
            InitManagerOnStart = EditorPrefs.GetBool(InitManagerPrefKey, false);
        }

        EditorGUI.BeginChangeCheck();
        bool newValue = GUILayout.Toggle(InitManagerOnStart, "Initialize XR[Standalone]");
        if (EditorGUI.EndChangeCheck())
        {
            UpdateInitManagerState(newValue);
        }
        // 강제 재갱신 – 에디터와 PC Play 모드에서 실시간 반영
        EditorApplication.QueuePlayerLoopUpdate();
        UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
    }

    private static void UpdateInitManagerState(bool newState)
    {
        InitManagerOnStart = newState;

        EditorPrefs.SetBool(InitManagerPrefKey, InitManagerOnStart);
        PlayerPrefs.SetInt(InitManagerPrefKey, InitManagerOnStart ? 1 : 0);
        PlayerPrefs.Save();

        // XRGeneralSettings.asset 직접 수정 (AssetDatabase를 통해)
        string[] guids = AssetDatabase.FindAssets("t:XRGeneralSettings");
        if (guids.Length > 0)
        {
            string assetPath = AssetDatabase.GUIDToAssetPath(guids[0]);
            XRGeneralSettings settingsAsset = AssetDatabase.LoadAssetAtPath<XRGeneralSettings>(assetPath);
            if (settingsAsset != null)
            {
                SerializedObject serializedSettings = new SerializedObject(settingsAsset);
                SerializedProperty prop = serializedSettings.FindProperty("m_InitManagerOnStart");
                if (prop != null)
                {
                    prop.boolValue = InitManagerOnStart;
                    serializedSettings.ApplyModifiedProperties();
                }
                EditorUtility.SetDirty(settingsAsset);
                AssetDatabase.SaveAssets();
            }
        }

        // 에디터 내에서 로드된 모든 XRGeneralSettings 인스턴스를 찾아 reflection으로 업데이트
        XRGeneralSettings[] instances = Resources.FindObjectsOfTypeAll<XRGeneralSettings>();
        foreach (var instance in instances)
        {
            FieldInfo field = typeof(XRGeneralSettings).GetField("m_InitManagerOnStart", BindingFlags.NonPublic | BindingFlags.Instance);
            if (field != null)
            {
                field.SetValue(instance, InitManagerOnStart);
            }
            EditorUtility.SetDirty(instance);
        }
    }

    private static void SyncWithXRGeneralSettings()
    {
        XRGeneralSettings generalSettings = XRGeneralSettings.Instance;
        if (generalSettings != null)
        {
            if (generalSettings.InitManagerOnStart != InitManagerOnStart)
            {
                InitManagerOnStart = generalSettings.InitManagerOnStart;
                EditorPrefs.SetBool(InitManagerPrefKey, InitManagerOnStart);
                PlayerPrefs.SetInt(InitManagerPrefKey, InitManagerOnStart ? 1 : 0);
                PlayerPrefs.Save();
            }
        }
    }
}

 

에디터 폴더에서 작성하셔야 합니다.