我正在使用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
当我单击“具有排放”时,隐藏的字段应该出现在“具有排放”按钮下方的“元素0”内。
但是,它出现在“元素0”的外部,而不是内部。我该如何解决?
如何使隐藏字段显示在其元素内部?
答案 0 :(得分:0)
您的问题是使用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
结果
对于您的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