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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

Q&A

解決済

1回答

773閲覧

Unityエディタ拡張で対象クラス以外のクラスを読み込む方法

Citron

総合スコア1

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

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

0グッド

0クリップ

投稿2022/07/05 01:14

Unityのエディタ拡張についての質問です。

Editor拡張初心者です。Unityのバージョンは2021.1.1f1です。

実現したいことは、ScriptableObjectで設定したパラメータのリストを、アタッチしたクラス(CharaController)でプルダウン化して、使いたいパラメータを簡単に指定できるようにすることです。

以下のスクリプトでは、Editorクラス内で、拡張するインスペクタのクラス(CharaController)を指定し処理のためScriptableObjectのクラスを読み込むということができず詰まっています。

Editor拡張では、拡張するクラス(CharaController)以外のクラス(ScriptableObject)の変数を参照するために読み込むことはできるのでしょうか?

ScriptableObject

1using System.Collections.Generic; 2using System.Linq; 3using UnityEngine; 4 5/// <summary> 6/// ScriptableObject 7/// </summary> 8[CreateAssetMenu(fileName = "CharaSettings", menuName = "CharaData/Parameter")] 9public class Testsc : ScriptableObject 10{ 11 [Header("====================Player===================\n")] 12 13 public PlayerDynamicStutas playerDynamicStutas = new PlayerDynamicStutas(); 14 15 public List<PlayerStaticStutas> playerStaticStutas = new List<PlayerStaticStutas>(); 16 17 [Header("====================Chara====================\n")] 18 19 public List<CharaStutas> _stutasList = new List<CharaStutas>(); 20 21 public List<CharaStutas> stutasList => _stutasList; 22 23 24 [SerializeField, HideInInspector] 25 public List<string> stutasNameList = new List<string>(); 26 27 [SerializeField, HideInInspector] 28 public string selectedStutasName; 29 30 [SerializeField, HideInInspector] 31 public int selectedStutasIndex; 32 33 private void OnValidate() 34 { 35 if (stutasList != null) CreateStutasNameList(); 36 } 37 38 /// <summary> 39 /// ステータスの名前リストを作成する 40 /// </summary> 41 private void CreateStutasNameList() 42 { 43 stutasNameList.Clear(); 44 45 foreach (var stutas in stutasList) 46 { 47 if (!stutasNameList.Contains(stutas.name)) stutasNameList.Add(stutas.name); 48 } 49 } 50 51 52 53 54 [System.Serializable] 55 public class PlayerDynamicStutas 56 { 57 public float health; 58 public float hungry; 59 public float stamina; 60 public float speed; 61 } 62 63 [System.Serializable] 64 public class PlayerStaticStutas 65 { 66 public string level; 67 public float power; 68 public float defense; 69 public float flightSpeedScale; 70 } 71 72 73 74 [System.Serializable] 75 public class CharaStutas 76 { 77 public string name; 78 [Header("Speed")] 79 public float MIN_SPEED; 80 public float MAX_SPEED; 81 public float START_SPEED; 82 public float speedScale; 83 84 [Header("Acceleration and Attenuation")] 85 public float DownAcceleration; 86 public float UpAttenuation; 87 public float GlideAttenuation; 88 public float rotationAttenuation; 89 90 [Header("Search")] 91 public float targetDistance; 92 public float searchAngle; 93 } 94} 95

Editor

1using UnityEditor; 2using System.Collections.Generic; 3 4/// <summary> 5/// キャラコントローラーのInspectorを拡張 6/// </summary> 7[CustomEditor(typeof(CharaController))] 8public class TestEditor : Editor 9{ 10 /// <summary> 11 /// 設定 12 /// </summary> 13 private Testsc _settings; 14 15 private CharaController _targetInspector; 16 17 /// <summary> 18 /// 選択したステータスのインデックス 19 /// </summary> 20 private static int _selectedStutasIndex; 21 22 private List<string> _stutasList = new List<string>(); 23 24 25 void OnEnable() 26 { 27 //_settings = (Testsc) target; 28 29 _targetInspector = (CharaController) target; 30 } 31 32 public override void OnInspectorGUI() 33 { 34 base.OnInspectorGUI(); 35 36 //変更があったときだけ 37 if (EditorGUI.EndChangeCheck()) 38 { 39 serializedObject.Update(); 40 41 42 //リストが空の時、エラーを吐くのでここで拾う 43 if (_settings.stutasList == null || _settings.stutasNameList.Count == 0) 44 { 45 EditorGUILayout.HelpBox("ステータスを設定してください", MessageType.Error); 46 return; 47 } 48 49 //リストの設定漏れは一番若い数字に 50 if (_settings.stutasNameList.Count <= _selectedStutasIndex) _settings.selectedStutasIndex = 0; 51 52 _selectedStutasIndex = EditorGUILayout.Popup("使用するステータス", _settings.selectedStutasIndex, _settings.stutasNameList.ToArray()); 53 54 //変更した値を設定側で保持 55 _settings.selectedStutasName = _settings.stutasNameList[_selectedStutasIndex]; 56 _settings.selectedStutasIndex = _selectedStutasIndex; 57 58 Undo.RecordObject(_targetInspector, "Settings Undo"); 59 EditorUtility.SetDirty(_targetInspector); 60 } 61 } 62}

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

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

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

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

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

guest

回答1

0

ベストアンサー

AssetDatabase.FindAssetsを使って探し出せないでしょうかね?

試しにちょっとやってみようかと思ったのですが、まず前段階としてCharaControllerTestscおよびステータス名を保持しておくべきじゃないかと思いまして、CharaControllerを下記のようにしました。

C#

1using System.Linq; 2using UnityEngine; 3 4public class CharaController : MonoBehaviour 5{ 6 //Testscへの参照、およびステータス名はCharaControllerがシリアライズして保持しておく 7 [SerializeField, HideInInspector] private Testsc charaSettings; 8 [SerializeField, HideInInspector] private string charaSettingName; 9 10 private Testsc.CharaStutas stutas; 11 12 //Awake時に名前がcharaSettingNameのステータスをcharaSettingsから引き出す 13 private void Awake() 14 { 15 if (this.charaSettings == null) 16 { 17 Debug.LogError($"{nameof(this.charaSettings)}が設定されていません"); 18 enabled = false; 19 return; 20 } 21 22 if (string.IsNullOrEmpty(this.charaSettingName)) 23 { 24 Debug.LogError($"{nameof(this.charaSettingName)}が設定されていません"); 25 enabled = false; 26 return; 27 } 28 29 this.stutas = this.charaSettings.stutasList.FirstOrDefault(s => s.name == this.charaSettingName); 30 31 if (this.stutas == null) 32 { 33 Debug.LogError($"{nameof(this.charaSettings)}に{this.charaSettingName}が見つかりませんでした"); 34 enabled = false; 35 return; 36 } 37 } 38 39 //ステータス情報を取り出せているか確認するため、コンソールにstutasの内容を出力してみる 40 private void Start() 41 { 42 Debug.Log($"{this.gameObject.name} parameters:"); 43 Debug.Log($"\t{nameof(this.stutas.name)}: {this.stutas.name}"); 44 Debug.Log($"\t{nameof(this.stutas.MIN_SPEED)}: {this.stutas.MIN_SPEED}"); 45 Debug.Log($"\t{nameof(this.stutas.MAX_SPEED)}: {this.stutas.MAX_SPEED}"); 46 Debug.Log($"\t{nameof(this.stutas.START_SPEED)}: {this.stutas.START_SPEED}"); 47 Debug.Log($"\t{nameof(this.stutas.speedScale)}: {this.stutas.speedScale}"); 48 Debug.Log($"\t{nameof(this.stutas.DownAcceleration)}: {this.stutas.DownAcceleration}"); 49 Debug.Log($"\t{nameof(this.stutas.UpAttenuation)}: {this.stutas.UpAttenuation}"); 50 Debug.Log($"\t{nameof(this.stutas.GlideAttenuation)}: {this.stutas.GlideAttenuation}"); 51 Debug.Log($"\t{nameof(this.stutas.rotationAttenuation)}: {this.stutas.rotationAttenuation}"); 52 Debug.Log($"\t{nameof(this.stutas.targetDistance)}: {this.stutas.targetDistance}"); 53 Debug.Log($"\t{nameof(this.stutas.searchAngle)}: {this.stutas.searchAngle}"); 54 } 55}

その上でTestEditorは下記のように変更してみましたが、いかがでしょうか。もしご質問者さんの意図を読み違えている部分などありましたら、コメントいただければなるべく直してみようと思います。

C#

1using System.Text; 2using UnityEditor; 3 4/// <summary> 5/// キャラコントローラーのInspectorを拡張 6/// </summary> 7[CustomEditor(typeof(CharaController))] 8public class TestEditor : UnityEditor.Editor 9{ 10 private readonly StringBuilder helpString = new StringBuilder(); 11 12 public override void OnInspectorGUI() 13 { 14 base.OnInspectorGUI(); 15 16 //アセットデータベースの中からTestscを探す 17 var foundGuids = AssetDatabase.FindAssets($"t:{nameof(Testsc)}"); 18 19 if (foundGuids.Length == 0) 20 { 21 EditorGUILayout.HelpBox($"{nameof(Testsc)}アセットが見つかりませんでした", MessageType.Error); 22 return; 23 } 24 25 if (foundGuids.Length > 1) 26 { 27 this.helpString.Clear(); 28 this.helpString.AppendLine($"{foundGuids.Length}個の{nameof(Testsc)}アセットが見つかりました"); 29 this.helpString.AppendLine($"以下の場所にあるアセットのうち、1つを残して他を削除してください:"); 30 foreach (var guid in foundGuids) 31 { 32 helpString.AppendLine(AssetDatabase.GUIDToAssetPath(guid)); 33 } 34 EditorGUILayout.HelpBox(helpString.ToString(), MessageType.Warning); 35 } 36 37 var settings = AssetDatabase.LoadAssetAtPath<Testsc>(AssetDatabase.GUIDToAssetPath(foundGuids[0])); 38 39 this.serializedObject.Update(); 40 41 //リストが空の時、エラーを吐くのでここで拾う 42 if (settings.stutasList == null || settings.stutasNameList.Count == 0) 43 { 44 EditorGUILayout.HelpBox("ステータスを設定してください", MessageType.Error); 45 return; 46 } 47 48 //見つかったTestscをCharaController.charaSettingsにセットする 49 this.serializedObject.FindProperty("charaSettings").objectReferenceValue = settings; 50 51 //現在のステータス名を取得し... 52 var stutasNameProperty = this.serializedObject.FindProperty("charaSettingName"); 53 var currentStutasName = stutasNameProperty.stringValue; 54 55 //そのインデックスを探す 56 var currentStutasIndex = settings.stutasNameList.IndexOf(currentStutasName); 57 58 //リストの設定漏れは一番若い数字に 59 if (currentStutasIndex < 0) currentStutasIndex = 0; 60 61 var newStutasIndex = EditorGUILayout.Popup("使用するステータス", currentStutasIndex, settings.stutasNameList.ToArray()); 62 63 //新しいステータス名をCharaController.charaSettingNameにセットする 64 stutasNameProperty.stringValue = settings.stutasNameList[newStutasIndex]; 65 this.serializedObject.ApplyModifiedProperties(); 66 } 67}

※ちなみにちょくちょく「Stutas」という単語が出てきて気になってしまったのですが、これは「Status」のことでしょうかね?

投稿2022/07/07 12:53

Bongo

総合スコア10807

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

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

Citron

2022/07/08 03:10

ご回答ありがとうございました。 アドバイス通りやってみたところ無事実現できました! ご丁寧にありがとうございました お恥ずかしながらStutasはスペルミスでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問