LoginSignup
0
0

More than 1 year has passed since last update.

Editor拡張のスクリプトから値を編集した際にオートセーブさせる

Posted at

※実際のコードから弄ってるので主要部分以外はコピペじゃ動かないかもしれません

問題点

 Inspector上から手動で値をセットするのが面倒だったのでEditor拡張で自動化したつもりだったが、何一つ反映されていなかった。どうやらEditor拡張から値を変更した場合は特殊な処理が必要になる。

環境

  • Unity 2020.3.26f
  • Windows 10

参考

今回は待ったのは Editor拡張 + Prefab編集です。
Editor拡張 + シーン編集はこちらの記事を参考にするとよいと思います。

問題のコード

ScriptBase.cs
using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using UnityEditor.Experimental.SceneManagement;
#endif

namespace KMVoyage.ModeScenes.MusicSelect
{
    internal abstract class ScriptBase : MonoBehaviour
    {
        [SerializeField] protected XxxComponent comp;

#if UNITY_EDITOR
        [CustomEditor(typeof(ScriptBase), true)]
        public class ScriptBaseEditor : Editor
        {
            public override void OnInspectorGUI()
            {
                var _target = target as ScriptBase;

                if (_target.info == null)
                    if (GUILayout.Button("Get XxxComponent"))
                        _target.comp = _target.gameObject.GetComponent<XxxComponent>();
                else
                    base.OnInspectorGUI();
            }
        }
#endif
    }
}

何が問題か

 ボタンを押したらGetComponentしてcompに入れるというシンプルなコード。compに値を入れる事は特に問題ないが、その値を入れたことがUnityに通知されない。Scene編集中にボタンを押しても変更があった事を表す*マークは付かない。ただこの場合はCtrl+sで保存をしてあげれば問題ない。
 厄介なのはPrefab編集中である。変更がUnityに通知されないのでAutoSaveが行われない。AutoSaveのチェックを外して手動でやろうとしても、Saveボタンがグレーアウトされたままなので保存が出来ない。関係ない部分を弄って戻せば保存はされるが、余計な手間とバグの原因を生み出すだけである。

解決方法

要はどうやって通知するか。それが重要だ。

解決したコード

ScriptBase.cs
using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using UnityEditor.Experimental.SceneManagement;
#endif

namespace KMVoyage.ModeScenes.MusicSelect
{
    internal abstract class ScriptBase : MonoBehaviour
    {
        [SerializeField] protected XxxComponent comp;

#if UNITY_EDITOR
        [CustomEditor(typeof(ScriptBase), true)]
        public class ScriptBaseEditor : Editor
        {
            public override void OnInspectorGUI()
            {
                var _target = target as ScriptBase;

                EditorGUI.BeginChangeCheck();

                if (_target.info == null)
                    if (GUILayout.Button("Get XxxComponent"))
                        _target.comp = _target.gameObject.GetComponent<XxxComponent>();
                else
                    base.OnInspectorGUI();

                if (EditorGUI.EndChangeCheck())
                {
                    var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
                    if (prefabStage != null)
                        EditorSceneManager.MarkSceneDirty(prefabStage.scene);
                    //var scene = SceneManager.GetActiveScene();
                    //EditorSceneManager.MarkSceneDirty(scene);
                }
            }
        }
#endif
    }
}

解説

0.cs
EditorGUI.BeginChangeCheck();
// 処理
if (EditorGUI.EndChangeCheck())

変更点の有無のチェック(これでわかるなら自動でやってくれと思う)

1.cs
var prefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if (prefabStage != null)
    EditorSceneManager.MarkSceneDirty(prefabStage.scene);

ここでprefab編集画面に変更を通知しているって事らしい。

2.cs
var scene = SceneManager.GetActiveScene();
EditorSceneManager.MarkSceneDirty(scene);

こちらはシーン編集画面で変更を通知する方法。

まとめ

解決したので寝られます。おやすみなさい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0