Editor スクリプティング 入門
誰もが使えるそんな環境づくり
私はこんな人
Unity Technologies Japan
フィールドエンジニア
Editor拡張にお熱
@kyusyukeigo
安藤 圭吾
Editorスクリプトってなんだ
Editorスクリプトってなんだ
UnityEditorを拡張するためのスクリプト
Editorスクリプトってなんだ
インスペクターを拡張したり
Editorスクリプトってなんだ
インスペクターを拡張したり ウィンドウを作成したり
Editorスクリプトってなんだ
自動でテスターにアプリ配信したり
Editorスクリプトってなんだ
Jenkinsさんにお願いしたり
Emotional Jenkins - https://cacoo.com/store/items/10148
Editorスクリプトってなんだ
Jenkinsさんにお願いしたり 怒られたり
Emotional Jenkins - https://cacoo.com/store/items/10148
Editorスクリプトってなんだ
開発をスムーズに行うために
手助けをするもの
時間割いてまでやる
必要あるの?
必要か?
実際にあったことを少しだけご紹介
こんなことって...ない?
初期パラメータは
wikiに書いてます
こんなことって...ない?
コピペ
スプレッドシートに一覧
初期パラメータはwikiに
書いてます
こんなことって...ない?
こんなことって...ない?
パラメータは
ContextMenuで管理
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
	 [ContextMenu("Hoge")]
	 public void Hoge ()
	 {
	 	 HogeScript h = GetComponent<HogeScript> ();
	 	 h.str = "hoge";
	 }
	 [ContextMenu("Fuga")]
	 public void Fuga (){}
	
	 [ContextMenu("Foo")]
	 public void Foo (){}
}
ContextMenuのためのScript...
パラメータは
ContextMenuで管理
こんなことって...ない?
こんなことって...ない?
パラメータはContextMenu
で管理
ランライム側
余計なコード
エディター側
に書け!
ちょっと
どこ触ってんの!
こんなことって...ない?
こんなことって...ない?
ちょっと
どこ触ってんの!
なんか動かないんだけど... どれどれ...
こんなことって...ない?
ちょっと
どこ触ってんの!
−90じゃなくて 270にして!
こんなことって...ない?
ちょっと
どこ触ってんの!
触ってほしくない所を触ってる!
こんなことって...ない?
ちょっと
どこ触ってんの!
触ってほしくない所を触ってる!
2Dのとき
Z軸は大丈夫?
こんなことって...ない?
ちょっと
どこ触ってんの!
Transform
こんなことって...ない?
ちょっと
どこ触ってんの!
Z軸削除
Transform
こんなことって...ない?
見せない
CustomEditorを使う触らせたくないもの
ちょっと
どこ触ってんの!
Editorスクリプトはこんな時に便利
コンパクト
見やすい / 目立つ
Editorスクリプトはこんな時に便利
Editorスクリプトはこんな時に便利
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
public class PostProcess
{
	 [PostProcessBuild]
	 static void OnPostprocessBuild (BuildTarget target, string pathToBuiltProject)
	 {
	 	 //フレームワーク追加とか
	 }
	 [PostProcessScene]
	 static void OnPostprocessScene ()
	 {
	 	 //デバッグ時のみに追加したいマネージャー(GameObject)追加とか
	 }
}
ビルド前後の処理自動化
Editorスクリプトはこんな時に便利
using UnityEngine;
using UnityEditor;
public class AssetModification : UnityEditor.AssetModificationProcessor
{
	 static void OnWillCreateAsset (string path){}
	 static void OnWillSaveAssets (string[] paths){}
	
	 static AssetMoveResult OnWillMoveAsset (string from, string to)
	 {
	 	 return AssetMoveResult.FailedMove; //ここでアセット移動制限
	 }
	
	 static AssetDeleteResult OnWillDeleteAsset (string path, RemoveAssetOptions option)
	 {
	 	 return AssetDeleteResult.FailedDelete; //ここでアセット削除制限
	 }
}
アセット管理
移動すんな!
削除すんな!
今回話すこと
GUI周りについて
PropertyDrawer
PropertyDrawer
PropertyDrawerって何
PropertyDrawer
PropertyDrawerって何
(シリアライズされたフィールドで)
カスタマイズするためのもの
インスペクターに表示されるGUIを
...PropertyDrawerって何
これ
つまり
public変数
PropertyDrawer
public Vector3 vector3;
パッと見たいときに
少し使いづらい
PropertyDrawer
...PropertyDrawerって何
[Compact]
public Vector3 vector3;
https://github.com/anchan828/property-drawer-collection/tree/master/CompactAttribute
PropertyDrawer
...PropertyDrawerって何
自分で作れる
PropertyDrawer
自分で作れる
PropertyDrawer
[Compact]
public Vector3 vector3;
using UnityEngine;
public class CompactAttribute : PropertyAttribute {}
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(CompactAttribute))]
public class CompactDrawer : PropertyDrawer
{
	 public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
	 {
	 	 ...
	 }
}
自分で作れる
PropertyAttribute
PropertyDrawer
using UnityEngine;
public class CompactAttribute : PropertyAttribute {}
PropertyDrawer
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof( Hoge ))]
public class CompactDrawer : PropertyDrawer
{
	 public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
	 {
	 	 ...
	 }
}
自分で作れる
シリアライズされた
クラス
[System.Serializable]
public class Hoge
{
public float number;
}
PropertyDrawer
FindPropertyRelative
唯一、使い回し出来るEditor拡張
(だと思ってる)
プロジェクトと切り分けてコードを書くことが容易
PropertyDrawer
ネタ
PreviewTexture
https://github.com/anchan828/property-drawer-collection/tree/master/PreviewTextureAttribute
PropertyDrawer
AnimatorParameter
LabelSearch
Password
Popup
SceneName
要望/バグあれば
issueお願い
https://github.com/anchan828/property-drawer-collection
PropertyDrawer
EditorWindow
EditorWindow
EditorWindowって何
UnityEditorはEditorWindowで成り立っている
EditorWindow
EditorWindow
EditorWindow
EditorWindow
EditorWindow
EditorWindow
EditorWindow
EditorWindowの作り方
EditorWindowはScriptableObject継承
EditorWindow
EditorWindowの作り方
EditorWindowはScriptableObject継承
なのでCreateInstanceで生成できる
EditorWindow
EditorWindowの作り方
CreateInstance
複数同じEditorWindow生成
EditorWindow
EditorWindowの作り方
CreateInstance
GetWindow<T>
複数同じEditorWindow生成
必ず1つのEditorWindow生成
EditorWindow
EditorWindowの作り方
GetWindowについて
• 内部でCreateInstanceが呼び出される
EditorWindow
EditorWindowの作り方
GetWindowについて
• 内部でCreateInstanceが呼び出される
• 生成されたEditorWindowはキャッシュされる
EditorWindow
EditorWindowの作り方
GetWindowについて
• 内部でCreateInstanceが呼び出される
• 生成されたEditorWindowはキャッシュされる
• Showが呼ばれる
EditorWindow
EditorWindowの種類
• Normal ( Show )
• Aux
• Popup
• Utility
• DropDown
• ScriptableWizard
• Preference
用途に合わせて
使い分ける
http://docs.unity3d.com/Documentation/ScriptReference/EditorWindow.html
http://anchan828.hatenablog.jp/entry/2013/02/17/020603
EditorWindow
EditorWindowでGUI
UnityのGUIStyleを使いたい
EditorWindow
EditorWindowでGUI
EditorGUIUtility.GetBuildinSkin
EditorWindow
EditorWindowでGUI
EditorGUIUtility.GetBuiltinSkin
Game
Scene
Inspector
Skin
EditorWindow
EditorWindowでGUI
EditorGUIUtility.GetBuiltinSkin
Game
Scene
Inspector
Label
Button
Toggle
Skin
Style
EditorWindow
EditorWindowでGUI
EditorStyles
EditorGUIUtility.GetBuiltinSkin
Game
Scene
Inspector
Label
Button
Toggle
Skin
Style
EditorWindow
EditorWindowでGUI
EditorStyles
EditorGUIUtility.GetBuiltinSkin
Game
Scene
Inspector
Label
Mini Button
Toggle
Label
Button
Toggle
Skin
Style
EditorWindow
EditorWindowでGUI
ビルドインされてるGUISkinのCustomStyleを使いたい
UnityのGUIStyleを使いたい
EditorWindow
ビルドインのGUISkinにあるCustomStyle名を知る
EditorWindow
現在ではCustomStyle名を知る術はない
ビルドインのGUISkinにあるCustomStyle名を知る
EditorWindow
現在ではCustomStyle名を知る術はない
むりやり知るには、ScriptableObjectで保存
ビルドインのGUISkinのCustomStyle名を知る
EditorWindow
using UnityEngine;
using UnityEditor;
public class BuildinSkins : ScriptableObject
{
public GUISkin game = EditorGUIUtility.GetBuiltinSkin (EditorSkin.Game);
public GUISkin inspector = EditorGUIUtility.GetBuiltinSkin (EditorSkin.Inspector);
public GUISkin scene = EditorGUIUtility.GetBuiltinSkin (EditorSkin.Scene);
}
AssetDatabase.CreateAsset (ScriptableObject.CreateInstance<BuildinSkins> (), "Assets/BuildinSkins.asset");
BuildInSkinのCustomStyle名を知る
http://anchan828.hatenablog.jp/entry/2013/02/17/024650
EditorWindow
.assetで保存してInspectorで見る
400以上CustomStyleがある
BuildInSkinのCustomStyle名を知る
EditorWindow
BuildInSkinのCustomStyle名を知る
ただしStyle名は今後変更される可能性があるので注意
.assetで保存してInspectorで見る
400以上CustomStyleがある
EditorWindow
UnityらしいEditorWindowを作成する
混乱を招かない
ように
GUIを知るはじめの一歩
• CustomEditor ( Attribute )
• Editor ( Class )
この2つを知ること
Editor
Editorクラスって何?
インスペクターとシーンビューの
GUIを表示するためのクラス
Editor
OnInspectorGUI インスペクターのGUIを描画する
Editor
OnInspectorGUI
OnPreviewGUI プレビューを描画する
インスペクターのGUIを描画する
Editor
OnInspectorGUI
OnPreviewGUI プレビューを描画する
インスペクターのGUIを描画する
OnSceneGUI シーンビューのGUIを描画する
Editor
OnInspectorGUI
3rd Person Controller ( Prefab )
Editor
OnInspectorGUI
OnPreviewGUI
3rd Person Controller ( Prefab )
Editor
OnInspectorGUI
OnPreviewGUI
3rd Person Controller ( Prefab )
OnSceneGUI
Editor
3rd Person Controller ( Prefab )
Editor
GameObjectInspector
TransformInspector
CharacterControllerEditor
AnimationEditor
MonoScriptInspector
Editor
Transform Inspectorみたいなのを作るには
CustomEditorを使う
CustomEditor
CustomEditorって何
Editorを継承したクラスを使用する
ためのAttribute
CustomEditor
CustomEditorって何
[CustomEditor(typeof(HogeScript))]
[CanEditMultipleObjects]
public class Custom : Editor
{	
	 public override void OnInspectorGUI ()
	 {
	 	 EditorGUIUtility.LookLikeInspector ();
	 	 HogeScript h = (HogeScript)target;
	 	 EditorGUI.BeginChangeCheck ();
	 	 string str = EditorGUILayout.TextField ("label", h.str);
	 	 if (EditorGUI.EndChangeCheck ()) {
	 	 	 h.str = str;
	 	 	 EditorUtility.SetDirty (h);
	 	 }
	 }
}
Editorを継承
CustomEditor
CanEditMultipleObjects
OnInspectorGUI
OnPreviewGUI
この部分を自由にカスタマイズできるようになる
OnSceneGUI
CustomEditor
editorForChildClassesでサブクラス(子クラス)を拡張
CustomEditor
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(Component), true)]
public class CustomComponent : Editor
{
	 private string memo = "";
	 public override void OnInspectorGUI ()
	 {
	 	 EditorGUI.BeginChangeCheck ();
	 	 string _memo = EditorGUILayout.TextArea (memo);
	 	 if (EditorGUI.EndChangeCheck ()) {
	 	 	 memo = _memo;
	 	 }
	 }
}
Editor
GUI使いたいけどどうするの?
Editor.CreateEditorでEditor作ってOnInspectorGUI
Editor.CreateEditor ( transform );
Editor
Preview使いたいけどどうするの?
Editor.CreateEditorでEditor作ってOnPreviewGUI
Editor.CreateEditor ( material );
Editor
こんな感じでEditorを生成する
Editor.CreateEditor ( transform );
Editor.CreateEditor ( material );
CustomEditorが複数ある場合は
Editor.CreateEditor ( transform, typeof(CustomTransform) );
Editor
Editorクラスを理解
することが
エディタ拡張(GUI)の
スタートライン
各WindowのOnGUI
既にUnityに実装してあるEditorWindow
EditorWindow
各WindowのOnGUI
OnGUIイベントをデリゲートに登録できる
• プロジェクトウィンドウ
EditorApplication.projectWindowItemOnGUI
• ヒエラルキーウィンドウ
EditorApplication.hierarchyWindowItemOnGUI
各WindowのOnGUI
• プロジェクトウィンドウ
projectWindowItemOnGUI
ファイルサイズ表示
各WindowのOnGUI
• ヒエラルキーウィンドウ
hierarchyWindowItemOnGUI
アイコン表示
Handles
Handles
Handles って何
3D GUI を表示するためのクラス
Handles
3D GUI の種類
まだ沢山ある
Handles
どこで使う?
Editor の OnSceneGUI で書く
void OnSceneGUI ()
{
	 transform.position =
	 	 Handles.DoPositionHandle (transform.position, Quaternion.identity);
}
シーンビューで使用する
Handles
2D GUI と 3D GUI の棲み分け
2D GUIを使うときはHandles.BeginGUI
void OnSceneGUI ()
{
	 GUILayout.Label ("表示されない");	
}
void OnSceneGUI ()
{
	 Handles.BeginGUI ();
	 GUILayout.Label ("表示される");	
	 Handles.EndGUI ();
}
Handles
SceneViewをカスタマイズしよう
GUIのお話終わり
時間割いてまでやる
必要あるの?
必要か?
最後のまとめ
開発者自身がEditor拡張は必要!と思うこと
触らせたくないものは見せるな!
Editorクラスを正しく理解すること
Questions ?
ご清聴ありがとうございました

Editor スクリプティング 入門