Unity继承中子类调用父类多维数组返回Null的问题求助
Unity继承中多维数组在子类Start中返回Null的解决方法
问题根源
你的问题核心是面向对象实例独立性和Unity脚本挂载逻辑的误解:
- 每个挂载在GameObject上的MonoBehaviour脚本都是独立实例,即使存在继承关系。如果同时挂载
ScriptA和ScriptB到同一对象(或不同对象),ScriptB实例的boardFields数组是自己的独立副本,和ScriptA实例的数组毫无关联。 - 若仅挂载
ScriptB,但ScriptA的Awake方法默认是私有访问权限(C#类成员默认private),虽然Unity的消息机制仍会调用,但这种写法不规范,可能引发潜在的执行顺序问题。
解决步骤
1. 规范脚本挂载,避免多实例混淆
只在目标GameObject上挂载ScriptB即可,无需同时挂载ScriptA。因为ScriptB继承自ScriptA,会自动继承其所有成员和方法,包括Awake,此时ScriptB实例的Awake会执行父类的初始化逻辑,数组会被正确赋值。
2. 修改父类Awake的访问修饰符(规范写法)
将ScriptA的Awake改为protected,确保子类可以重写并显式调用父类初始化逻辑(即使当前不需要重写,也能避免潜在问题):
public class ScriptA : MonoBehaviour { protected GameObject[,] boardFields = new GameObject[8, 8]; // 改为protected,允许子类访问/重写 protected void Awake() { boardFields[4, 0] = GameObject.Find("Canvas/Board/Fields/A4"); Debug.Log(boardFields[4, 0]); } } public class ScriptB : ScriptA { // 若子类需要自定义Awake逻辑,必须先调用base.Awake()初始化数组 protected override void Awake() { base.Awake(); // 优先执行父类的数组初始化 // 子类自己的Awake代码 } void Start() { Debug.Log(boardFields[4, 0]); } }
3. 替换GameObject.Find为序列化引用(更可靠)
GameObject.Find依赖精确路径,容易因对象改名、层级变动失效,建议改用Inspector直接赋值:
public class ScriptA : MonoBehaviour { // 添加[SerializeField]让数组在Inspector中可见,直接拖入对象赋值 [SerializeField] protected GameObject[,] boardFields = new GameObject[8, 8]; protected void Awake() { // 无需再用GameObject.Find,直接使用Inspector赋值的引用 Debug.Log(boardFields[4, 0]); } } public class ScriptB : ScriptA { void Start() { Debug.Log(boardFields[4, 0]); } }
4. 检查脚本执行顺序(可选)
若仍存在问题,可在Unity编辑器的Edit > Project Settings > Script Execution Order中,将ScriptA(或ScriptB)的执行顺序提前,确保数组初始化在Start之前完成。
内容的提问来源于stack exchange,提问作者Dupcjusz
相关产品推荐
相关产品推荐

