Unity 2D中通过字符串获取Unit类属性值遇空引用异常求助
解决Unity中获取Unit属性的空引用错误及动态属性获取方案
问题根源分析
你的NullReferenceException大概率来自两个核心问题:
- unit对象未赋值:在Inspector面板中,没有将挂载了Unit组件的玩家对象拖入脚本的
unit字段,导致unit为null。 - 反射调用逻辑错误:你用
GetField("MaxHealth")尝试获取属性,但MaxHealth是Unit类的公共属性(Property),不是字段(Field)——对应的字段是小写的maxHealth(且为protected,默认无法通过反射访问)。GetField找不到目标会返回null,调用GetValue时自然触发空引用。
解决方案步骤
1. 先确保unit实例已正确赋值
选中挂载该脚本的GameObject,在Inspector面板找到你的脚本组件,将带有Unit组件的玩家对象拖入unit字段中。每个挂载该脚本的GameObject都需要完成这一步。
2. 修正反射逻辑(获取属性而非字段)
因为要获取的是MaxHealth这类公共属性,应该使用GetType().GetProperty()而非GetField(),代码示例如下:
using UnityEngine; using System; using System.Reflection; public class StatUI : MonoBehaviour { [SerializeField] private Unit unit; [SerializeField] private string stat; // 配置为MaxHealth、Speed、Damage private void OnEnable() { // 订阅Unit的属性变更事件(替换为你实际的事件名称) if (unit != null) { // unit.StatChanged += OnStatChange; } } private void OnDisable() { // 取消订阅,避免内存泄漏 if (unit != null) { // unit.StatChanged -= OnStatChange; } } private void OnStatChange(object sender, EventArgs args) { if (unit == null) { Debug.LogError("Unit实例未赋值,请在Inspector中设置"); return; } // 获取指定名称的公共属性 PropertyInfo property = unit.GetType().GetProperty(stat); if (property == null) { Debug.LogError($"Unit类中不存在名为{stat}的公共属性"); return; } // 校验类型并获取属性值 if (property.PropertyType == typeof(float)) { float value = (float)property.GetValue(unit); Debug.Log($"Unit {stat}: {value}"); // 在此添加UI更新逻辑,比如修改文本组件内容 // GetComponent<TMPro.TMP_Text>().text = value.ToString(); } else { Debug.LogError($"{stat}属性不是float类型"); } } }
3. 更安全的替代方案(避免反射)
反射存在性能开销和字符串拼写错误的风险,推荐用枚举+字典映射的方式替代,稳定性和性能更好:
using UnityEngine; using System; using System.Collections.Generic; public class StatUI : MonoBehaviour { [SerializeField] private Unit unit; [SerializeField] private StatType statType; // 用枚举替代字符串,避免拼写错误 private Dictionary<StatType, Func<Unit, float>> _statGetters; private void Awake() { // 初始化属性获取器字典 _statGetters = new Dictionary<StatType, Func<Unit, float>> { { StatType.MaxHealth, u => u.MaxHealth }, { StatType.Speed, u => u.Speed }, { StatType.Damage, u => u.Damage } }; } private void OnEnable() { if (unit != null) { // 订阅Unit的属性变更事件 // unit.StatChanged += OnStatChange; } } private void OnDisable() { if (unit != null) { // 取消订阅事件 // unit.StatChanged -= OnStatChange; } } private void OnStatChange(object sender, EventArgs args) { if (unit == null) { Debug.LogError("Unit实例未赋值"); return; } if (_statGetters.TryGetValue(statType, out var getter)) { float value = getter(unit); Debug.Log($"Unit {statType}: {value}"); // 添加UI更新逻辑 } else { Debug.LogError($"未找到对应{statType}的属性获取方法"); } } // 定义枚举,对应Unit的所有属性 public enum StatType { MaxHealth, Speed, Damage } }
内容的提问来源于stack exchange,提问作者draymone
相关产品推荐
相关产品推荐

