読者です 読者をやめる 読者になる 読者になる

(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

拡張したインスペクタの項目を同時に編集【Unity】【エディタ拡張】


このエントリーをはてなブックマークに追加

はじめに

以下の様にInspectorに表示される内容は独自に拡張する事ができます。


f:id:kan_kikuchi:20141221152840p:plain


詳しくは以下の記事を参照の事。



しかし、このままでは複数のオブジェクトを選択した時に

以下の様にnot supportedと表示され、編集できません。


f:id:kan_kikuchi:20150429203322p:plain


今回はこれの対処法をご紹介!


CanEditMultipleObjects

複数選択出来るようにする方法は、

拡張を行うクラスに[CanEditMultipleObjects]と記述するだけです。



例えば、Monsterクラスの拡張を行うMonsterEditorクラスがあった場合は

以下のようにすると、複数選択する事が可能になります。

using UnityEngine;
using System.Collections;
using UnityEditor;

//モンスタークラスを拡張
[CustomEditor (typeof(Monster))]

//複数選択有効
[CanEditMultipleObjects]

public class MonsterEditor : Editor
{
}


ただこの状態だと複数選択が可能になっただけで、

編集した値が複数のオブジェクトに反映はされません


例えば、MonsterクラスにHP,MP,Powerという変数があり、

それを以下のMonsterEditorで拡張した場合を考えます。

using UnityEngine;
using System.Collections;
using UnityEditor;

//モンスタークラスを拡張
[CustomEditor (typeof(Monster))]

//複数選択有効
[CanEditMultipleObjects]

public class MonsterEditor : Editor
{
	Monster mainMonster = target as Monster;

	//注記
	EditorGUILayout.HelpBox("ステータスは0以下に設定できません。", MessageType.Info, true );

	//各ステータス
	mainMonster.HP    = Mathf.Max(1, EditorGUILayout.FloatField ("体力", mainMonster.HP));
	mainMonster.MP    = Mathf.Max(1, EditorGUILayout.FloatField ("マジックポイント", mainMonster.MP));
	mainMonster.Power = Mathf.Max(1, EditorGUILayout.FloatField ("パワー!", mainMonster.Power));

	EditorUtility.SetDirty(target);
}


この状態でMonster1とMonster2を選択し、インスペクター上でHPを100と設定しても、


f:id:kan_kikuchi:20150429204319p:plain


Monster2のHPは100になったけど、Monster1のHPは1のまま!

なんて事になります。


同時編集

選択した全てのオブジェクトに対して変更を行うように改良したコードが以下になります。

using UnityEngine;
using System.Collections;
using UnityEditor;

//モンスタークラスを拡張
[CustomEditor (typeof(Monster))]

//複数選択有効
[CanEditMultipleObjects]

public class MonsterEditor : Editor
{
	//インスペクターを拡張
	public override void OnInspectorGUI() {

		Monster mainMonster = target as Monster;

		//注記
		EditorGUILayout.HelpBox("ステータスは0以下に設定できません。", MessageType.Info, true );

		//各ステータス
		mainMonster.HP    = Mathf.Max(1, EditorGUILayout.FloatField ("体力", mainMonster.HP));
		mainMonster.MP    = Mathf.Max(1, EditorGUILayout.FloatField ("マジックポイント", mainMonster.MP));
		mainMonster.Power = Mathf.Max(1, EditorGUILayout.FloatField ("パワー!", mainMonster.Power));

		EditorUtility.SetDirty(target);

		//選択されている全てものについて処理
		foreach(Object monsterObject in targets){

			Monster submonster = monsterObject as Monster;

			submonster.HP    = mainMonster.HP;
			submonster.MP    = mainMonster.MP;
			submonster.Power = mainMonster.Power;

			EditorUtility.SetDirty(monsterObject);
		}

	}

}


変更が反映されるオブジェクトであるtargetの設定をした後、

選択されている全てのオブジェクトをtargetsで取得し、

targetの設定値を全てのオブジェクトに反映するようにしています。


ただし、このやり方をすると
複数選択した時点で、全てのオブジェクトの設定値が同じになるので、注意が必要です。