Unity音乐播放器连续重复选曲问题及空引用异常求助
解决Unity音乐播放器连续重复播放同一曲目&空引用异常问题
初始代码的问题分析
先拆解下你最初代码里导致问题的核心点:
- NullReferenceException根源:
Update里的if (audioSource.clip.name.Length >= 0)会直接触发空引用异常——游戏刚启动时audioSource.clip是null,直接访问name属性肯定报错。 - 逻辑错误:
audioSource.Play(index)是错误调用,AudioSource没有接受索引参数的Play方法;另外如果音频数组只有1首歌,那个while循环会无限卡死,因为nextTitle永远等于currentTitle。 - 重复播放问题:随机选曲时没有排除当前正在播放的曲目,自然会出现连续播放同一首的情况。
优化后的最终解决方案
我帮你重构了代码,不仅解决了重复播放和空引用的问题,还支持多音频数组扩展(比如音效、旁白等),以下是最终代码:
/* AudioPlayer.cs RTS Game Created by Robin den Ambtman on 17-06-2019 Copyright © Robinblitz. All rights reserved. */ using System.Collections; using UnityEngine; using System.Linq; public class AudioPlayer : MonoBehaviour { #region Variables //Variables needed for this code [Header("Sound arrays")] public AudioClip[] musicClips; [Space(10)] public AudioClip[] announcerClips; [Space(10)] public AudioClip[] TBDClips; [Header("Effect/Music sources")] public AudioSource effectAudioSource; public AudioSource musicAudioSource; #endregion #region Start Void // Start is called before the first frame update void Start() { //关闭音乐源的循环播放 musicAudioSource.loop = false; //用当前时间戳初始化随机数种子,让随机结果更均匀 Random.InitState((int)System.DateTime.Now.Ticks); } #endregion #region Music RNG //随机获取一首非当前播放的音乐 private AudioClip GetRandomMusicClip() { //过滤掉当前正在播放的曲目,避免连续重复 var filteredClips = musicClips.Where(c => c != musicAudioSource.clip).ToArray(); //兼容数组只有1首歌的情况,直接返回原数组随机项 return filteredClips.Length > 0 ? filteredClips[Random.Range(0, filteredClips.Length)] : musicClips[Random.Range(0, musicClips.Length)]; } #endregion #region Update Void // Update is called once per frame void Update() { //当音乐源停止播放时,自动播放下一首随机曲目 if (!musicAudioSource.isPlaying) { var newClip = GetRandomMusicClip(); musicAudioSource.clip = newClip; musicAudioSource.Play(); } //测试代码:按空格键播放音效 if (Input.GetKeyDown(KeyCode.Space)) { effectAudioSource.PlayOneShot(effectAudioSource.clip, 0.7f); } } #endregion }
关键优化点说明
- 拆分音频源:将音乐和音效的AudioSource分开,方便后续扩展不同类型的音频播放逻辑
- 智能过滤重复曲目:使用Linq的
Where方法排除当前正在播放的曲目,从剩余曲目里随机选择,彻底避免连续重复 - 空引用防护:去掉了直接访问
clip.name的危险代码,所有操作都做了安全兼容 - 随机数优化:用时间戳初始化随机种子,避免每次运行游戏的随机序列都一致
内容的提问来源于stack exchange,提问作者Robinblitz
相关产品推荐
相关产品推荐

