【Unity】動作確認を簡単にするエディタ拡張「EssentialEditor」の紹介

# Unityにおける動作確認
<!-- 動作テストの面倒くささについて共感してもらう -->
僕たちプログラマはコーディングを終えた後、当然動作確認を行います。
1つのプロダクトを完成させるまでに行う **動作確認はかなりの回数** になるはずです。
その動作確認は難しくはなくとも少し面倒なことが多々あります。
まずは、Unityを用いた開発において僕が良く行ってきた動作確認を見てみます。

単純に関数に引数を渡して、戻り値が期待通りかを確かめたい場合は↓みたいな感じでした。
引数に渡す値を本来は動的に取得することが想定される場合には、代わりにシリアライズフィールドを用意して、その値を引数に渡してやります。

````````````````c#
public class Character : UnityEngine.MonoBehaviour
{
	/// <summary>
	/// キャラクターの視界[m]
	/// </summary>
	[UnityEngine.SerializeField]
	private float sight = 10;

	public UnityEngine.Vector3 debugPosition;

	private void Start()
	{
		UnityEngine.Debug.Log(this.IsInSight(this.debugPosition));
	}

	/// <summary>
	/// 座標は視界内か
	/// </summary>
	/// <param name="position">判定したい座標</param>
	/// <returns><c>true</c>視界内</returns>
	private bool IsInSight(UnityEngine.Vector3 position)
	{
		return (position - this.transform.position).magnitude < this.sight;
	}
}

````````````````
↑のように関数をとりあえず呼ばれば良い場合はまだいいです。
任意のタイミングで関数を呼びたかったり何かしらの計算をした後の値を見たかったりする場合はもう少し面倒です。
そのような時僕は、↓のようにして、動作確認をしていました。

````````````````c#
public class Enemy : UnityEngine.MonoBehaviour
{
	/// <summary>
	/// 基本攻撃力
	/// </summary>
	[UnityEngine.SerializeField]
	private int baseAttack;

	/// <summary>
	/// 攻撃力
	/// </summary>
	[UnityEngine.SerializeField]
	private int attack;

	/// <summary>
	/// 攻撃力を上昇させるバフの効果値[割合]
	/// </summary>
	/// <remarks>実行時に書き換わることを想定</remarks>
	private float attackBuffRate = 1f;

	/// <summary>
	/// 弾のプレハブ
	/// </summary>
	[UnityEngine.SerializeField]
	private UnityEngine.GameObject bulletPrefab;

	/// <summary>
	/// 攻撃力
	/// </summary>
	public int Attack => (int)(this.baseAttack * this.attackBuffRate);

	private void Update()
	{
		// プロパティの値をインスペクタから見るにはSerializeFieldにも反映しなきゃいけない
		this.attack = this.Attack;

		// 射撃テスト
		if (UnityEngine.Input.GetMouseButtonDown(0))
		{
			this.Shot();
		}
	}

	/// <summary>
	/// 射撃する
	/// </summary>
	private void Shot()
	{
		UnityEngine.GameObject.Instantiate(this.bulletPrefab);
	}
}
````````````````
`Update()`の中から値を反映させたり入力を取って関数を呼んだり...。
どれも大した作業じゃないですが、若干面倒くさいです。
そして、動作確認は何度も行いますから、若干でも嫌なものです。
もちろん、エディタ拡張やインスペクタ拡張を利用する手もありますが、1度動作確認に使うだけの場合は効率が良くないこともあります。
そんな面倒を減らしてくれるアセットが **EssentialEditor** です。

# EssentialEditorの紹介
https://github.com/zsaladin/EssentialEditor
EssentialEditorはKim Daeheeさんが作られた2種類の属性が使えるようになるアセットです。
MITライセンスなので、無料ですし、ライセンス的にも使いやすいです。

## 何ができるのか
2つの属性(Attribute)を使うことで次の3つができるようになります。

* プロパティの値をインスペクタに表示する
* プロパティの値をインスペクタから編集する(プロパティに`set`がある場合のみ)
* メソッドをインスペクタから任意の引数とタイミングで実行し、戻り値をコンソールに表示する

属性をつけるだけなので、デバッグ用のコードで本番用のコードが汚れることもありませんし、エディタからしか意味をなさないため、消し忘れによる事故も防げます。

## 使い方
まずは[Github](https://github.com/zsaladin/EssentialEditor)のページからEssentialEditorをダウンロードしてきます。
UnityPackageも用意されています。

まずは、一番最初に示した座標がキャラクターの視界内にあるかを判定する関数にEssentialEditorの`ExposeMethod`属性を使った例です。

````````````````c#
public class Enemy : UnityEngine.MonoBehaviour
{
	/// <summary>
	/// 基本攻撃力
	/// </summary>
	[UnityEngine.SerializeField]
	private int baseAttack;

	/// <summary>
	/// 弾のプレハブ
	/// </summary>
	[UnityEngine.SerializeField]
	private UnityEngine.GameObject bulletPrefab;

	/// <summary>
	/// 攻撃力を上昇させるバフの効果値[割合]
	/// </summary>
	[EssentialEditor.ExposeProperty]
	private float AttackBuffRate
	{
		get;
		set;
	} = 1f;

	/// <summary>
	/// 攻撃力
	/// </summary>
	[EssentialEditor.ExposeProperty]
	public int Attack => (int)(this.baseAttack * this.AttackBuffRate);

	/// <summary>
	/// 射撃する
	/// </summary>
	[EssentialEditor.ExposeMethod]
	private void Shot()
	{
		UnityEngine.GameObject.Instantiate(this.bulletPrefab);
	}
}
````````````````
![例2.png](https://qiita-image-store.s3.amazonaws.com/0/67536/85e86042-a544-416c-b920-86e03c6205a8.png)

`ExposeProperty`属性はプロパティにつけることで、その値をインスペクタに表示することができます。
また、そのプロパティに`set`があれば、その値を編集することもできます。
ただし、`SerializeField`属性とは違い、保存はできません。
保存したい場合は、`set`内でシリアライズされる変数に格納しておく必要があります。

## ScriptableObjectにも使えるようにするには
EssentialEditorの属性は`MonoBehaviour`にしか使えないようになっています。
ですが、少し書き換えることで`UnityEngine.Object`の派生クラスであれば、全てのクラスに使えるようにできます。
その方法は↓の画像の通りに1行書き換えるだけです。

![ScriptableObjectにも使えるように.png](https://qiita-image-store.s3.amazonaws.com/0/67536/a26fdc0b-31cf-621b-3f60-0fe370fee021.png)

# 出来そうで出来ないこと

* `UnityEngine.Object`の派生クラス以外で使う
* `ExposeProperty`属性の値を保存する

`UnityEngine.Object`の派生クラス以外で使えるようにできないか、僕も試行錯誤してみましたが、駄目でした。
何か良い方法がありましたら、コメントなどで教えていただけると嬉しいです。