You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 13:50:26