Unity跨场景访问脚本失败:无法修改背景音乐音量
解决Unity跨场景访问背景音乐脚本的空引用问题
错误根源
你遇到的Object reference not set to an instance of an object错误,本质是设置场景加载时,游戏场景里的BGMusic对象根本不在当前场景中——Unity默认切换场景会卸载旧场景的所有对象,所以GameObject.FindGameObjectWithTag("BGMusic")返回null,后续调用GetComponent自然会报错。
另外代码里还有两处小错误:
- 分辨率选项里把
height写成了width,导致显示的分辨率都是宽x宽 loadBGVolume方法里的PlayerPrefs键名拼错了:BGMUsicVolume→BGMusicVolume
解决方案
核心思路是让背景音乐对象跨场景持久化,同时修复代码里的小问题,添加空引用防护。
1. 修改背景音乐脚本(BackgroundMusicScript)
添加DontDestroyOnLoad确保对象在场景切换时不被销毁,同时优化空引用检查:
public class BackgroundMusicScript : MonoBehaviour { public BirdScript bird; public AudioSource BGMusic; void Awake() { // 让对象跨场景持久化 DontDestroyOnLoad(gameObject); // 提前获取AudioSource组件,避免Start里重复查找 BGMusic = GetComponent<AudioSource>(); } void Start() { // 添加空引用运算符,避免找不到Bird时报错 bird = GameObject.FindGameObjectWithTag("Bird")?.GetComponent<BirdScript>(); // 加载保存的音量,设置默认值1 BGMusic.volume = PlayerPrefs.GetFloat("BGMusicVolume", 1f); } void Update() { // 先检查bird是否存在,再判断存活状态 if(bird != null && !bird.birdIsAlive) { BGMusic.Stop(); } } }
2. 修改设置菜单脚本(SettingsMenuLogic)
修复拼写错误,添加空引用检查,避免找不到BGMusic对象时报错:
public class SettingsMenuLogic : MonoBehaviour { public TMP_Dropdown resolutionDropdown; Resolution[] resolutions; public Slider BGMusicSlider; public BackgroundMusicScript BGMusicScript; void Start() { resolutions = Screen.resolutions; resolutionDropdown.ClearOptions(); List<string> options = new List<string>(); int currentResolutionIndex = 0; for(int i = 0; i < resolutions.Length; i++) { // 修复分辨率显示错误:width x height string option = resolutions[i].width + " x " + resolutions[i].height; options.Add(option); if (resolutions[i].width == Screen.currentResolution.width && resolutions[i].height == Screen.currentResolution.height) { currentResolutionIndex = i; } } resolutionDropdown.AddOptions(options); resolutionDropdown.value = currentResolutionIndex; resolutionDropdown.RefreshShownValue(); // 查找BGMusic对象并添加空检查 GameObject bgMusicObj = GameObject.FindGameObjectWithTag("BGMusic"); if (bgMusicObj != null) { BGMusicScript = bgMusicObj.GetComponent<BackgroundMusicScript>(); } else { Debug.LogWarning("找不到BGMusic对象!请确认背景音乐对象已设置正确标签,且先加载了包含它的场景"); } // 初始化音量设置(简化逻辑) if (!PlayerPrefs.HasKey("BGMusicVolume")) { PlayerPrefs.SetFloat("BGMusicVolume", 1f); } loadBGVolume(); } public void setResolution(int resolutionIndex) { Resolution resolution = resolutions[resolutionIndex]; Screen.SetResolution(resolution.width, resolution.height, Screen.fullScreen); } public void changeBGVolume() { // 修改音量前先检查组件是否存在 if (BGMusicScript != null && BGMusicScript.BGMusic != null) { BGMusicScript.BGMusic.volume = BGMusicSlider.value; saveBGVolume(); } else { Debug.LogWarning("无法修改音量:背景音乐脚本未初始化"); } } public void saveBGVolume() { PlayerPrefs.SetFloat("BGMusicVolume", BGMusicSlider.value); } public void loadBGVolume() { // 修复键名拼写错误 BGMusicSlider.value = PlayerPrefs.GetFloat("BGMusicVolume", 1f); } public void setQuality(int qualityIndex) { QualitySettings.SetQualityLevel(qualityIndex); } public void setFullscreen(bool isFullscreen) { Screen.fullScreen = isFullscreen; } }
额外注意事项
- 标签设置:确保背景音乐对象的Tag确实是
BGMusic(在Inspector的Tag下拉框里选择或创建)。 - 场景加载顺序:如果从设置场景启动游戏,需要先加载包含背景音乐的游戏场景,再加载设置场景;或者用
SceneManager.LoadSceneAsync("设置场景", LoadSceneMode.Additive)以叠加模式加载设置场景。 - 避免重复实例:如果担心多次加载场景创建多个背景音乐对象,可以在Awake里添加单例逻辑,确保全局只有一个实例。
内容的提问来源于stack exchange,提问作者Daralela
相关产品推荐
相关产品推荐

