うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】Type の FieldInfo を serializedObject.FindProperty で取得できるように 再帰的に取得するコード

Array や List の場合は要素のTypeを取得する必要があるためチェック処理を入れている
また、System系の構造体やクラスだと無限ループすることがあったので Array や List 以外の System系は無視している

※Array や List の Path には非対応

       private static Dictionary<string, FieldInfo> GetAllFields(Type type, BindingFlags flags)
        {
            Dictionary<string, FieldInfo> list = new Dictionary<string, FieldInfo>();
            GetAllFieldsRecursive(type, flags, string.Empty, ref list);
            
            return list;
        }
 
        private static void GetAllFieldsRecursive(
            Type type, 
            BindingFlags flags,
            string path,
            ref Dictionary<string, FieldInfo> list)
        {
            foreach (var field in type.GetFields(flags))
            {
                var key = string.IsNullOrEmpty(path) ? field.Name : $"{path}{field.Name}";
                if (!list.ContainsKey(key))
                    list.Add(key, field);
 
                var ftype = field.FieldType;
                if (ftype.Namespace != null && 
                    (ftype.Namespace.StartsWith("System.") &&
                    !ftype.IsArray && 
                    !(ftype.IsGenericType && (ftype.GetGenericTypeDefinition() == typeof(List<>) || )))
                )
                {
                    continue;
                }
 
                if (ftype.IsClass && ftype != typeof(string) && ftype.IsSerializable)
                {
                    if (ftype.IsArray)
                        ftype = ftype.GetElementType();
                    else if (
                        ftype.IsGenericType && 
                        (ftype.GetGenericTypeDefinition() == typeof(List<>) || ftype.GetGenericTypeDefinition() == typeof(IList<>))
                    )
                        ftype = ftype.GetGenericArguments()[0];
                     
                    GetAllFieldsRecursive(ftype, flags, $"{field.Name}.", ref list);
                }
            }
        }

serializedObject.FindProperty で子フィールドを取得するときは ”.” を利用するので、結合している
結果以下のように取得できる

f:id:hacchi_man:20200106211316p:plain

再帰的に FiledInfo が欲しいだけなら Dictionary じゃなくて FieldInfo に変更すればよい