Tutti Lab

元シリコンバレー在住のおっさん技術者、モバイルVRアプリ開発に挑戦中

【Unity開発Tips】Unityライブラリに含まれるクラスのエディタ拡張

Unityを使って開発をしていると、例えばuGUIのGUI部品(ボタンなど)に独自拡張を加えたい、という場合が出てきます。この拡張が、例えば見た目等、Inspectorの内容を変更するものだったり、子オブジェクトを追加したり、ということで対応可能であれば、インスペクタ・Heirarchyでの情報更新・追加で済みます。しかし、イベント発生時の挙動を変えたい(ボタンからフォーカスが外れた時に何らかの処理をしたい、等)場合は、本GUI部品を制御するスクリプトを継承したスクリプトを作る必要が出てきます。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class VRKeyInputField : InputField {

	[System.Serializable]
	public class KeyboardTranform {
		public Vector3 keyboardPosition = new Vector3 (0, -1.5f, 0);
		public float keyboardScale = 2;
	}
	public KeyboardTranform keyboardTransform = new KeyboardTranform();

	public override void OnSelect(BaseEventData eventData) {
		base.OnSelect (eventData);
		Board.NotifyActiveInputField (this);
	}
}

現在、以前にご紹介したバーチャルキーボードのパワーアップ版を開発中です。本バージョンでは、バーチャルキーボードでの入力をInputFieldに反映させるようにしています。このバーチャルキーボードを、InputFieldがクリックされた際に表示するようにするために、uGUIのInputFieldクラスを拡張したもの(の抜粋)が、上記のスクリプトです。
f:id:tuti107:20160618051627p:plain
本スクリプトは、InputFieldが選択された際に呼ばれるOnSelect()メソッドをオーバーライドして、InputFieldが選択された際にバーチャルキーボード表示の要求を行っています。また、この表示の要求が行われた際、keyboardTransformに設定された内容に従い、バーチャルキーボードの表示位置や大きさを調整しています。

publicフィールドがInspectorに表示されない

上記KeyboardTransformはSystem.Serializableであり、またkeyboardTransformはpublicフィールドのため、インスペクタに表示されることを期待しますが、これだとkeyboardTransformは表示されません。InputFieldのインスペクタ表示はエディタ拡張によって実現されており、本エディタ拡張を行っているスクリプトInputFieldEditorが、keyboardTransformを表示対象としていないためです(当たり前ですが)。
keyboardTransformをインスペクタ表示させるためには、InputFieldEditorを継承したエディタ拡張を作成する必要があります。

InputFieldEditorのエディタ拡張スクリプト

using UnityEngine;
using UnityEditor;
using System.Collections;

[CustomEditor(typeof(VRKeyInputField))]
public class VRKeyInputFieldInspector : UnityEditor.UI.InputFieldEditor {

	public override void OnInspectorGUI() {

		VRKeyInputField f = (VRKeyInputField)target;
		EditorGUILayout.LabelField ("Virtual Keyboard transform:");

		EditorGUI.BeginChangeCheck ();

		EditorGUI.indentLevel++;

		f.keyboardTransform.keyboardPosition = EditorGUILayout.Vector3Field ("LocalPosition", f.keyboardTransform.keyboardPosition);

		EditorGUILayout.BeginHorizontal ();
		EditorGUILayout.PrefixLabel ("Scale");
		f.keyboardTransform.keyboardScale = EditorGUILayout.FloatField (f.keyboardTransform.keyboardScale);
		EditorGUILayout.EndHorizontal ();

		EditorGUI.indentLevel--;

		EditorGUILayout.Separator ();

		if (EditorGUI.EndChangeCheck ()) {
			EditorUtility.SetDirty (target);
		}

		base.OnInspectorGUI ();
	}
}

上記スクリプトを、ProjectのEditorフォルダ内に配置することで、keyboardTransformがインスペクタに表示されるようになります。
エディタ拡張の詳細については、たくさんの書籍やサイトがあるためそちらを参照頂ければと思いますが、ざっくりと説明すると、

  • [CustomEditor(typeof(***))]にて、指定されたクラス***のインスペクタの表示を拡張する
  • OnInspectorGUI()メソッドにて、インスペクタに具体的にどのように表示されるかを記述する

という感じです。
上記のスクリプトにより、VRKeyInputFieldのインスペクタ表示は下記の通りとなります。
f:id:tuti107:20160618052902p:plain
Interactable以下は、もともとのInputFieldに関するものです。Virtual Keyboard transform:の項目が追加され、keyboardTransformの内容の表示と変更ができるようになっています。例えばscaleを5とすると、上記(デフォルトは2)と比較して、キーボードが大きく表示されております。
f:id:tuti107:20160618053407p:plain

最後に

バーチャルキーボードを開発する上で、ハマってしまったUnityライブラリに含まれるクラスを継承したクラスを作成した際の、インスペクタ表示の問題について、書いてみました。以外と触れられている記事がなく、結構はまってしまったので、備忘録として残しておこうと思いました。