Unity - EditorGUILayout показывает скрытый элемент внутри поля Serializable - PullRequest
0 голосов
/ 26 июня 2019

Я использую Unity 2018.3.14f1 и пытаюсь создать новый ScriptableObject.Вот мой код:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Items;
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif

[CreateAssetMenu(fileName = "New Weapon", menuName = "Ingame Item/Weapon")]
public class Weapon : ScriptableObject
{
    public GameObject modelMesh;
    public WeaponType weaponType;
    public SlotType slotType;
    public WeaponTextureMaps[] weaponTextureMaps;


}

[Serializable]
public struct WeaponTextureMaps
{
    public Material material;
    public Texture normalMap;
    public Texture albedoMap;
    public Texture metalicMap;
    public Texture ambientOcullsionMap;
    public bool hasEmission;
    [HideInInspector]
    public Texture emissionMap;
}

#if UNITY_EDITOR
[CustomEditor(typeof(Weapon))]
public class Weapon_Editor : Editor
{
    Weapon script;
    GameObject model;
    SerializedProperty m_weaponTextureMaps;

    public void OnEnable()
    {
        script = (Weapon)target;
        model = script.modelMesh;
    }

    public override void OnInspectorGUI()
    {

        DrawDefaultInspector(); // for other non-HideInInspector fields
        if (GUI.changed)
        {
            if (model.name != script.modelMesh.name)
            {
                model = script.modelMesh;
                int totalMaterials = model.GetComponent<MeshRenderer>().sharedMaterials.Length;
                Array.Resize(ref script.weaponTextureMaps, totalMaterials);
                int i = -1;
                foreach (Material mat in model.GetComponent<MeshRenderer>().sharedMaterials)
                {
                    i++;
                    script.weaponTextureMaps[i].material = mat;
                }

            }
        }
        int ii = -1;
        foreach(WeaponTextureMaps wtm in script.weaponTextureMaps)
        {
            ii++;
            if (wtm.hasEmission == true)
            {
                script.weaponTextureMaps[ii].emissionMap = EditorGUILayout.ObjectField("Emission Map", script.weaponTextureMaps[ii].emissionMap, typeof(Texture), true) as Texture;
            }
        }
    }
}
#endif

enter image description here

Когда я нажимаю «Имеет выброс», скрытое поле должно появиться внутри «Элемент 0» под кнопкой »Имеет излучение "само по себе".

Однако оно появляется вне "Элемента 0" вместо того, чтобы быть внутри.Как я могу это исправить?

Как я могу заставить скрытое поле появляться внутри его элемента?

1 Ответ

0 голосов
/ 26 июня 2019

Ваша проблема использует DrawDefaultInspector();

Это приводит к тому, что поле появляется не только за пределами Element 0, но и после всех записей в Инспекторе.


Вместо этого я бы сделал CustomPropertyDrawer для WeaponTextureMaps.Огромное преимущество: вам не нужно снова реализовывать пользовательский редактор каждый раз, когда вы используете в скрипте поле WeaponTextureMaps.

    [Serializable]
    public struct WeaponTextureMaps
    {
        public Material material;
        public Texture normalMap;
        public Texture albedoMap;
        public Texture metalicMap;
        public Texture ambientOcullsionMap;
        public bool hasEmission;

        public Texture emissionMap;
    }

#if UNITY_EDITOR
    [CustomPropertyDrawer(typeof(WeaponTextureMaps))]
    public class WeaponTextureMapsDrawer : PropertyDrawer
    {
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            var material = property.FindPropertyRelative("material");
            var normalMap = property.FindPropertyRelative("normalMap");
            var albedoMap = property.FindPropertyRelative("albedoMap");
            var metalicMap = property.FindPropertyRelative("metalicMap");
            var ambientOcullsionMap = property.FindPropertyRelative("ambientOcullsionMap");
            var hasEmission = property.FindPropertyRelative("hasEmission");

            var emissionMap = property.FindPropertyRelative("emissionMap");

            // Using BeginProperty / EndProperty on the parent property means that
            // prefab override logic works on the entire property.
            EditorGUI.BeginProperty(position, label, property);

            // Draw label
            position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);

            EditorGUI.PropertyField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), material);
            position.y += EditorGUIUtility.singleLineHeight;

            EditorGUI.PropertyField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), normalMap);
            position.y += EditorGUIUtility.singleLineHeight;

            EditorGUI.PropertyField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), albedoMap);
            position.y += EditorGUIUtility.singleLineHeight;

            EditorGUI.PropertyField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), metalicMap);
            position.y += EditorGUIUtility.singleLineHeight;

            EditorGUI.PropertyField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), ambientOcullsionMap);
            position.y += EditorGUIUtility.singleLineHeight;

            EditorGUI.PropertyField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), hasEmission);
            position.y += EditorGUIUtility.singleLineHeight;

            if (hasEmission.boolValue)
            {
                EditorGUI.PropertyField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), emissionMap);
            }

            EditorGUI.EndProperty();
        }

        public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
        {
            var hasEmission = property.FindPropertyRelative("hasEmission");

            return EditorGUIUtility.singleLineHeight * (hasEmission.boolValue ? 8 : 7);
        }
    }
#endif

результат

enter image description here


Для вашего Weapon_Editor я бы посоветовал не смешивать SerializedProperty с прямым присвоением и изменением значений target.Вместо этого

[CustomEditor(typeof(Weapon))]
public class Weapon_Editor : Editor
{
    SerializedProperty model;
    SerializedProperty weaponType;
    SerializedProperty slotType;
    SerializedProperty weaponTextureMaps;

    // Link all script fields
    public void OnEnable()
    {
        model = serializedObject.FindProperty("modelMesh");
        weaponType = serializedObject.FindProperty("weaponType");
        slotType = serializedObject.FindProperty("slotType");
        weaponTextureMaps = serializedObject.FindProperty("weaponTextureMaps");
    }

    public override void OnInspectorGUI()
    {
        // Draw the Script field
        EditorGUI.BeginDisabledGroup(true);
        {
            EditorGUILayout.ObjectField("Script", MonoScript.FromScriptableObject((Weapon)target), typeof(Weapon), false);
        }
        EditorGUI.EndDisabledGroup();

        // load current values into the serialized fields
        serilaizedObject.Update();

        EditorGUI.BeginChangeCheck();
        {
            EditorGUILayout.PropertyField(model);
        }
        // runs everytime the model is changed
        if (EditorGUI.EndChangeCheck())
        {
            if(model.objectReferenceValue == null)
            {
                weaponTextureMaps.arraySize = 0;
            }
            else
            {
                // get the renderer fromt he SerializedProperty
                var renderer = ((GameObject)model.objectReferenceValue).GetComponent<Renderer>();

                if(renderer == null)
                {
                     weaponTextureMaps.arraySize = 0;
                }
                else
                {
                    int totalMaterials = renderer.sharedMaterials.Length;

                    weaponTextureMaps.arraySize = totalMaterials;

                    // set the material references
                    for (var i = 0; i < totalMaterials; i++)
                    {
                        weaponTextureMaps.GetArrayElementAtIndex(i).FindPropertyRelative("material").objectReferenceValue = renderer.sharedMaterials[i];
                    }
                }
            }
        }

        EditorGUILayout.PropertyField(weaponType);EditorGUILayout.PropertyField(slotType);

        // Note you have to pass true in order to see sub-fields
        EditorGUILayout.PropertyField(weaponTextureMaps, true);

        // Note that without that any changes to SerializedProperties does absolutely nothing
        serializedObject.ApplyModifiedProperties();
    }
}
#endif
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...