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

Unity2D环境音效管理器脚本修改:多场景无缝切换不同音效组

解决方案

针对你的需求,我修改了AmbientManager脚本,实现了分场景切换音效组、无缝播放控制以及特定场景静音的功能,核心思路是通过监听场景加载事件动态切换音效配置,同时确保单例避免重复实例:

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

[System.Serializable]
public class SceneAudioGroup
{
    public string sceneName;
    public AudioClip[] audioClips;
    public bool isSeamlessGroup; // 标记是否属于同一无缝播放组,比如关卡1和关卡2用同一组音效,切换时不中断
}

public class AmbientManager : MonoBehaviour
{
    public List<SceneAudioGroup> sceneAudioGroups;
    public string[] muteScenes = { "MainMenu" }; // 需要静音的场景名

    private AudioSource audioSource;
    private SceneAudioGroup currentAudioGroup;
    private static AmbientManager instance;

    private void Awake()
    {
        // 单例模式,确保只有一个实例
        if (instance != null && instance != this)
        {
            Destroy(gameObject);
            return;
        }
        instance = this;
        DontDestroyOnLoad(gameObject);

        audioSource = GetComponent<AudioSource>();
        audioSource.loop = false; // 关闭循环,因为我们要随机播放不同曲目
    }

    private void OnEnable()
    {
        // 订阅场景加载事件
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    private void OnDisable()
    {
        // 取消订阅,避免内存泄漏
        SceneManager.sceneLoaded -= OnSceneLoaded;
    }

    private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        string sceneName = scene.name;

        // 检查是否是静音场景
        foreach (string muteScene in muteScenes)
        {
            if (sceneName == muteScene)
            {
                audioSource.Stop();
                currentAudioGroup = null;
                return;
            }
        }

        // 查找当前场景对应的音效组
        SceneAudioGroup targetGroup = sceneAudioGroups.Find(g => g.sceneName == sceneName);
        if (targetGroup == null)
        {
            audioSource.Stop();
            currentAudioGroup = null;
            return;
        }

        // 处理无缝播放:如果当前组和目标组属于同一无缝组,且正在播放,不切换
        if (currentAudioGroup != null && currentAudioGroup.isSeamlessGroup == targetGroup.isSeamlessGroup && audioSource.isPlaying)
        {
            return;
        }

        // 切换到目标音效组,随机播放
        currentAudioGroup = targetGroup;
        PlayRandomClipFromGroup(currentAudioGroup);
    }

    private void PlayRandomClipFromGroup(SceneAudioGroup group)
    {
        if (group.audioClips.Length == 0) return;

        int randomIndex = Random.Range(0, group.audioClips.Length);
        AudioClip randomClip = group.audioClips[randomIndex];

        audioSource.clip = randomClip;
        audioSource.Play();
        // 播放完当前曲目后自动随机播放同组的下一首
        StartCoroutine(PlayNextClipAfterCurrent(group));
    }

    private IEnumerator PlayNextClipAfterCurrent(SceneAudioGroup group)
    {
        yield return new WaitForSeconds(audioSource.clip.length);
        // 如果当前组没变化,继续随机播放同组曲目
        if (currentAudioGroup == group)
        {
            PlayRandomClipFromGroup(group);
        }
    }

    private void Update()
    {
        // 简化暂停逻辑
        audioSource.pause = Pause_menu.GameIsPaused;
    }
}

关键改动说明

  • SceneAudioGroup可序列化类:在Inspector面板可以直观地给每个场景绑定对应的音效组,还能标记是否属于无缝播放组——比如关卡1和关卡2设置相同的isSeamlessGroup状态,切换场景时不会中断当前播放。
  • 单例模式:解决DontDestroyOnLoad导致的重复创建实例问题,确保整个游戏只有一个AmbientManager在运行。
  • 场景加载监听:通过SceneManager.sceneLoaded事件,每次场景切换时自动检查并切换音效配置,无需手动调用。
  • 自动续播逻辑:用协程监听当前音效播放结束,自动随机播放同组的下一首,实现持续的环境音效。
  • 静音场景配置:通过muteScenes数组设置不需要播放音效的场景(比如主菜单),切换到这些场景时自动停止播放。

使用步骤

  1. 在Inspector面板的Scene Audio Groups列表中,添加每个需要播放音效的场景条目:
    • 输入场景名称(要和Build Settings里的场景名完全一致)
    • 拖入对应场景的音效数组
    • 给同属一个无缝播放组的场景设置相同的Is Seamless Group勾选状态
  2. 在Mute Scenes数组中添加主菜单等需要静音的场景名称
  3. 将这个脚本挂载到一个空物体上,放在主场景(比如主菜单)中,运行游戏即可自动生效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 13:05:23