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

67
知って得する Unity エディタ拡張編 株式会社ハ・ン・ド プログラマ 馬場翔太 http://baba-s.hatenablog.com/

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

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

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

株式会社ハ・ン・ド

プログラマ

馬場翔太

http://baba-s.hatenablog.com/

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

スライド内容

1. PropertyDrawerでUnityエディタを拡張する

2. AssetPostprocessorでアセットを監視する

3. MenuItemでソースコードを自動生成する

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

PropertyDrawerで

Unityエディタを拡張する

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

エディタ拡張は二通りの方法で行えます

• CustomEditorを使用する

スクリプト単位によるエディタ拡張

• PropertyDrawerを使用する

プロパティ単位によるエディタ拡張

このスライドで紹介する機能

使いまわしやすい!

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

標準で用意されているPropertyDrawer

• RangeAttribute

• MultilineAttribute

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

RangeAttributeを使うと…

値の入力範囲を制限できるようになります

using UnityEngine;

public class Character : MonoBehaviour

{

[Range(1, 100)] public int Level = 1;

}

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

MultilineAttributeを使うと…

文字列を複数行で入力できるようになります

using UnityEngine;

public class Character : MonoBehaviour

{

[Multiline(3)] public string Comment;

}

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

独自のPropertyDrawerを作成して使用する

RangeAttributeやMultilineAttributeのような

PropertyDrawerは自分で作成可能です

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

独自のPropertyDrawerを作成して使用する

プロパティ名を変更できる

PropertyDrawerを作成してみましょう

using UnityEngine;

public class Character : MonoBehaviour

{

[MyProperty("名前")] public string Name;

}

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

using UnityEngine;

public class MyPropertyAttribute : PropertyAttribute

{

public string Label;

public MyPropertyAttribute(string label)

{

Label = label;

}

}

1.PropertyAttributeを継承したクラス作成

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

using UnityEditor;

using UnityEngine;

[CustomPropertyDrawer(typeof(MyPropertyAttribute))]

public class MyPropertyDrawer : PropertyDrawer

{

}

2.PropertyDrawerを継承したクラスを作成

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

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関数をオーバーライドして実装

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

using UnityEngine;

public class Character : MonoBehaviour

{

[MyProperty("名前")] public string Name;

}

4.作成したPropertyDrawerを使用する

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

PropertyDrawer作成時の注意

PropertyDrawerを継承したクラスは

Editorフォルダに保存するか

#if UNITY_EDITOR ~ #endifで囲まないと

ビルド時にエラーになるので気をつけてください

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

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フォルダに追加する

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

using UnityEngine;

public class Character : MonoBehaviour

{

public Vector3 Position;

}

Vector2やVector3の入力を楽にしたい

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

CompactAttribute.csを手に入れる

1. 下記のサイトからCompactAttribute.csを取得する

https://github.com/anchan828/property-drawer-collection

2. CompactAttribute.csをUnityプロジェクトに追加する

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

using UnityEngine;

public class Character : MonoBehaviour

{

[Compact] public Vector3 Position;

}

CompactAttributeを使用する

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

using UnityEngine;

public class Character : MonoBehaviour

{

public enum JobType

{

SOLDIER,

SORCERER,

}

public JobType Job;

}

列挙型の表示名を変えたい

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

EnumLabelAttribute.csを手に入れる

1. 下記のサイトからEnumLabelAttribute.csを取得する

https://github.com/anchan828/property-drawer-collection

2. EnumLabelAttribute.csをUnityプロジェクトに追加する

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

using UnityEngine;

public class Character : MonoBehaviour

{

public enum JobType

{

[EnumLabel("王国兵士")] SOLDIER,

[EnumLabel("魔法使い")] SORCERER,

}

[EnumLabel("ジョブ")] public JobType Job;

}

EnumLabelAttributeを使用する

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

using UnityEngine;

public class Character : MonoBehaviour

{

public string Job;

public int Money;

}

入力できる値をポップアップで制限したい

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

PopupAttribute.csを手に入れる

1. 下記のサイトからPopupAttribute.csを取得する

https://github.com/anchan828/property-drawer-collection

2. PopupAttribute.csをUnityプロジェクトに追加する

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

using UnityEngine;

public class Character : MonoBehaviour

{

[Popup("王国兵士", "魔法使い")]

public string Job;

[Popup(1, 5, 10, 50, 100, 500)]

public int Money;

}

PopupAttributeを使用する

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

using UnityEngine;

public class LoadSceneButton : MonoBehaviour

{

public string SceneName;

}

ポップアップでシーン名を設定したい

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

SceneNameAttribute.csを手に入れる

1. 下記のサイトからSceneNameAttribute.csを取得する

https://github.com/anchan828/property-drawer-collection

2. SceneNameAttribute.csをUnityプロジェクトに追加する

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

using UnityEngine;

public class LoadSceneButton : MonoBehaviour

{

[SceneName] public string SceneName;

}

SceneNameAttributeを使用する

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

using UnityEngine;

public class Config : MonoBehaviour

{

// IPアドレス

public string ServerAddress;

}

入力できる値を正規表現で制限したい

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

RegexAttribute.csを手に入れる

1. 下記のサイトからRegexAttribute.csを取得する

https://gist.github.com/baba-s/9430471

2. RegexAttribute.csをUnityプロジェクトに追加する

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

using UnityEngine;

public class Config : MonoBehaviour

{

// IPアドレス

[Regex(@"^(?:¥d{1,3}¥.){3}¥d{1,3}$", "無効なIPアドレスです!例:'127.0.0.1'")]

public string ServerAddress;

}

RegexAttributeを使用する

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

PropertyDrawerまとめ

PropertyDrawerを使用すると

スクリプト単位ではなく

プロパティ単位でエディタ拡張が可能なので

多くのスクリプトやプロジェクトで使いまわせます

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

AssetPostprocessorで

アセットを監視する

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

AssetPostprocessorを使うと…

• 特定のファイルのみ

Unityプロジェクトに追加不能にできる

• テクスチャやAudioClipの設定を

Unityプロジェクトに追加された時に変更できる

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

独自のAssetPostprocessorを作成してみる

全角文字が含まれたファイルが

プロジェクトに追加されたら自動で削除する

AssetPostprocessorを作成してみましょう

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

1.AssetPostprocessorのサブクラスを作成

using UnityEditor;

using UnityEngine;

public class MyAssetPostprocessor : AssetPostprocessor

{

}

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

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

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

3. OnPostprocessAllAssets関数を定義

// すべてのアセットのインポートが終了した際に呼び出されます

// importedAssets :インポートされたアセットのパス

// deletedAssets :削除されたアセットのパス

// movedAssets :移動したアセットの移動後のパス

// movedFromPath:移動したアセットの移動前のパス

private static void OnPostprocessAllAssets(

string[] importedAssets,

string[] deletedAssets,

string[] movedAssets,

string[] movedFromPath)

{

}

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

4.AssetDatabase.DeleteAssetを利用

foreach (var importedAsset in importedAssets)

{

if (!IsOneByteStr(importedAsset))

{

// 指定されたパスに存在するアセットを削除します

if (AssetDatabase.DeleteAsset(importedAsset))

{

Debug.Log(importedAsset + "を削除しました");

}

}

}

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

MyAssetPostprocessor.csを手に入れる

今回作成したMyAssetPostprocessorは

Gistで公開しているので参考にしてください

1. 下記のサイトからMyAssetPostprocessor.csを取得する

https://gist.github.com/baba-s/9426854

2. MyAssetPostprocessor.csを

UnityプロジェクトのEditorフォルダに追加する

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

MenuItemで

ソースコードを自動生成する

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

MenuItemを使うと…

Unityエディタに独自の機能を追加できます

• すべてのシーンのオブジェクトから

不要なコンポーネントを削除する機能を追加したり…

• 選択中のゲームオブジェクトのパラメータを

一括で設定する機能を追加したり…

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

独自のMenuItemを作成してみる

ソースコードを自動生成する

MenuItemを作成してみましょう

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

using UnityEditor;

public static class MyClassCreator

{

// Unityエディタのメニューに

// ソースコード自動生成用のコマンドを追加します

[MenuItem("Tools/Create My Class")]

private static void Create()

{

}

}

1.MenuItemが適用された静的関数を作成

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

// ソースコードを表す文字列を作成します

var builder = new System.Text.StringBuilder();

builder.AppendLine("public class MyClass");

builder.AppendLine("{");

builder.AppendLine("}");

2.StringBuilderで文字列を作成

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

// 新しいファイルを作成して

// ソースコードを表す文字列を書き込みます

System.IO.File.WriteAllText(

"Assets/MyClass.cs",

builder.ToString(),

System.Text.Encoding.UTF8);

3.File.WriteAllTextでファイルを作成

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

// Unityのアセットデータベースをリフレッシュします

AssetDatabase.Refresh(

ImportAssetOptions.ImportRecursive);

4.AssetDatabase.Refreshを実行

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

5.用意したUnityエディタのコマンドを実行

public class MyClass

{

}

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

MyClassCreator.csを手に入れる

今回作成したMyClassCreatorは

Gistで公開しているので参考にしてください

1. 下記のサイトからMyClassCreator.csを取得する

https://gist.github.com/baba-s/9446762

2. MyClassCreator.csを

UnityプロジェクトのEditorフォルダに追加する

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

ソースコードの自動生成のサンプル

MenuItemを使用して

データを定数で管理するクラスの

自動生成を行ってみましょう

• シーン名を定数で管理するクラスの自動生成

• タグ名を定数で管理するクラスの自動生成

• レイヤー名を定数で管理するクラスの自動生成

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

シーン名を定数で管理するクラスの生成

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

シーン名の一覧を取得する方法

EditorBuildSettings.scenesを使用すると

シーン名の一覧を取得できます

foreach (var n in EditorBuildSettings.scenes)

{

Debug.Log(n);

}

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

シーン名を定数で管理するクラスの生成

1. 下記のサイトからSceneNameCreator.csを取得する

https://gist.github.com/baba-s/9286120

2. SceneNameCreator.csをEditorフォルダに追加する

3. Unityエディタの「Tools>Create>Scene Name」を実行する

4. SceneName.csが作成される

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

シーン名を定数で管理するクラスの生成

/// <summary>

/// シーン名を定数で管理するクラス

/// </summary>

public static class SceneName

{

public const string Title = "Title";

public const string MainMenu = "MainMenu";

}

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

シーン名を定数で管理するクラスの利用

// タイトル画面に遷移します

Application.LoadLevel(SceneName.Title);

// タイトル画面に遷移します

Application.LoadLevel("Title");

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

タグ名を定数で管理するクラスの生成

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

タグ名の一覧を取得する方法

InternalEditorUtility.tagsを使用すると

タグ名の一覧を取得できます

foreach (var n in InternalEditorUtility.tags)

{

Debug.Log(n);

}

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

タグ名を定数で管理するクラスの生成

1. 下記のサイトからTagNameCreator.csを取得する

https://gist.github.com/baba-s/9287103

2. TagNameCreator.csをEditorフォルダに追加する

3. Unityエディタの「Tools>Create>Tag Name」を実行する

4. TagName.csが作成される

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

タグ名を定数で管理するクラスの生成

/// <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";

}

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

タグ名を定数で管理するクラスの利用

// ゲームオブジェクトがキャラクターかどうか

if (gameObject.CompareTag(TagName.Character))

{

// ...

}

// ゲームオブジェクトがキャラクターかどうか

if (gameObject.CompareTag("Character"))

{

// ...

}

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

レイヤー名を定数で管理するクラスの生成

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

レイヤー名の一覧を取得する方法

InternalEditorUtility.layersを使用すると

レイヤー名の一覧を取得できます

foreach (var n in InternalEditorUtility.layers)

{

Debug.Log(n);

}

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

レイヤー名を定数で管理するクラスの生成

1. 下記のサイトからLayerNameCreator.csを取得する

https://gist.github.com/baba-s/9286212

2. LayerNameCreator.csをEditorフォルダに追加する

3. Unityエディタの「Tools>Create>Layer Name」を実行する

4. LayerName.csが作成される

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

レイヤー名を定数で管理するクラスの生成

/// <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;

}

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

レイヤー名を定数で管理するクラスの利用

// ゲームオブジェクトのレイヤーを変更します

gameObject.layer = LayerName.Character;

// ゲームオブジェクトのレイヤーを変更します

gameObject.layer = 8;

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

MenuItemまとめ

MenuItemを使用すると

Unity APIから取得したデータをもとに

ソースコードの自動生成を行うこともできます

シーン名やタグ名を定数で管理するクラスを

自動生成できるようにしておくことで

タイプセーフなゲーム開発を行うことが可能です

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

ありがとうございました