やりたいこと
とあるデータをScriptableObjectで用意し、それをセットすることを考え、
エディタ拡張を用い、プルダウンメニューで選択し、読み込むことができるのではないかと考えました。
現時点でできていること
以下のコードで右クリックから新しいデータを作成、Special型にフィールドにSetSpecialPropertyを追加すると、その時点で生成されているデータのリストをプルダウン表示するところまでできています。
以下のようになっているところから、プルダウンで
Poisonを選ぶと
以下のようになります
しかし、表示が変わっているだけで、Special型には何も代入されていません。
目標
質問タイトルにもある通り、任意のスクリプタブルオブジェクトをプロパティドロワーなどを用いて設定したいのです。
環境
Unity 2017.2.0f3
C#
1//使用例 2 [SerializeField,SetSpecialAttribute] 3 private SetSpecialAttribute special; //値がセットされない 4
C#
1//プルダウンで選択し、読み込ませたいデータ 2using UnityEngine; 3using System.Collections; 4using TowerDefClass; 5using UnityEditor; 6 7[CreateAssetMenu( menuName = "Data/Create SpecialData", fileName = "SpecialData" ),System.Serializable] 8public class Special : ScriptableObject{ 9 public float hoge; 10}
C#
1//Property Drawer : プルダウンメニュー表示 2using UnityEngine; 3using UnityEditor; 4using System.IO; 5 6[CustomPropertyDrawer (typeof(SetSpecialAttribute))] 7public class SpecialDrawer : PropertyDrawer 8{ 9 string datapath = "Assets/Resources/Data/SpecialData"; 10 11 public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) 12 { 13 property.serializedObject.Update (); 14 label = EditorGUI.BeginProperty(position, label, property); 15 SetSpecialAttribute specialAttribute = (SetSpecialAttribute)attribute; 16 int index = GetElementIndex( label ); 17 var paths = Directory.GetFiles (datapath, "*.asset"); 18 string[] names = new string[paths.Length]; 19 for (int i = 0; i < paths.Length; ++i) { 20 names [i] = Path.GetFileNameWithoutExtension (paths [i]); 21 } 22 position.height = 16f; 23 int size = EditorGUI.IntField(position,"size",specialAttribute.size); 24 position.y += 18f; 25 specialAttribute.size = size; 26 if(specialAttribute.special.Length < size){ 27 specialAttribute.special = new Special[size]; 28 specialAttribute.idx = new int[size]; 29 } 30 // 文字列のindexを取得する 31 // EditorGUI.Popupの結果を index として使用し文字列更新する 32 33 int indent = EditorGUI.indentLevel; 34 EditorGUI.indentLevel = 1; 35 for(int i = 0; i < size; ++i) { 36 int idx = EditorGUI.Popup (position, label.text, specialAttribute.idx[i], names); 37 position.y += 18f; 38 specialAttribute.idx[i] = idx; 39 var special = AssetDatabase.LoadAssetAtPath<Special> (paths [idx]) as Special; 40 specialAttribute.special[i] = special; 41 } 42 EditorGUI.indentLevel = indent; 43 EditorGUI.EndProperty(); 44 property.serializedObject.ApplyModifiedProperties(); 45 return; 46 } 47 public override float GetPropertyHeight (SerializedProperty property, GUIContent label) { 48 SetSpecialAttribute specialAttribute = (SetSpecialAttribute)attribute; 49 return (16f + 18f * specialAttribute.size) ; 50 } 51 //http://www.urablog.xyz/entry/2017/02/12/165706 より 52 private int GetElementIndex( GUIContent i_label ) 53 { 54 string countText = i_label.text.Replace( "Element ", "" ); 55 int index = 0; 56 57 if( int.TryParse( countText, out index ) ) 58 { 59 return index; 60 } 61 62 return -1; 63 } 64}
C#
1//Property Attribute : 2using UnityEngine; 3using UnityEditor; 4using System.IO; 5 6[System.Serializable] 7public class SetSpecialAttribute : PropertyAttribute 8{ 9 public int[] idx; 10 public int size; 11 public Special[] special; 12 13 public SetSpecialAttribute () 14 { 15 //適当なサイズを指定するしかない? 16 idx = new int[10]; 17 special = new Special[10]; 18 } 19}
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。