質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

3818閲覧

UnityのProperty Drawerでの任意のScriptableObjectを代入したい

Fujisaki_prpr

総合スコア21

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2018/02/22 11:51

編集2018/03/07 03:09

やりたいこと

とあるデータを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}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

結局当初のようにPropertyDrawerを使うことは諦め、専用のEditor拡張で済ませました。

C#

1[SerializeField] 2private List<Special> special; 3

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#

1public override void OnInspectorGUI (){ //の中に以下を追加 2 isSpecialFold = EditorGUILayout.Foldout(isSpecialFold,"sp"); 3 if(isSpecialFold){ 4 SerializedProperty sp = serializedObject.FindProperty ("special"); 5 EditorGUILayout.LabelField("Special"); 6 for(int i = 0; i < count;++i){ 7 int idx = EditorGUILayout.Popup(paths.IndexOf(specialPaths[i]),names); 8 if(idx < 0) idx = 0; 9 specialPaths[i] = paths[idx]; 10 special[i] = AssetDatabase.LoadAssetAtPath<Special>(paths[idx]) as Special; 11 } 12}

断片的なコードを切り取っているため、このままではうまく動かないのですが、脳内補完していただけると幸いです。

結局のところやりたかった
プルダウンでのスクリプタブルオブジェクト読み込みはこの方法で出来たのでこれで解決にします。

投稿2018/03/07 06:44

Fujisaki_prpr

総合スコア21

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

解決出来るか未検証ですが、
第5章 SerializedObject について - エディター拡張入門
このサイトの「5.2 SerializedObject の使い方 > 最新のデータを取得、更新」にあるように
serializedObject.Update ();serializedObject.ApplyModifiedProperties ();を使ってみてはいかがでしょうか。

投稿2018/02/23 00:57

sakura_hana

総合スコア11425

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Fujisaki_prpr

2018/02/23 10:16

ちょっと、今別の方面で立て込んでいて試すことができません 時間を見つけ次第試して見ます、回答ありがとうございました
Fujisaki_prpr

2018/03/04 09:59

ここ2日ぐらい格闘していましたが、上記の方法ではダメだったみたいです もしかしてあまり複雑なことはプロパティドロワーではなくエディター拡張で専用のエディターを作るべきなのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問