- 自己去下一个Dotween 的插件。
using UnityEngine;
using System.Linq;
using System.Collections.Generic;
using System;
using DG.Tweening;
public class SoundMaster : MonoBehaviour
{
public const string POOL_KEY = "SoundMasterTemplate";
private static SoundMaster instance;
public static SoundMaster Ins { get { return instance; } }
public SoundData[] sounds;
public ObjectSoundData[] objects;
private void Awake()
{
if (instance != null && instance != this)
{
Destroy(this);
return;
}
instance = this;
}
private void OnDestroy()
{
if (instance == this)
instance = null;
}
private void Start()
{
var numSoundNameDuplicates = sounds.Select(_ => _.key).Concat(objects.Select(_ => _.key)).GroupBy(_ => _).Where(_ => _.Count() > 1);
if (numSoundNameDuplicates.Count() > 0)
{
var keys = numSoundNameDuplicates.Select(_ => _.Key).ToArray();
throw new System.InvalidOperationException("duplicated key exists, make sure the keys are unique. duplicated key(s): " + string.Join(", ", keys));
}
}
public void PlaySoundTo(string key, AudioSource aud, float delay = -1, bool recursive = false)
{
SoundData sd = null;
foreach (var s in sounds)
{
if (s.key == key)
{
sd = s;
break;
}
}
if (sd == null)
{
Debug.Log("audio with key: " + key + " not found.");
return;
}
var d = delay != -1 ? delay : sd.delay;
if (sd.mode == AudioPlayMode.InstanceIgnore)
{
if (aud.clip != sd.audio)
{
aud.Stop();
aud.clip = sd.audio;
PlayAudio(aud, d, recursive);
}
else if (!aud.isPlaying)
{
PlayAudio(aud, d, recursive);
}
}
else
{
if (aud.isPlaying)
aud.Stop();
aud.clip = sd.audio;
PlayAudio(aud, d, recursive);
}
}
public void PlaySound(string key, float delay = -1, bool recursive = false)
{
SoundData sd = null;
foreach (var s in sounds)
{
if (s.key == key)
{
sd = s;
break;
}
}
if (sd == null)
{
Debug.Log("audio key not found: " + key);
return;
}
var d = delay != -1 ? delay : sd.delay;
var playNewSound = false;
if (sd.mode != AudioPlayMode.Multiple)
{
var playingObj = GetPlayingSoundObject(sd.key);
if (playingObj != null)
{
if (sd.mode == AudioPlayMode.InstanceRestart)
{
var aud = playingObj.GetComponent<AudioSource>();
aud.Stop();
PlayAudio(aud, d, recursive);
}
}
else
{
playNewSound = true;
}
}
else
{
playNewSound = true;
}
if (playNewSound)
{
var obj = new GameObject();
obj.name = sd.key;
obj.transform.SetParent(transform);
var ac = obj.AddComponent<AudioControl>();
var aud = obj.AddComponent<AudioSource>();
aud.loop = false;
aud.playOnAwake = false;
aud.clip = sd.audio;
PlayAudio(aud, d, recursive);
}
}
public void PlayPichSound(string key,float pich)
{
SoundData sd = null;
foreach (var s in sounds)
{
if (s.key == key)
{
sd = s;
break;
}
}
if (sd == null)
{
Debug.Log("audio with key: " + key + " not found.");
return;
}
var playNewSound = false;
if (sd.mode != AudioPlayMode.Multiple)
{
var playingObj = GetPlayingSoundObject(sd.key);
if (playingObj != null)
{
if (sd.mode == AudioPlayMode.InstanceRestart)
{
var aud = playingObj.GetComponent<AudioSource>();
aud.Stop();
aud.pitch = pich;
PlayAudio(aud, sd.delay);
}
}
else
{
playNewSound = true;
}
}
else
{
playNewSound = true;
}
if (playNewSound)
{
var obj = new GameObject();
obj.name = sd.key;
obj.transform.SetParent(transform);
var ac = obj.AddComponent<AudioControl>();
var aud = obj.AddComponent<AudioSource>();
aud.loop = false;
aud.playOnAwake = false;
aud.clip = sd.audio;
aud.pitch = pich;
PlayAudio(aud, sd.delay);
}
}
public float PlayObjectSound(string key, float delay = -1, float volume = 1)
{
ObjectSoundData sd = null;
foreach (var s in objects)
{
if (s.key == key)
{
sd = s;
break;
}
}
if (sd == null)
{
Debug.Log("audio with key: " + key + " not found.");
return 0;
}
var d = delay != -1 ? delay : sd.delay;
var aud = sd.target;
if(sd.mode == AudioPlayMode.InstanceIgnore)
{
if (!aud.isPlaying)
PlayAudio(aud, d, volume:volume);
}
else
{
aud.Stop();
PlayAudio(aud, d, volume: volume);
}
return aud.clip.length;
}
public void StopObjectSound(string key)
{
foreach (var o in objects)
{
if (o.key == key)
{
o.target.GetComponent<AudioSource>().Stop();
break;
}
}
}
public void StopSound(string key, bool stopAllWithSameKey = true)
{
var len = transform.childCount;
while (len-- > 0)
{
var child = transform.GetChild(len);
if (child.name == key)
{
child.SetParent(null);
Destroy(child.gameObject);
if (stopAllWithSameKey)
len = transform.childCount;
else
break;
}
}
}
public void StopAllObjSound()
{
foreach (var sound in objects)
{
if (sound.target.isPlaying)
sound.target.Stop();
}
}
public void StopAllObjSoundExcept(string keyList)
{
foreach (var sound in objects)
{
if (sound.target.isPlaying && !keyList.Contains(sound.key))
sound.target.Stop();
}
}
public void StopSceneSound()
{
AudioSource tempAudioSource = null;
for (int i = 0; i < transform.childCount; i++)
{
tempAudioSource = transform.GetChild(i).GetComponent<AudioSource>();
if (tempAudioSource != null && tempAudioSource.isPlaying)
tempAudioSource.Stop();
}
}
public void StopSceneSound(string noStopkey)
{
AudioSource tempAudioSource = null;
for (int i = 0; i < transform.childCount; i++)
{
tempAudioSource = transform.GetChild(i).GetComponent<AudioSource>();
if (tempAudioSource != null && tempAudioSource.isPlaying)
{
if (!tempAudioSource.clip.name.Equals(noStopkey))
{
tempAudioSource.Stop();
}
}
}
}
public void StopSound(string key, float fadeTime)
{
var len = transform.childCount;
while (len-- > 0)
{
var child = transform.GetChild(len);
if (child.name == key)
{
child.SetParent(null);
child.GetComponent<AudioSource>().DOFade(0, fadeTime).OnComplete(
delegate {
Destroy(child.gameObject);
}
);
break;
}
}
}
public float GetObjectSoundLength(string key)
{
var sd = GetObjectSound(key);
if (sd == null)
return 0;
var aud = sd.target.GetComponent<AudioSource>();
if (aud != null && aud.clip != null)
return aud.clip.length;
return 0;
}
public ObjectSoundData GetObjectSound(string key)
{
ObjectSoundData sd = null;
foreach (var s in objects)
{
if (s.key == key)
{
sd = s;
break;
}
}
return sd;
}
private GameObject GetPlayingSoundObject(string key)
{
var len = transform.childCount;
while (len-- > 0)
{
var child = transform.GetChild(len);
if (child.name == key)
return child.gameObject;
}
return null;
}
private void PlayAudio(AudioSource aud, float delay, bool recursive = false, float volume = 1)
{
aud.loop = recursive;
aud.volume = volume;
if (delay != 0)
aud.PlayDelayed(delay);
else
aud.Play();
}
}
[System.Serializable]
public class SoundData
{
public string key;
public AudioClip audio;
public AudioPlayMode mode;
public float delay;
}
[System.Serializable]
public class ObjectSoundData
{
public string key;
public AudioSource target;
public AudioPlayMode mode;
public float delay;
}
public enum AudioPlayMode
{
Multiple,
InstanceIgnore,
InstanceRestart
}