【Unity】【エディタ拡張】InspectorからSceneビューのカメラを操作する

SceneビューのカメラをInspectorから切り替えるボタンを作る方法です。

Unity2019.2.6

やりたいことと問題点

Sceneビューではカメラを自由に操作できます。
いま、このカメラをInspectorのボタンにより編集できるようにします。

まず思いつくのがOnInspectorGUIでボタンを描画した後すぐにSceneビューのカメラを操作する方法です。

using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class Example : MonoBehaviour {}

#if UNITY_EDITOR
[CustomEditor(typeof(Example))]
public class ExampleInspector : Editor
{
    public override void OnInspectorGUI()
    {
        using (new EditorGUILayout.HorizontalScope()) {
            if (GUILayout.Button("Back")) {
                 SceneView.currentDrawingSceneView.LookAt(Vector3.zero, Quaternion.identity, 10, false, false);
            }
            else if (GUILayout.Button("Top")) {
                SceneView.currentDrawingSceneView.LookAt(Vector3.zero, Quaternion.AngleAxis(90, Vector3.right), 10, false, false);
            }
            else if (GUILayout.Button("Left")) {
                 SceneView.currentDrawingSceneView.LookAt(Vector3.zero, Quaternion.AngleAxis(90, Vector3.up), 10, false, false);
            }
        }
    }
}
#endif

しかしこのボタンを押下するとNullReferenceExceptionがスローされてしまいます。
どうやらOnInspectorGUIの時点ではSceneView.currentDrawingSceneViewにアクセスできないようです。

解決方法

SceneView.currentDrawingSceneViewにはOnSceneGUI()内でアクセスすれば正常に取得できます。
そのため、下記のような実装をすればInspectorからカメラを操作できることが確認できました。

using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class Example : MonoBehaviour {}

#if UNITY_EDITOR
[CustomEditor(typeof(Example))]
public class ExampleInspector : Editor
{
    private System.Action _postOnSceneGUI;

    private void OnSceneGUI()
    {
        _postOnSceneGUI?.Invoke();
        _postOnSceneGUI = null;
    }

    public override void OnInspectorGUI()
    {
        using (new EditorGUILayout.HorizontalScope()) {
            if (GUILayout.Button("Back")) {
                 _postOnSceneGUI += () => SceneView.currentDrawingSceneView.LookAt(Vector3.zero, Quaternion.identity, 10, false, false);
                SceneView.RepaintAll();
            }
            else if (GUILayout.Button("Top")) {
                 _postOnSceneGUI += () => SceneView.currentDrawingSceneView.LookAt(Vector3.zero, Quaternion.AngleAxis(90, Vector3.right), 10, false, false);
                SceneView.RepaintAll();
            }
            else if (GUILayout.Button("Left")) {
                 _postOnSceneGUI += () => SceneView.currentDrawingSceneView.LookAt(Vector3.zero, Quaternion.AngleAxis(90, Vector3.up), 10, false, false);
                SceneView.RepaintAll();
            }
        }
    }
}
#endif