UnityEditor 확장 필드로 보존된 사용자 정의 클래스의 개인 필드에 대한 액세스 정보: 메모

16237 단어 유닛 확장UnityC#

거치다


단원 편집기 확장에서 여러 가지 편리한 기능을 만들려고 시도할 때, 구성 요소 필드에 사용자 정의 클래스가 있다면, 검사기에서 사용자 정의 클래스의 개인 구성원을 조작할 때의 주석
다음 스크립트 예시 샘플 클래스의 hoge 필드에 직접 접근하고 싶어도private 구성원이기 때문에 직접 조작할 수 없습니다
using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
#endif



namespace Sample
{
    /// <summary>
    /// サンプルクラス.
    /// </summary>
    public class Sample : MonoBehaviour
    {
        /// <summary>
        /// 何かしらのデータクラス.
        /// </summary>
        [System.Serializable]
        public class HogeParam
        {
            [SerializeField] int id;
            public int Id => id;

            public HogeParam(
                int argId)
            {
                id = argId;
            }
        }


        [SerializeField] string characterName;
        [SerializeField] HogeParam hoge;


#if UNITY_EDITOR
        [CustomEditor(typeof(Sample))]
        class SampleEditor : Editor
        {
            public override void OnInspectorGUI()
            {
                var component = target as Sample;

                EditorGUILayout.LabelField("エディタ拡張だべ");

                component.characterName = EditorGUILayout.TextField("キャラ名", component.characterName);

                 // privateなメンバなためアクセスできない,プロパティもゲッターのみなので値のセットはできない.
                //component.hoge.Id = EditorGUILayout.IntField("ID", component.hoge.Id);

            }
        }
#endif
    }
}

RTA 플레이어의 가장 빠른 해결 방법


가장 빠른 해결 방법은 HogeParam 클래스의 구성원 필드를public로 설정하거나public 속성을 사용하여 외부에서 접근하는 것이다

using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
#endif



namespace Sample
{
    /// <summary>
    /// サンプルクラス.
    /// </summary>
    public class Sample : MonoBehaviour
    {
        /// <summary>
        /// 何かしらのデータクラス.
        /// </summary>
        [System.Serializable]
        public class HogeParam
        {
            [SerializeField] int id;
            public int Id
            {
                get { return id; }
                set { id = value; }
            }

            public HogeParam(
                int argId)
            {
                id = argId;
            }
        }

        [SerializeField] string characterName;
        [SerializeField] HogeParam hoge;


#if UNITY_EDITOR
        [CustomEditor(typeof(Sample))]
        class SampleEditor : Editor
        {
            public override void OnInspectorGUI()
            {
                var component = target as Sample;

                EditorGUILayout.LabelField("エディタ拡張だべ");
                component.characterName = EditorGUILayout.TextField("キャラ名", component.characterName);
                component.hoge.Id = EditorGUILayout.IntField("ID", component.hoge.Id);
            }
        }
#endif
    }
}

공공영역을 갖고 싶지 않은 사람들의 해결책


어떤 사람들은 장소를 공공장소로 바꾸는데, 너무 황당하다.속성에서 자유롭게 외부에서 조작할 수 없는 파라미터를 만들고 싶다!그러나 Inspector 확장을 보면 작업을 원하는 경우도 있으므로 C#의 반사를 이용하여 문제를 해결할 수 있습니다.
using UnityEngine;

 #if UNITY_EDITOR
 using System.Reflection;
 using UnityEditor;
 #endif



 namespace Sample
 {
     /// <summary>
     /// サンプルクラス.
     /// </summary>
     public class Sample : MonoBehaviour
     {
         /// <summary>
         /// 何かしらのデータクラス.
         /// </summary>
         [System.Serializable]
         public class HogeParam
         {
             [SerializeField] int id;

             public HogeParam(
                 int argId)
             {
                 id = argId;
             }
         }


         [SerializeField] string characterName;
         [SerializeField] HogeParam hoge;


 #if UNITY_EDITOR
         [CustomEditor(typeof(Sample))]
         class Class1Editor : Editor
         {
             public override void OnInspectorGUI()
             {
                 var component = target as Sample;

                 EditorGUILayout.LabelField("エディタ拡張だべ");

                 component.characterName = EditorGUILayout.TextField("キャラ名", component.characterName);

                 EditorGUILayout.LabelField("Hoge");
                 EditorGUI.indentLevel++;
                 // Reflectionを利用してパラメータを操作.
                 {
                     System.Type fieldType = component.hoge.GetType();
                     FieldInfo fieldInfo = fieldType.GetField("id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
                     int tempId = (int)fieldInfo.GetValue(component.hoge);
                     fieldInfo.SetValue(component.hoge, (int)EditorGUILayout.IntField("ID", tempId));
                }
                EditorGUI.indentLevel--;
             }
         }
 #endif
     }
 }

검사기에서 사용자 정의 클래스 내부의 개인 구성원에 성공적으로 접근

후기


Reflection은 편리하지만 남용하면 원본의 가독성과 원래의 접근 제한이 의미가 없기 때문에 저는 개인적으로 게임 논리 정편에서 사용하고 남용하지 않는 것이 좋다고 생각합니다.
이 방면 과 프로젝트 방침 등 의 상의
나에게 있어서, 나는 편집기만 확장하는 것이 가능하다고 생각한다

좋은 웹페이지 즐겨찾기