Unity中可以使用 AudioSource.PlayClipAtPoint 方便的播放一个音效。但是AudioSource并没有提供一个静态方法去停止这个音效。正常情况确实是不需要停止的,但是有时这个音效会比较长,且符合某个条件时需要停止他,那怎么办呢?我想了一个work around,基本思路是:PlayClipAtPoint会产生一个GameObject,名字是“One shot audio”,这个object会有一个AudioSource组件,其clip的名字就是PlayClipAtPoint播放的clip的名字。当然这个GameObject可能会有多个,所以需要循环查找。代码如下:
public void StopSoundEffect(string sfxName){
if (!IsEnableSfx) {
return;
}
if (!m_soundEffectCache.ContainsKey (sfxName)) {
return;
}
var audio = GameObject.Find ("One shot audio");
while (audio!=null) {
var source = audio.GetComponent<AudioSource>();
if(source.clip.name==sfxName){
source.enabled = false;
GameObject.Destroy(audio);
break;
}
audio = GameObject.Find ("One shot audio");
}
}
后记:发现这个方法有较大的几率会导致cpu占用升高,程序Freeze。导出xcode工程后用Instruments查看,GameObject.Find方法会导致freeze,但不是100%。虽然不知道是为什么,但是为了处理这个问题,写了一组新的方法用于播放/停止音效,要点是将创建的AudioSource返回。
public static AudioSource PlayClipAtPoint (AudioClip clip, Vector3 position, float volume=1.0f)
{
GameObject gameObject = new GameObject ("One shot audio");
gameObject.transform.position = position;
AudioSource audioSource = (AudioSource)gameObject.AddComponent (typeof(AudioSource));
audioSource.clip = clip;
audioSource.spatialBlend = 1f;
audioSource.volume = volume;
audioSource.Play ();
Object.Destroy (gameObject, clip.length * ((Time.timeScale >= 0.01f) ? Time.timeScale : 0.01f));
return audioSource;
}
public void StopSoundEffect(AudioSource audio){
if (!IsEnableSfx || audio==null) {
return;
}
if (audio.enabled) {
audio.enabled = false;
}
}