Unity中关联变量与枚举的更优方案?替代数组实现Inspector易读展示
可行的Inspector友好型实现方案
方案1:自定义可序列化抗性条目结构体(推荐)
直接把伤害类型和对应抗性值封装成可序列化结构体,用列表或数组存储,Inspector里每个条目会清晰显示对应的伤害类型和数值,完全无需注释。
代码示例:
using System.Collections.Generic; using UnityEngine; public enum SpecialDamageType { Physical, Fire, Cold, Lightning, Hydro, Air, } // 可序列化的抗性条目结构体 [System.Serializable] public struct ResistanceEntry { public SpecialDamageType damageType; [Range(0f, 1f)] // 可选:限制抗性值范围(0=无抗性,1=免疫) public float resistanceValue; } public abstract class EnemyParent : ScriptableObject { [Header("Enemy Details")] [SerializeField] public string enemyName; [SerializeField] public string enemyDesc; [Header("Enemy Stats")] [SerializeField] public float enemyMaxHealthf; [SerializeField] protected float enemyArmourf; [SerializeField] protected float enemyMaxShield; [SerializeField] protected float enemyWalkSpeed; [SerializeField] protected float enemyRunSpeed; [Header("Elemental Resistances")] [SerializeField] private List<ResistanceEntry> enemyResistances; // 提供获取抗性的方法 public float GetResistance(SpecialDamageType damageType) { foreach (var entry in enemyResistances) { if (entry.damageType == damageType) { return entry.resistanceValue; } } return 0f; // 默认无抗性 } }
该方案优势:
- Inspector中每个抗性条目明确显示类型与数值,直观易懂
- 灵活支持新增/删除抗性条目,无需修改类结构
- 可通过
[Range]属性限制数值范围,避免不合理输入
方案2:为每个枚举类型定义单独字段
如果SpecialDamageType枚举不会频繁新增类型,直接给每个伤害类型定义对应抗性字段,Inspector里字段名直接对应抗性类型,可读性拉满。
代码示例:
public abstract class EnemyParent : ScriptableObject { // 原有字段省略... [Header("Elemental Resistances")] [Range(0f, 1f)] public float physicalResistance; [Range(0f, 1f)] public float fireResistance; [Range(0f, 1f)] public float coldResistance; [Range(0f, 1f)] public float lightningResistance; [Range(0f, 1f)] public float hydroResistance; [Range(0f, 1f)] public float airResistance; // 获取抗性的方法 public float GetResistance(SpecialDamageType damageType) { return damageType switch { SpecialDamageType.Physical => physicalResistance, SpecialDamageType.Fire => fireResistance, SpecialDamageType.Cold => coldResistance, SpecialDamageType.Lightning => lightningResistance, SpecialDamageType.Hydro => hydroResistance, SpecialDamageType.Air => airResistance, _ => 0f }; } }
该方案优势:
- Inspector中无需额外理解,字段名直接对应抗性类型
- 代码逻辑简单,无需遍历列表
缺点:枚举新增类型时,需手动添加对应字段和switch分支
方案3:自定义PropertyDrawer(进阶)
如果想保留数组的高效性,同时让Inspector显示枚举名称,可自定义PropertyDrawer替换数组元素的显示方式(需写编辑器脚本,适合有编辑器开发经验的场景)。
核心思路:创建自定义PropertyDrawer,绘制数组元素时自动显示对应索引的枚举名称。
编辑器脚本(需放在Editor文件夹下):
using UnityEditor; using UnityEngine; [CustomPropertyDrawer(typeof(float), true)] public class ResistanceArrayDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { // 匹配抗性数组字段(这里假设字段名为enemyResistances) if (property.name == "enemyResistances" && property.parent != null) { int index = int.Parse(property.propertyPath.Split('[')[1].Split(']')[0]); SpecialDamageType damageType = (SpecialDamageType)index; label.text = damageType.ToString(); } EditorGUI.PropertyField(position, property, label); } }
EnemyParent中定义数组:
[Header("Elemental Resistances")] [SerializeField] private float[] enemyResistances = new float[System.Enum.GetValues(typeof(SpecialDamageType)).Length];
该方案优势:保留数组性能的同时,Inspector里每个数组元素标签显示对应枚举名称,解决原数组方案的可读性问题。
内容的提问来源于stack exchange,提问作者Hiyazcool
相关产品推荐
相关产品推荐

