Transformをこのようにする方法を紹介します。
このスクリプトをEditorフォルダ内に入れてください。
もろもろ
[CustomEditor(typeof(Transform))]
によって、「Transformの描画処理を置き換える」ことを高らかに宣言します。Editor
を継承するのを忘れずに。- 実際の描画処理は
OnInspectorGUI()
をoverrideします。 serializedObject.Update();
でインスペクタからこのスクリプトへ最新データの取得、serializedObject.ApplyModifiedProperties();
でこのスクリプトの変更をインスペクタに反映します。target
というのが実際にインスペクタで対象になっているオブジェクト(今回はTransform)なので、必要な型にキャストして使用します。Vector3Field()
などの描画系関数の戻り値が、インスペクタ上で値を変更したときの変更後の値になるので、それを適用することで変更の反映を行います。- Vector3の仕様からか、インスペクタの幅が狭くなると自動的に2行分の高さで描画されてしまうので、
GUILayout.Height(16)
で明示的にどの幅でも1行分の高さとして描画させます。 - Rotationで
Vector3Field()
に渡す値をtransform.rotation.eulerAngles
にしてしまってしばらくはまった。なぜだめなのかを理解するにはUnityの内部と四元数の理解が要るかも… - 値の変更もこのスクリプトが一手に請け負っているので、Undoの登録もこのスクリプトのやりたいタイミングでやる必要があります。
- 流れは、1.
Undo.RecordObjects(targets, "Change Transform");
を「値を変更する前に」呼ぶ 2. 値を変更する(すると変更を検知してUndoに登録される) 3.SetDirty()
してシーンに保存すべき変更があることをエディターに伝える - なので
RecordObjects()
はRecordObjectsOnNextChange()
というほうが適切って感じ。 - 複数選択もありうるのでそれぞれ
targets
,RecordObjects()
にしてます。要[CanEditMultipleObjects]
。 RecordObjects()
の第2引数の文字列はEdit > Undo/Redo
に表示される文字列です。
NGUIの実装は、いまよりも制約の多い時代のUnityの時に書かれたためか、かなり複雑なコードになっていますが、やっていることは基本的には同じです。簡単かと思いきや、意外と考えることの多いTransform拡張でした。