ゲーム作成のスピードを上げるには、よく使うコンポーネントのカスタムエディターを作成することがポイントになります。 例として、オブジェクトを常に一点で見続ける、この非常に単純なスクリプトを使用します。 このスクリプトをプロジェクトに追加し、シーン内の立方体のゲームオブジェクトに配置します。 スクリプトの名前は “LookAtPoint”
//C# Example (LookAtPoint.cs)using UnityEngine;public class LookAtPoint : MonoBehaviour{ public Vector3 lookAtPoint = Vector3.zero; void Update() { transform.LookAt(lookAtPoint); }}
//JS Example (LookAtPoint.js)#pragma strictvar lookAtPoint = Vector3.zero;function Update(){ transform.LookAt(lookAtPoint);}
これは、オブジェクトを世界空間の点に向け続けるものです。 現在のところ、このスクリプトはプレイモード、つまりゲームが動作しているときのみ有効になります。 エディタスクリプトを書くとき、ゲームが実行されていないときに、あるスクリプトを編集モードでも実行させると便利なことがあります。
//C# Example (LookAtPoint.cs)using UnityEngine;public class LookAtPoint : MonoBehaviour{ public Vector3 lookAtPoint = Vector3.zero; void Update() { transform.LookAt(lookAtPoint); }}
//JS Example (LookAtPoint.js)#pragma strict@script ExecuteInEditMode()var lookAtPoint = Vector3.zero;function Update(){ transform.LookAt(lookAtPoint);}
このスクリプトを持つオブジェクトをエディタで動かしたり、インスペクタで “Look At Point” の値を変更すると、プレイモードでない場合でも、オブジェクトはワールド空間のターゲットポイントを見たまま、その方向に対応するように更新されます。
Making a Custom Editor
上記は、編集時に簡単なスクリプトを実行させる方法を示していますが、これだけでは独自のエディター ツールを作成することはできません。
Unity でスクリプトを作成する場合、デフォルトでは MonoBehaviour を継承しているので、ゲーム オブジェクトに配置できる Component になっています。 ゲームオブジェクトに配置されると、Inspector は、整数、フロート、文字列、Vector3 など、表示可能なすべてのパブリック変数を表示および編集するためのデフォルトのインターフェイスを表示します。
以下は、上記のスクリプトのデフォルトのインスペクタの外観です。
A custom editor is a separate script that replaces this default layout with any editor controls you choose.
LookAtPoint スクリプト用のカスタム エディタを作り始めるために、同じ名前に “Editor” が付加された別のスクリプトを作成しなければなりません。 つまり、この例では 「
//c# Example (LookAtPointEditor.cs)using UnityEngine;using UnityEditor;public class LookAtPointEditor : Editor { SerializedProperty lookAtPoint; void OnEnable() { lookAtPoint = serializedObject.FindProperty("lookAtPoint"); } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(lookAtPoint); serializedObject.ApplyModifiedProperties(); }}
//JS Example (LookAtPointEditor.js)#pragma strict@CustomEditor(LookAtPoint)@CanEditMultipleObjectsclass LookAtPointEditor extends Editor { var lookAtPoint : SerializedProperty; function OnEnable() { lookAtPoint = serializedObject.FindProperty("lookAtPoint"); } function OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(lookAtPoint); serializedObject.ApplyModifiedProperties(); }}
このクラスは Editor から派生している必要があります。 CustomEditor属性は、Unityにどのコンポーネントのエディタとして動作するかを知らせます。 CanEditMultipleObjects属性は、このエディタで複数のオブジェクトを選択し、それらをすべて同時に変更できることをUnityに知らせます。 ここに任意のGUIコードを置くことができます。ゲーム用のOnGUIと同じように動作しますが、Inspectorの内部で実行されます。 エディタは、検査されるオブジェクトにアクセスするために使用できるターゲットプロパティを定義します。 カスタムインスペクタは次のようになります。
ここまでで行ったことは、デフォルトインスペクタが示すように、Vector3 フィールドを正確に再現しただけなので、結果は非常に似ています (「Script」フィールドは今は存在しません。それを表示するインスペクタコードを追加しなかったからですが)。
しかし、エディター スクリプトでインスペクターの表示方法を制御できるようになったので、好きなコードを使ってインスペクター フィールドをレイアウトし、ユーザーが値を調整し、グラフィックやその他の視覚的要素を表示することさえ可能になりました。 実際、地形システムやアニメーションのインポート設定など、より複雑なインスペクタを含むUnityエディタ内のすべてのインスペクタは、独自のカスタムエディタを作成するときにアクセスできるのと同じAPIを使用して作られています。
ここでは、ターゲット ポイントがゲーム オブジェクトの上か下かを示すメッセージを表示するためにエディター スクリプトを拡張する簡単な例を紹介します。 エディター ウィンドウ内でカメラを使用してシーンをレンダリングするなど、あらゆるタイプのインターフェイスを描画する IMGUI コマンドに完全にアクセスできます。
OnSceneGUI は OnInspectorGUI と同じように動作しますが、シーン ビューで実行されることが異なります。 シーン ビューで独自の編集コントロールを作成するために、Handles クラスで定義された関数を使用することができます。
//C# Example (LookAtPointEditor.cs)using UnityEngine;using UnityEditor;public class LookAtPointEditor : Editor{ SerializedProperty lookAtPoint; void OnEnable() { lookAtPoint = serializedObject.FindProperty("lookAtPoint"); } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(lookAtPoint); if (lookAtPoint.vector3Value.y > (target as LookAtPoint).transform.position.y) { EditorGUILayout.LabelField("(Above this object)"); } if (lookAtPoint.vector3Value.y < (target as LookAtPoint).transform.position.y) { EditorGUILayout.LabelField("(Below this object)"); } serializedObject.ApplyModifiedProperties(); } public void OnSceneGUI() { var t = (target as LookAtPoint); EditorGUI.BeginChangeCheck(); Vector3 pos = Handles.PositionHandle(t.lookAtPoint, Quaternion.identity); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Move point"); t.lookAtPoint = pos; t.Update(); } }}
//JS Example (LookAtPointEditor.js)#pragma strict@CustomEditor(LookAtPointJS)@CanEditMultipleObjectsclass LookAtPointEditorJS extends Editor { var lookAtPoint : SerializedProperty; function OnEnable() { lookAtPoint = serializedObject.FindProperty("lookAtPoint"); } function OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(lookAtPoint); serializedObject.ApplyModifiedProperties(); if (lookAtPoint.vector3Value.y > (target as LookAtPointJS).transform.position.y) { EditorGUILayout.LabelField("(Above this object)"); } if (lookAtPoint.vector3Value.y < (target as LookAtPointJS).transform.position.y) { EditorGUILayout.LabelField("(Below this object)"); } } function OnSceneGUI() { var t : LookAtPointJS = (target as LookAtPointJS); EditorGUI.BeginChangeCheck(); var pos = Handles.PositionHandle(t.lookAtPoint, Quaternion.identity); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "Move point"); t.lookAtPoint = pos; t.Update(); } }}
2DのGUIオブジェクト(GUI、EditorGUI、および友人)を配置したい場合は、Handles.BeginGUI()とHandles.EndGUI()への呼び出しでそれらをラップする必要があります。