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

Unity调用LoadActiveScene后AudioSource空引用异常求助

问题分析

你的问题根源在于静态事件不会随场景卸载自动清除订阅。首次运行时,音频管理脚本实例订阅了静态事件;场景重载后,旧的音频管理实例及其依附的AudioSource已经被销毁,但它的PlayCarrotAudio方法仍然挂在静态事件上。当再次触发事件时,调用的是已销毁对象的方法,自然会出现NullReferenceException。

解决方案(无需静态变量)

方案1:在OnDestroy中取消静态事件订阅

这是最直接的修复方式,只需在音频管理脚本的销毁生命周期中取消订阅,避免旧实例的方法残留:

拾取脚本(触发事件)

public class PickupScript : MonoBehaviour
{
    // 静态事件保留,但要确保订阅者及时取消
    public static event Action audioCarrotPlay;

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Carrot"))
        {
            // 加分逻辑
            // 销毁物体
            Destroy(other.gameObject);
            // 触发事件
            audioCarrotPlay?.Invoke();
        }
    }
}

音频管理脚本

public class AudioFxManager : MonoBehaviour
{
    private AudioSource FxGame;
    public AudioClip carrotPickupClip; // 在Inspector赋值

    void Start()
    {
        FxGame = GetComponent<AudioSource>();
        // 订阅事件
        PickupScript.audioCarrotPlay += PlayCarrotAudio;
    }

    void OnDestroy()
    {
        // 关键:销毁前取消订阅,避免旧方法残留
        PickupScript.audioCarrotPlay -= PlayCarrotAudio;
    }

    void PlayCarrotAudio()
    {
        FxGame.PlayOneShot(carrotPickupClip);
    }
}

场景重载时,旧的AudioFxManager实例会被销毁,OnDestroy方法会移除它对静态事件的订阅;新场景的实例会在Start中重新订阅,触发事件时只会调用新实例的方法,不会再访问已销毁的FxGame。

方案2:使用DontDestroyOnLoad单例(跨场景持久化)

如果你的音频管理器需要在多个场景中复用,可以将其设置为跨场景持久化的单例,避免场景重载时被销毁:

音频管理脚本

public class AudioManager : MonoBehaviour
{
    // 单例实例(非静态变量的单例,只是用静态字段存实例)
    public static AudioManager Instance;
    private AudioSource FxGame;
    public AudioClip carrotPickupClip;

    void Awake()
    {
        // 确保全局只有一个音频管理器实例
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject); // 让物体不随场景销毁
        }
        else
        {
            // 如果新场景又创建了实例,直接销毁
            Destroy(gameObject);
        }
    }

    void Start()
    {
        FxGame = GetComponent<AudioSource>();
    }

    // 提供公开方法供拾取脚本调用
    public void PlayCarrotPickupAudio()
    {
        FxGame.PlayOneShot(carrotPickupClip);
    }
}

拾取脚本(直接调用单例方法,无需静态事件)

public class PickupScript : MonoBehaviour
{
    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Carrot"))
        {
            // 加分逻辑
            Destroy(other.gameObject);
            // 直接调用单例的音频播放方法
            AudioManager.Instance?.PlayCarrotPickupAudio();
        }
    }
}

这种方式完全避开了静态事件的订阅问题,单例实例会一直存在,FxGame也不会被销毁,自然不会有空引用。

方案3:使用ScriptableObject事件通道(解耦更优雅)

如果想进一步解耦拾取逻辑和音频播放逻辑,可以用ScriptableObject作为事件中间层,这种方式更符合Unity的模块化设计:

1. 创建ScriptableObject事件通道

using UnityEngine;
using UnityEngine.Events;

// 右键菜单创建:Assets > Create > Events > Carrot Pickup Event
[CreateAssetMenu(fileName = "CarrotPickupEvent", menuName = "Events/Carrot Pickup Event")]
public class CarrotPickupEvent : ScriptableObject
{
    public UnityEvent OnCarrotPickup;

    public void Raise()
    {
        OnCarrotPickup?.Invoke();
    }
}

2. 拾取脚本(触发事件)

public class PickupScript : MonoBehaviour
{
    // 在Inspector面板拖拽创建好的CarrotPickupEvent资源
    public CarrotPickupEvent carrotPickupEvent;

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Carrot"))
        {
            // 加分逻辑
            Destroy(other.gameObject);
            // 触发事件
            carrotPickupEvent.Raise();
        }
    }
}

3. 音频管理脚本(订阅事件)

public class AudioFxManager : MonoBehaviour
{
    // 在Inspector面板拖拽同一个CarrotPickupEvent资源
    public CarrotPickupEvent carrotPickupEvent;
    private AudioSource FxGame;
    public AudioClip carrotPickupClip;

    void Start()
    {
        FxGame = GetComponent<AudioSource>();
        // 订阅事件
        carrotPickupEvent.OnCarrotPickup += PlayCarrotAudio;
    }

    void OnDestroy()
    {
        // 销毁前取消订阅
        carrotPickupEvent.OnCarrotPickup -= PlayCarrotAudio;
    }

    void PlayCarrotAudio()
    {
        FxGame.PlayOneShot(carrotPickupClip);
    }
}

这种方式下,拾取逻辑和音频逻辑完全解耦,不需要互相引用脚本,场景重载时同样通过OnDestroy取消旧订阅,新实例重新订阅,不会有空引用问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 06:10:33