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

Unity中调用LoadLevels()出现NullReferenceException空引用错误求助

问题原因

你遇到的NullReferenceException是因为静态字段instance在调用LoadLevels()时还未被赋值,常见触发场景有3种:

  • LoadCustomLevels脚本未挂载到场景中处于激活状态的GameObject上,Awake方法从未执行,instance始终为null
  • 你调用LoadLevels()的时机早于该脚本的Awake执行时机(比如其他脚本的Awake生命周期里就调用了该方法)
  • 场景中挂载该脚本的GameObject被设置为失活,Awake生命周期不会触发
解决方案

第一步:修正单例写法,增加空校验

替换为以下版本的脚本,优化了单例赋值逻辑、增加调用空保护,同时保留你不需要将LoadTheLevels设为静态的需求:

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine.UI;
using UnityEngine;
using System;

public class LoadCustomLevels : MonoBehaviour
{
    static LoadCustomLevels instance;
    public GameObject ButtonPrefab; // 请在Inspector中赋值
    public Sprite DefaultPNG; // 请在Inspector中赋值

    private void Awake()
    {
        // 单例防重复逻辑
        if (instance != null && instance != this)
        {
            Destroy(gameObject);
            return;
        }
        instance = this;
        // 可选:如果需要跨场景保留这个对象,解开下面一行注释
        // DontDestroyOnLoad(gameObject);
    }

    void LoadTheLevels()
    {
        string path = Application.persistentDataPath + @"\Levels";
        if (!Directory.Exists(path))
            Directory.CreateDirectory(path);
        string[] levelPaths = Directory.GetDirectories(path);
        foreach (string item in levelPaths)
        {
            if (File.Exists(item + @"\data") && File.Exists(item + @"\objects"))
            {
                GameObject currentButton = Instantiate(ButtonPrefab, transform);

                currentButton.transform.GetChild(0).gameObject.GetComponent<Text>().text = new DirectoryInfo(path).Name;

                currentButton.transform.GetChild(1).gameObject.GetComponent<Image>().sprite = DefaultPNG;
                if (File.Exists(item + @"\icon.png"))
                {
                    Texture2D levelImagetex = new Texture2D(700, 500);
                    levelImagetex.LoadImage(File.ReadAllBytes(item + @"\icon.png"));
                    currentButton.transform.GetChild(1).gameObject.GetComponent<Image>().sprite = Sprite.Create(levelImagetex, currentButton.transform.GetChild(1).GetComponent<Rect>(), new Vector2(0.5f, 0.5f));
                }

                string version = File.ReadAllText(item + @"\data").Split(',')[0];
                if (Application.version != version)
                    currentButton.transform.GetChild(2).gameObject.GetComponent<Text>().color = Color.red;
                currentButton.transform.GetChild(2).gameObject.GetComponent<Text>().text = version;

                long levelSize = 0;
                foreach (var item2 in Directory.GetFiles(item))
                {
                    levelSize += new FileInfo(item2).Length;
                }
                levelSize /= 1024;
                currentButton.transform.GetChild(3).gameObject.GetComponent<Text>().text = levelSize.ToString() + "Kb";

                if ((DateTime.Now - new DirectoryInfo(item).LastAccessTime).Minutes <= 60)
                    currentButton.transform.GetChild(4).gameObject.GetComponent<Text>().text = (DateTime.Now - new DirectoryInfo(item).LastAccessTime).Minutes + " minute(s) ago" ;
                else if ((DateTime.Now - new DirectoryInfo(item).LastAccessTime).Hours <= 24)
                    currentButton.transform.GetChild(4).gameObject.GetComponent<Text>().text = (DateTime.Now - new DirectoryInfo(item).LastAccessTime).Hours + " hour(s) ago";
                else
                    currentButton.transform.GetChild(4).gameObject.GetComponent<Text>().text = (DateTime.Now - new DirectoryInfo(item).LastAccessTime).Days + " day(s) ago";
            }
        }
    }

    public static void LoadLevels()
    {
        // 增加空校验,避免空引用报错
        if (instance == null)
        {
            Debug.LogError("LoadCustomLevels实例不存在,请先将脚本挂载到场景激活的GameObject上");
            return;
        }
        instance.LoadTheLevels();
    }
}

第二步:检查场景配置和调用时机

  • 确认你已经把LoadCustomLevels脚本挂载到场景里一开始就处于激活状态的GameObject上,且Inspector中已经给ButtonPrefab和DefaultPNG赋值
  • 所有对LoadCustomLevels.LoadLevels()的调用,都要放在Start生命周期及之后的阶段执行,不要放在其他脚本的Awake里调用,避免单例还未初始化就被访问
额外注意事项

如果后续还出现空引用报错,可以排查以下点:

  • 实例化的ButtonPrefab的子物体数量和索引是否和你代码中GetChild(0)~GetChild(4)的索引对应
  • 上述代码已经修正了原代码中ReadAllBytes().ToString()的错误,该写法会返回字节数组的类型名而非文件内容,替换为ReadAllText才能正确读取版本号

内容的提问来源于stack exchange,提问作者gamefal 1820

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 06:48:01