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

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

ただいまの
回答率

89.55%

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,516

Fujisaki_prpr

score 19

 やりたいこと 

とあるデータをScriptableObjectで用意し、それをセットすることを考え、
エディタ拡張を用い、プルダウンメニューで選択し、読み込むことができるのではないかと考えました。

 現時点でできていること

以下のコードで右クリックから新しいデータを作成、Special型にフィールドにSetSpecialPropertyを追加すると、その時点で生成されているデータのリストをプルダウン表示するところまでできています。
イメージ説明
以下のようになっているところから、プルダウンで
イメージ説明
Poisonを選ぶと
イメージ説明
以下のようになります
イメージ説明
しかし、表示が変わっているだけで、Special型には何も代入されていません。

 目標

質問タイトルにもある通り、任意のスクリプタブルオブジェクトをプロパティドロワーなどを用いて設定したいのです。

 環境

Unity 2017.2.0f3

//使用例
    [SerializeField,SetSpecialAttribute]
        private SetSpecialAttribute special; //値がセットされない
//プルダウンで選択し、読み込ませたいデータ
using UnityEngine;
using System.Collections;
using TowerDefClass;
using UnityEditor;

[CreateAssetMenu( menuName = "Data/Create SpecialData", fileName = "SpecialData" ),System.Serializable]
public class Special : ScriptableObject{
    public float hoge;
}
//Property Drawer : プルダウンメニュー表示
using UnityEngine;
using UnityEditor;
using System.IO;

[CustomPropertyDrawer (typeof(SetSpecialAttribute))]
public class SpecialDrawer : PropertyDrawer
{
    string datapath = "Assets/Resources/Data/SpecialData";

    public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
    {
        property.serializedObject.Update ();
        label = EditorGUI.BeginProperty(position, label, property);
        SetSpecialAttribute specialAttribute = (SetSpecialAttribute)attribute;
        int index   = GetElementIndex( label );
        var paths = Directory.GetFiles (datapath, "*.asset");
        string[] names = new string[paths.Length];
        for (int i = 0; i < paths.Length; ++i) {
            names [i] = Path.GetFileNameWithoutExtension (paths [i]);
        }
        position.height = 16f;
        int size = EditorGUI.IntField(position,"size",specialAttribute.size);
        position.y += 18f;
        specialAttribute.size = size;
        if(specialAttribute.special.Length < size){
            specialAttribute.special = new Special[size];
            specialAttribute.idx = new int[size];
        }
        // 文字列のindexを取得する
        // EditorGUI.Popupの結果を index として使用し文字列更新する

        int indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 1;
        for(int i = 0; i < size; ++i) {
            int idx = EditorGUI.Popup (position, label.text, specialAttribute.idx[i], names);
            position.y += 18f;
            specialAttribute.idx[i] = idx;
            var special = AssetDatabase.LoadAssetAtPath<Special> (paths [idx]) as Special;
            specialAttribute.special[i] = special;
        }
        EditorGUI.indentLevel = indent;
        EditorGUI.EndProperty();
        property.serializedObject.ApplyModifiedProperties();
        return;
    }
    public override float GetPropertyHeight (SerializedProperty property, GUIContent label) {
        SetSpecialAttribute specialAttribute = (SetSpecialAttribute)attribute;
        return (16f + 18f * specialAttribute.size) ;
    }
    //http://www.urablog.xyz/entry/2017/02/12/165706 より
    private int GetElementIndex( GUIContent i_label )
    {
        string countText    = i_label.text.Replace( "Element ", "" );
        int index           = 0;

        if( int.TryParse( countText, out index ) )
        {
            return index;
        }

        return -1;
    }
}
//Property Attribute : 
using UnityEngine;
using UnityEditor;
using System.IO;

[System.Serializable]
public class SetSpecialAttribute : PropertyAttribute
{
    public int[] idx;
    public int size;
    public Special[] special;

    public SetSpecialAttribute ()
    {
        //適当なサイズを指定するしかない?
        idx = new int[10];
        special = new Special[10];
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

check解決した方法

0

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

[SerializeField]
private List<Special> special;
//プルダウンで選択し、読み込ませたいデータ
using UnityEngine;
using System.Collections;
using TowerDefClass;
using UnityEditor;

[CreateAssetMenu( menuName = "Data/Create SpecialData", fileName = "SpecialData" ),System.Serializable]
public class Special : ScriptableObject{
    public float hoge;
}
public override void OnInspectorGUI (){ //の中に以下を追加
 isSpecialFold = EditorGUILayout.Foldout(isSpecialFold,"sp");
 if(isSpecialFold){
  SerializedProperty sp = serializedObject.FindProperty ("special");
  EditorGUILayout.LabelField("Special");
  for(int i = 0; i < count;++i){
   int idx = EditorGUILayout.Popup(paths.IndexOf(specialPaths[i]),names);
   if(idx < 0) idx = 0;
   specialPaths[i] = paths[idx];
   special[i] = AssetDatabase.LoadAssetAtPath<Special>(paths[idx]) as Special;
  }
}

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/02/23 19:16

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

    キャンセル

  • 2018/03/04 18:59

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

    キャンセル

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

  • ただいまの回答率 89.55%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる