Unity中使用继承时列表内对象运行时为空的问题
Unity中继承MonoBehaviour的子类列表运行时引用为空的解决方法
问题根源
Unity对继承自MonoBehaviour的组件引用序列化有特殊限制:当你在Inspector中将挂载了Activable子类(如FM)的组件拖入List<Activable>时,编辑状态下Unity能显示引用,但运行时无法正确还原子类组件的引用,导致列表项为null。
[SerializeReference]特性在此场景不适用——它仅用于序列化非MonoBehaviour/ScriptableObject的普通引用类型,对Unity场景中的组件对象无效。而直接使用基类Activable组件时能正常工作,是因为Unity可以直接序列化基类型的组件引用。
可行解决方案
方法1:改用List<GameObject>存储对象,运行时动态获取组件
修改基类Activator的代码,通过存储GameObject引用,在运行时主动获取Activable子类组件:
public class Activator : MonoBehaviour { // 在Inspector中拖入挂载了Activable子类的GameObject public List<GameObject> activableGameObjects; private List<Activable> objectsToActivate = new List<Activable>(); public virtual void Start() { objectsToActivate.Clear(); foreach (var go in activableGameObjects) { var activable = go.GetComponent<Activable>(); if (activable != null) { objectsToActivate.Add(activable); Debug.Log(activable); } else { Debug.LogWarning($"GameObject {go.name} 未挂载Activable或其子类组件"); } } } }
这种方式利用Unity对GameObject引用的可靠序列化机制,确保运行时能正确获取到对应的子类组件。
方法2:使用[SerializeField]配合显式类型声明(可选)
如果坚持要直接存储组件引用,可以在子类中添加显式的序列化字段,但这种方式扩展性较差,仅适用于固定子类:
public class SpecificActivator : Activator { [SerializeField] private List<FM> fmObjects; public override void Start() { base.Start(); objectsToActivate.AddRange(fmObjects); // 后续逻辑处理 } }
但这种方法仅支持特定子类,不如方法1灵活。
验证步骤
- 将原
List<Activable>替换为List<GameObject>(方法1) - 在Inspector中重新拖入所有挂载了
FM组件的GameObject - 运行游戏,检查控制台输出,确认组件引用正常
内容的提问来源于stack exchange,提问作者Manuel A
相关产品推荐
相关产品推荐

