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

Unity新手技术问询:跨脚本调用方法时遭遇NullReferenceException错误及自行解决记录

Unity跨脚本调用NullReferenceException问题解决与优化方案

作为Unity新手,你遇到的NullReferenceException是跨脚本调用时最常见的问题之一,本质就是你声明的displayController变量没有指向任何实际的组件实例,所以调用它的方法时会报错。下面先梳理你的问题,再给出你找到的解决方案和其他更灵活的替代方案:

问题回顾

你将语言选择下拉菜单的逻辑写在ChoseLanguage脚本(ScriptA)中,想要调用DisplayController脚本(ScriptB)的DropdownSetLanguage()方法。虽然语言选择和PlayerPrefs保存逻辑正常,但调用方法时出现以下错误:

NullReferenceException: Object reference not set to an instance of an object ChoseLanguage.DropdownChooseLanguage () (at Assets/Scripts/ChoseLanguage.cs:28)

你的代码片段:

ScriptA (ChoseLanguage.cs)

using UnityEngine;
public class ChoseLanguage: MonoBehaviour {
    public TMPro.TMP_Dropdown myDrop;
    DisplayController displayController; // 这里的变量未初始化
    public void DropdownChooseLanguage() {
        if (myDrop.value == 1) PlayerPrefs.SetString("chosenLanguage", "Spanish");
        if (myDrop.value == 2) PlayerPrefs.SetString("chosenLanguage", "Japanese");
        if (myDrop.value == 3) PlayerPrefs.SetString("chosenLanguage", "Korean");
        if (myDrop.value == 4) PlayerPrefs.SetString("chosenLanguage", "Icelandic");
        Debug.Log(PlayerPrefs.GetString("chosenLanguage"));
        displayController.DropdownSetLanguage(); // 调用未初始化的变量导致报错
    }
}

ScriptB (DisplayController.cs)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
using TMPro;
public class DisplayController : MonoBehaviour {
    ...
    public void DropdownSetLanguage() {
        SetFileName();
        setLanguage.gameObject.SetActive(false);
        Start();
    }
    ...
}

你找到的解决方案(手动赋值法)

这是新手最容易理解的方法,步骤完全正确:

  1. 将DisplayController displayController;修改为公开字段:public DisplayController displayController;
  2. 在Unity编辑器的Inspector面板中,找到挂载了ChoseLanguage脚本的游戏对象,把挂载了DisplayController脚本的游戏对象拖入这个公开字段中

这种方法直观,适合场景结构简单的情况,能明确看到引用关系。

其他更灵活的解决方案

1. 代码自动查找(适合单实例场景)

如果你的场景中只有一个DisplayController实例,可以在ChoseLanguage的初始化方法中自动查找组件,不用手动拖赋值:

using UnityEngine;
public class ChoseLanguage: MonoBehaviour {
    public TMPro.TMP_Dropdown myDrop;
    DisplayController displayController;

    void Awake()
    {
        // 查找场景中第一个DisplayController组件
        displayController = FindObjectOfType<DisplayController>();
        // 如果要指定特定对象,可以用:
        // displayController = GameObject.Find("你的DisplayController对象名称").GetComponent<DisplayController>();
    }

    public void DropdownChooseLanguage() {
        // 原有逻辑...
        if(displayController != null) // 加个空判断更安全,避免意外报错
            displayController.DropdownSetLanguage();
    }
}

注意:如果场景中有多个同类型组件,FindObjectOfType会返回第一个找到的,要确保找的是你需要的那个。

2. 单例模式(适合全局通用控制器)

如果DisplayController是全局唯一的UI控制器(比如整个游戏只有一个语言显示控制),可以把它做成单例,这样任何脚本都能直接调用它的方法:
修改DisplayController脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
using TMPro;
public class DisplayController : MonoBehaviour {
    // 静态单例实例,全局可访问
    public static DisplayController Instance;

    void Awake()
    {
        // 确保场景中只有一个实例
        if(Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject); // 可选,跨场景保留这个对象
        }
        else
        {
            Destroy(gameObject); // 如果重复创建就销毁多余的
        }
    }

    ...
    public void DropdownSetLanguage() {
        SetFileName();
        setLanguage.gameObject.SetActive(false);
        Start();
    }
    ...
}

然后在ChoseLanguage中调用时直接用:

public void DropdownChooseLanguage() {
    // 原有逻辑...
    DisplayController.Instance.DropdownSetLanguage(); // 直接通过单例调用,无需声明变量
}

这种方法适合全局管理类脚本,不用处理字段赋值,非常方便。

新手小贴士

  • 遇到NullReferenceException时,第一反应是检查变量有没有被正确赋值,可以用Debug.Log(displayController)打印看看是不是null
  • 拆分脚本时尽量按功能模块划分(比如交互逻辑、显示控制、数据存储),避免一个脚本臃肿不堪
  • 公开字段虽然方便,但如果不想在Inspector中暴露,可以用[SerializeField]修饰私有字段,既可以在Inspector赋值,又保持代码封装性:[SerializeField] private DisplayController displayController;

内容的提问来源于stack exchange,提问作者Weasel Bandit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 13:57:34