Your SlideShare is downloading. ×
知って得するUnity エディタ拡張編
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

知って得するUnity エディタ拡張編

18,122

Published on

Published in: Technology
1 Comment
63 Likes
Statistics
Notes
No Downloads
Views
Total Views
18,122
On Slideshare
0
From Embeds
0
Number of Embeds
14
Actions
Shares
0
Downloads
120
Comments
1
Likes
63
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. 知って得する Unity エディタ拡張編 株式会社ハ・ン・ド プログラマ 馬場翔太 http://baba-s.hatenablog.com/
  • 2. スライド内容 1. PropertyDrawerでUnityエディタを拡張する 2. AssetPostprocessorでアセットを監視する 3. MenuItemでソースコードを自動生成する
  • 3. PropertyDrawerで Unityエディタを拡張する
  • 4. エディタ拡張は二通りの方法で行えます • CustomEditorを使用する スクリプト単位によるエディタ拡張 • PropertyDrawerを使用する プロパティ単位によるエディタ拡張 このスライドで紹介する機能 使いまわしやすい!
  • 5. 標準で用意されているPropertyDrawer • RangeAttribute • MultilineAttribute
  • 6. RangeAttributeを使うと… 値の入力範囲を制限できるようになります using UnityEngine; public class Character : MonoBehaviour { [Range(1, 100)] public int Level = 1; }
  • 7. MultilineAttributeを使うと… 文字列を複数行で入力できるようになります using UnityEngine; public class Character : MonoBehaviour { [Multiline(3)] public string Comment; }
  • 8. 独自のPropertyDrawerを作成して使用する RangeAttributeやMultilineAttributeのような PropertyDrawerは自分で作成可能です
  • 9. 独自のPropertyDrawerを作成して使用する プロパティ名を変更できる PropertyDrawerを作成してみましょう using UnityEngine; public class Character : MonoBehaviour { [MyProperty("名前")] public string Name; }
  • 10. using UnityEngine; public class MyPropertyAttribute : PropertyAttribute { public string Label; public MyPropertyAttribute(string label) { Label = label; } } 1.PropertyAttributeを継承したクラス作成
  • 11. using UnityEditor; using UnityEngine; [CustomPropertyDrawer(typeof(MyPropertyAttribute))] public class MyPropertyDrawer : PropertyDrawer { } 2.PropertyDrawerを継承したクラスを作成
  • 12. public override void OnGUI( Rect position, SerializedProperty property, GUIContent label) { var myPropertyAttribute = attribute as MyPropertyAttribute; property.stringValue = EditorGUI.TextField( position, myPropertyAttribute.Label, property.stringValue); } 3. OnGUI関数をオーバーライドして実装
  • 13. using UnityEngine; public class Character : MonoBehaviour { [MyProperty("名前")] public string Name; } 4.作成したPropertyDrawerを使用する
  • 14. PropertyDrawer作成時の注意 PropertyDrawerを継承したクラスは Editorフォルダに保存するか #if UNITY_EDITOR ~ #endifで囲まないと ビルド時にエラーになるので気をつけてください
  • 15. MyPropertyAttribute.csを手に入れる 今回作成したMyPropertyAttributeは Gistで公開しているので参考にしてください 1. 下記のサイトからMyPropertyAttribute.csを取得する https://gist.github.com/baba-s/9430324 2. 下記のサイトからMyPropertyDrawer.csを取得する https://gist.github.com/baba-s/9430335 3. MyPropertyAttribute.csを Unityプロジェクトに追加する 4. MyPropertyDrawer.csを UnityプロジェクトのEditorフォルダに追加する
  • 16. PropertyDrawerのサンプル https://github.com/anchan828/property-drawer-collection http://blogs.unity3d.com/2012/09/07/property-drawers-in-unity-4/ ネット上で公開されている PropertyDrawerを使用してみましょう • CompactAttribute • EnumLabelAttribute • PopupAttribute • SceneNameAttribute • RegexAttribute
  • 17. using UnityEngine; public class Character : MonoBehaviour { public Vector3 Position; } Vector2やVector3の入力を楽にしたい
  • 18. CompactAttribute.csを手に入れる 1. 下記のサイトからCompactAttribute.csを取得する https://github.com/anchan828/property-drawer-collection 2. CompactAttribute.csをUnityプロジェクトに追加する
  • 19. using UnityEngine; public class Character : MonoBehaviour { [Compact] public Vector3 Position; } CompactAttributeを使用する
  • 20. using UnityEngine; public class Character : MonoBehaviour { public enum JobType { SOLDIER, SORCERER, } public JobType Job; } 列挙型の表示名を変えたい
  • 21. EnumLabelAttribute.csを手に入れる 1. 下記のサイトからEnumLabelAttribute.csを取得する https://github.com/anchan828/property-drawer-collection 2. EnumLabelAttribute.csをUnityプロジェクトに追加する
  • 22. using UnityEngine; public class Character : MonoBehaviour { public enum JobType { [EnumLabel("王国兵士")] SOLDIER, [EnumLabel("魔法使い")] SORCERER, } [EnumLabel("ジョブ")] public JobType Job; } EnumLabelAttributeを使用する
  • 23. using UnityEngine; public class Character : MonoBehaviour { public string Job; public int Money; } 入力できる値をポップアップで制限したい
  • 24. PopupAttribute.csを手に入れる 1. 下記のサイトからPopupAttribute.csを取得する https://github.com/anchan828/property-drawer-collection 2. PopupAttribute.csをUnityプロジェクトに追加する
  • 25. using UnityEngine; public class Character : MonoBehaviour { [Popup("王国兵士", "魔法使い")] public string Job; [Popup(1, 5, 10, 50, 100, 500)] public int Money; } PopupAttributeを使用する
  • 26. using UnityEngine; public class LoadSceneButton : MonoBehaviour { public string SceneName; } ポップアップでシーン名を設定したい
  • 27. SceneNameAttribute.csを手に入れる 1. 下記のサイトからSceneNameAttribute.csを取得する https://github.com/anchan828/property-drawer-collection 2. SceneNameAttribute.csをUnityプロジェクトに追加する
  • 28. using UnityEngine; public class LoadSceneButton : MonoBehaviour { [SceneName] public string SceneName; } SceneNameAttributeを使用する
  • 29. using UnityEngine; public class Config : MonoBehaviour { // IPアドレス public string ServerAddress; } 入力できる値を正規表現で制限したい
  • 30. RegexAttribute.csを手に入れる 1. 下記のサイトからRegexAttribute.csを取得する https://gist.github.com/baba-s/9430471 2. RegexAttribute.csをUnityプロジェクトに追加する
  • 31. using UnityEngine; public class Config : MonoBehaviour { // IPアドレス [Regex(@"^(?:¥d{1,3}¥.){3}¥d{1,3}$", "無効なIPアドレスです!例:'127.0.0.1'")] public string ServerAddress; } RegexAttributeを使用する
  • 32. PropertyDrawerまとめ PropertyDrawerを使用すると スクリプト単位ではなく プロパティ単位でエディタ拡張が可能なので 多くのスクリプトやプロジェクトで使いまわせます
  • 33. AssetPostprocessorで アセットを監視する
  • 34. AssetPostprocessorを使うと… • 特定のファイルのみ Unityプロジェクトに追加不能にできる • テクスチャやAudioClipの設定を Unityプロジェクトに追加された時に変更できる
  • 35. 独自のAssetPostprocessorを作成してみる 全角文字が含まれたファイルが プロジェクトに追加されたら自動で削除する AssetPostprocessorを作成してみましょう
  • 36. 1.AssetPostprocessorのサブクラスを作成 using UnityEditor; using UnityEngine; public class MyAssetPostprocessor : AssetPostprocessor { }
  • 37. 2.全角文字を含むか判定する関数を追加 // 1バイト文字で構成された文字列かどうかを判定します // 1バイト文字のみで構成された文字列の場合 true // 2バイト文字が含まれている文字列の場合 false private static bool IsOneByteStr(string str) { var bytes = System.Text.Encoding.GetEncoding(932).GetBytes(str); return bytes.Length == str.Length; } http://7ujm.net/NET%20Framework/isOneByteChar.html
  • 38. 3. OnPostprocessAllAssets関数を定義 // すべてのアセットのインポートが終了した際に呼び出されます // importedAssets :インポートされたアセットのパス // deletedAssets :削除されたアセットのパス // movedAssets :移動したアセットの移動後のパス // movedFromPath:移動したアセットの移動前のパス private static void OnPostprocessAllAssets( string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromPath) { }
  • 39. 4.AssetDatabase.DeleteAssetを利用 foreach (var importedAsset in importedAssets) { if (!IsOneByteStr(importedAsset)) { // 指定されたパスに存在するアセットを削除します if (AssetDatabase.DeleteAsset(importedAsset)) { Debug.Log(importedAsset + "を削除しました"); } } }
  • 40. MyAssetPostprocessor.csを手に入れる 今回作成したMyAssetPostprocessorは Gistで公開しているので参考にしてください 1. 下記のサイトからMyAssetPostprocessor.csを取得する https://gist.github.com/baba-s/9426854 2. MyAssetPostprocessor.csを UnityプロジェクトのEditorフォルダに追加する
  • 41. MenuItemで ソースコードを自動生成する
  • 42. MenuItemを使うと… Unityエディタに独自の機能を追加できます • すべてのシーンのオブジェクトから 不要なコンポーネントを削除する機能を追加したり… • 選択中のゲームオブジェクトのパラメータを 一括で設定する機能を追加したり…
  • 43. 独自のMenuItemを作成してみる ソースコードを自動生成する MenuItemを作成してみましょう
  • 44. using UnityEditor; public static class MyClassCreator { // Unityエディタのメニューに // ソースコード自動生成用のコマンドを追加します [MenuItem("Tools/Create My Class")] private static void Create() { } } 1.MenuItemが適用された静的関数を作成
  • 45. // ソースコードを表す文字列を作成します var builder = new System.Text.StringBuilder(); builder.AppendLine("public class MyClass"); builder.AppendLine("{"); builder.AppendLine("}"); 2.StringBuilderで文字列を作成
  • 46. // 新しいファイルを作成して // ソースコードを表す文字列を書き込みます System.IO.File.WriteAllText( "Assets/MyClass.cs", builder.ToString(), System.Text.Encoding.UTF8); 3.File.WriteAllTextでファイルを作成
  • 47. // Unityのアセットデータベースをリフレッシュします AssetDatabase.Refresh( ImportAssetOptions.ImportRecursive); 4.AssetDatabase.Refreshを実行
  • 48. 5.用意したUnityエディタのコマンドを実行 public class MyClass { }
  • 49. MyClassCreator.csを手に入れる 今回作成したMyClassCreatorは Gistで公開しているので参考にしてください 1. 下記のサイトからMyClassCreator.csを取得する https://gist.github.com/baba-s/9446762 2. MyClassCreator.csを UnityプロジェクトのEditorフォルダに追加する
  • 50. ソースコードの自動生成のサンプル MenuItemを使用して データを定数で管理するクラスの 自動生成を行ってみましょう • シーン名を定数で管理するクラスの自動生成 • タグ名を定数で管理するクラスの自動生成 • レイヤー名を定数で管理するクラスの自動生成
  • 51. シーン名を定数で管理するクラスの生成
  • 52. シーン名の一覧を取得する方法 EditorBuildSettings.scenesを使用すると シーン名の一覧を取得できます foreach (var n in EditorBuildSettings.scenes) { Debug.Log(n); }
  • 53. シーン名を定数で管理するクラスの生成 1. 下記のサイトからSceneNameCreator.csを取得する https://gist.github.com/baba-s/9286120 2. SceneNameCreator.csをEditorフォルダに追加する 3. Unityエディタの「Tools>Create>Scene Name」を実行する 4. SceneName.csが作成される
  • 54. シーン名を定数で管理するクラスの生成 /// <summary> /// シーン名を定数で管理するクラス /// </summary> public static class SceneName { public const string Title = "Title"; public const string MainMenu = "MainMenu"; }
  • 55. シーン名を定数で管理するクラスの利用 // タイトル画面に遷移します Application.LoadLevel(SceneName.Title); // タイトル画面に遷移します Application.LoadLevel("Title");
  • 56. タグ名を定数で管理するクラスの生成
  • 57. タグ名の一覧を取得する方法 InternalEditorUtility.tagsを使用すると タグ名の一覧を取得できます foreach (var n in InternalEditorUtility.tags) { Debug.Log(n); }
  • 58. タグ名を定数で管理するクラスの生成 1. 下記のサイトからTagNameCreator.csを取得する https://gist.github.com/baba-s/9287103 2. TagNameCreator.csをEditorフォルダに追加する 3. Unityエディタの「Tools>Create>Tag Name」を実行する 4. TagName.csが作成される
  • 59. タグ名を定数で管理するクラスの生成 /// <summary> /// タグ名を定数で管理するクラス /// </summary> public static class TagName { public const string Untagged = "Untagged"; public const string Respawn = "Respawn"; public const string Finish = "Finish"; public const string EditorOnly = "EditorOnly"; public const string MainCamera = "MainCamera"; public const string Player = "Player"; public const string GameController = "GameController"; public const string Character = "Character"; }
  • 60. タグ名を定数で管理するクラスの利用 // ゲームオブジェクトがキャラクターかどうか if (gameObject.CompareTag(TagName.Character)) { // ... } // ゲームオブジェクトがキャラクターかどうか if (gameObject.CompareTag("Character")) { // ... }
  • 61. レイヤー名を定数で管理するクラスの生成
  • 62. レイヤー名の一覧を取得する方法 InternalEditorUtility.layersを使用すると レイヤー名の一覧を取得できます foreach (var n in InternalEditorUtility.layers) { Debug.Log(n); }
  • 63. レイヤー名を定数で管理するクラスの生成 1. 下記のサイトからLayerNameCreator.csを取得する https://gist.github.com/baba-s/9286212 2. LayerNameCreator.csをEditorフォルダに追加する 3. Unityエディタの「Tools>Create>Layer Name」を実行する 4. LayerName.csが作成される
  • 64. レイヤー名を定数で管理するクラスの生成 /// <summary> /// レイヤー名を定数で管理するクラス /// </summary> public static class LayerName { public const int Default = 0; public const int TransparentFX = 1; public const int IgnoreRaycast = 2; public const int Water = 4; public const int Character = 8; public const int DefaultMask = 1; public const int TransparentFXMask = 2; public const int IgnoreRaycastMask = 4; public const int WaterMask = 16; public const int CharacterMask = 256; }
  • 65. レイヤー名を定数で管理するクラスの利用 // ゲームオブジェクトのレイヤーを変更します gameObject.layer = LayerName.Character; // ゲームオブジェクトのレイヤーを変更します gameObject.layer = 8;
  • 66. MenuItemまとめ MenuItemを使用すると Unity APIから取得したデータをもとに ソースコードの自動生成を行うこともできます シーン名やタグ名を定数で管理するクラスを 自動生成できるようにしておくことで タイプセーフなゲーム開発を行うことが可能です
  • 67. ありがとうございました

×