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

Unity运行2D游戏触发NullReferenceException错误求助

排查Unity中Inventory脚本的NullReferenceException错误

错误原因

  1. MonoBehaviour构造函数执行时机问题:Unity中,继承自MonoBehaviour的类的自定义构造函数会在Awake方法执行前很久就被调用。此时GameEvents的Awake还未运行,静态实例gameEvents仍为null,直接访问CustonGameEvent.GameEvents.gameEvents.onItemPurchase会触发空引用错误。
  2. 违反Unity生命周期规范:Unity不推荐给MonoBehaviour编写自定义构造函数,这类组件的实例由Unity管理,自定义构造会导致生命周期逻辑混乱。

解决方案

1. 重构Inventory脚本,用Unity生命周期方法替代构造函数

移除自定义构造,将初始化和事件注册逻辑移到Awake中,同时添加事件注销逻辑防止内存泄漏:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Inventory : MonoBehaviour
{
    private List<Item> itemList;

    private void Awake()
    {
        // 先初始化物品列表,避免AddItem时的潜在空引用
        itemList = new List<Item>();
        
        // 注册事件前先判空,避免GameEvents实例未初始化的情况
        if (CustonGameEvent.GameEvents.gameEvents != null)
        {
            CustonGameEvent.GameEvents.gameEvents.onItemPurchase += AddItem;
        }
        else
        {
            Debug.LogError("未找到GameEvents实例!请确保场景中存在带有GameEvents组件的GameObject");
        }
        
        Debug.Log("Inventory已初始化");
    }

    public void AddItem(Item item)
    {
        itemList.Add(item);
    }

    // 组件销毁时注销事件,防止内存泄漏
    private void OnDestroy()
    {
        if (CustonGameEvent.GameEvents.gameEvents != null)
        {
            CustonGameEvent.GameEvents.gameEvents.onItemPurchase -= AddItem;
        }
    }
}

2. 优化GameEvents的单例实现

给GameEvents添加单例安全检查,避免多实例冲突,同时用C#空传播运算符简化事件触发逻辑:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace CustonGameEvent
{
    public class GameEvents : MonoBehaviour
    {
        public static GameEvents gameEvents;

        private void Awake()
        {
            // 单例安全检查,确保场景中只有一个GameEvents实例
            if (gameEvents == null)
            {
                gameEvents = this;
                DontDestroyOnLoad(gameObject); // 如需跨场景保留实例,可添加此行
            }
            else
            {
                Destroy(gameObject);
            }
        }

        public event Action<Item> onItemPurchase;

        public void ItemPurchaseMade(Item item)
        {
            // 空传播运算符替代手动null检查,更简洁安全
            onItemPurchase?.Invoke(item);
        }
    }
}

3. 额外注意事项

  • 确保场景中存在且仅存在一个挂载了GameEvents组件的GameObject;
  • 若仍存在初始化顺序问题,可在Unity编辑器中通过Edit > Project Settings > Script Execution Order,将GameEvents的执行顺序设为比Inventory更早,保证其Awake先执行;
  • 永远不要给MonoBehaviour编写自定义构造函数,所有初始化逻辑都应放在Awake/Start等Unity官方生命周期方法中。

内容的提问来源于stack exchange,提问作者kylorius beno

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 20:27:30