/****************************************************************************
* Copyright (c) 2017 ~ 2021.1 liangxie
*
* http://qframework.io
* https://github.com/liangxiegame/QFramework
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
****************************************************************************/
using System;
using System.Collections.Generic;
using UnityEngine;
namespace QFramework
{
public class AudioKit
{
///
/// 音频相关的设置
///
public static readonly AudioKitSettings Settings = new AudioKitSettings();
public static AudioPlayer MusicPlayer
{
get { return AudioManager.Instance.MusicPlayer; }
}
public static AudioKitConfig Config = new AudioKitConfig();
///
/// 播放背景音乐
///
///
///
///
///
///
///
public static void PlayMusic(string musicName, bool loop = true, System.Action onBeganCallback = null,
System.Action onEndCallback = null, bool allowMusicOff = true, float volume = -1f)
{
AudioManager.Instance.CheckAudioListener();
var audioMgr = AudioManager.Instance;
audioMgr.CurrentMusicName = musicName;
if (!Settings.IsMusicOn.Value && allowMusicOff)
{
onBeganCallback?.Invoke();
onEndCallback?.Invoke();
return;
}
Debug.Log(">>>>>> Start Play Music");
// TODO: 需要按照这个顺序去 之后查一下原因
// 需要先注册事件,然后再play
MusicPlayer.SetOnStartListener(musicUnit =>
{
onBeganCallback?.Invoke();
if (volume < 0)
{
MusicPlayer.SetVolume(Settings.MusicVolume.Value);
}
else
{
MusicPlayer.SetVolume(volume);
}
// 调用完就置为null,否则应用层每注册一个而没有注销,都会调用
MusicPlayer.SetOnStartListener(null);
});
MusicPlayer.SetAudio(audioMgr.gameObject, musicName, loop);
MusicPlayer.SetOnFinishListener(player =>
{
onEndCallback?.Invoke();
// 调用完就置为null,否则应用层每注册一个而没有注销,都会调用
player.SetOnFinishListener(null);
});
}
public static void StopMusic()
{
AudioManager.Instance.MusicPlayer.Stop();
}
public static void PauseMusic()
{
AudioManager.Instance.MusicPlayer.Pause();
}
public static void ResumeMusic()
{
AudioManager.Instance.MusicPlayer.Resume();
}
public static AudioPlayer VoicePlayer
{
get { return AudioManager.Instance.VoicePlayer; }
}
public static void PlayVoice(string voiceName, bool loop = false, System.Action onBeganCallback = null,
System.Action onEndedCallback = null)
{
var audioMgr = AudioManager.Instance;
AudioManager.Instance.CheckAudioListener();
audioMgr.CurrentVoiceName = voiceName;
if (!Settings.IsVoiceOn.Value)
{
return;
}
VoicePlayer.SetOnStartListener(player =>
{
onBeganCallback?.Invoke();
player.SetVolume(Settings.VoiceVolume.Value);
// 调用完就置为null,否则应用层每注册一个而没有注销,都会调用
VoicePlayer.SetOnStartListener(null);
});
VoicePlayer.SetAudio(AudioManager.Instance.gameObject, voiceName, loop);
VoicePlayer.SetOnFinishListener(musicUnit =>
{
onEndedCallback?.Invoke();
VoicePlayer.SetOnFinishListener(null);
});
}
public static void PauseVoice()
{
VoicePlayer.Pause();
}
public static void ResumeVoice()
{
VoicePlayer.Resume();
}
public static void StopVoice()
{
VoicePlayer.Stop();
}
public static AudioPlayer PlaySound(string soundName, bool loop = false, Action callBack = null,
int customEventId = -1)
{
AudioManager.Instance.CheckAudioListener();
if (!Settings.IsSoundOn.Value) return null;
var soundPlayer = SafeObjectPool.Instance.Allocate();
soundPlayer.SetOnStartListener(player =>
{
player.SetVolume(Settings.SoundVolume.Value);
soundPlayer.SetOnStartListener(null);
});
soundPlayer.SetAudio(AudioManager.Instance.gameObject, soundName, loop);
soundPlayer.SetOnFinishListener(soundUnit =>
{
if (callBack != null)
{
callBack(soundUnit);
}
AudioManager.Instance.RemoveSoundPlayerFromPool(soundPlayer);
});
soundPlayer.customEventID = customEventId;
AudioManager.Instance.AddSoundPlayer2Pool(soundPlayer);
return soundPlayer;
}
public static void StopAllSound()
{
AudioManager.Instance.ForEachAllSound(player => player.Stop());
AudioManager.Instance.ClearAllPlayingSound();
}
#region 梅川内酷需求
public static void PlayMusic(AudioClip clip, bool loop = true, System.Action onBeganCallback = null,
System.Action onEndCallback = null, bool allowMusicOff = true, float volume = -1f)
{
AudioManager.Instance.CheckAudioListener();
var audioMgr = AudioManager.Instance;
audioMgr.CurrentMusicName = "music" + clip.GetHashCode();
if (!Settings.IsMusicOn.Value && allowMusicOff)
{
onBeganCallback?.Invoke();
onEndCallback?.Invoke();
return;
}
Debug.Log(">>>>>> Start Play Music");
// TODO: 需要按照这个顺序去 之后查一下原因
// 需要先注册事件,然后再play
MusicPlayer.SetOnStartListener(musicUnit =>
{
onBeganCallback?.Invoke();
if (volume < 0)
{
MusicPlayer.SetVolume(Settings.MusicVolume.Value);
}
else
{
MusicPlayer.SetVolume(volume);
}
// 调用完就置为null,否则应用层每注册一个而没有注销,都会调用
MusicPlayer.SetOnStartListener(null);
});
MusicPlayer.SetAudioExt(audioMgr.gameObject, clip, audioMgr.CurrentMusicName, loop);
MusicPlayer.SetOnFinishListener(musicUnit =>
{
onEndCallback?.Invoke();
// 调用完就置为null,否则应用层每注册一个而没有注销,都会调用
MusicPlayer.SetOnFinishListener(null);
});
}
public static void PlayVoice(AudioClip clip, bool loop = false, System.Action onBeganCallback = null,
System.Action onEndedCallback = null)
{
AudioManager.Instance.CheckAudioListener();
var audioMgr = AudioManager.Instance;
audioMgr.CurrentVoiceName = "voice" + clip.GetHashCode();
if (!Settings.IsVoiceOn.Value)
{
return;
}
VoicePlayer.SetOnStartListener(musicUnit =>
{
onBeganCallback?.Invoke();
VoicePlayer.SetOnStartListener(null);
});
VoicePlayer.SetAudioExt(AudioManager.Instance.gameObject, clip, audioMgr.CurrentVoiceName, loop);
VoicePlayer.SetOnFinishListener(musicUnit =>
{
onEndedCallback?.Invoke();
VoicePlayer.SetOnFinishListener(null);
});
}
public static AudioPlayer PlaySound(AudioClip clip, bool loop = false, Action callBack = null,
int customEventId = -1)
{
AudioManager.Instance.CheckAudioListener();
if (!Settings.IsSoundOn.Value) return null;
var soundPlayer = SafeObjectPool.Instance.Allocate();
soundPlayer.SetAudioExt(AudioManager.Instance.gameObject, clip,"sound" + clip.GetHashCode(), loop);
soundPlayer.SetVolume(Settings.SoundVolume.Value);
soundPlayer.SetOnFinishListener(soundUnit =>
{
if (callBack != null)
{
callBack(soundUnit);
}
AudioManager.Instance.RemoveSoundPlayerFromPool(soundPlayer);
});
soundPlayer.customEventID = customEventId;
AudioManager.Instance.AddSoundPlayer2Pool(soundPlayer);
return soundPlayer;
}
#endregion
}
public class AudioKitConfig
{
public IAudioLoaderPool AudioLoaderPool = new DefaultAudioLoaderPool();
}
public interface IAudioLoader
{
AudioClip Clip { get; }
AudioClip LoadClip(AudioSearchKeys audioSearchKeys);
void LoadClipAsync(AudioSearchKeys audioSearchKeys, Action onLoad);
void Unload();
}
public class AudioSearchKeys : IPoolType, IPoolable
{
public string AssetBundleName;
public string AssetName;
public void OnRecycled()
{
AssetBundleName = null;
AssetName = null;
}
public bool IsRecycled { get; set; }
public override string ToString()
{
return
$"AudioSearchKeys AssetName:{AssetName} AssetBundleName:{AssetBundleName}";
}
public static AudioSearchKeys Allocate()
{
return SafeObjectPool.Instance.Allocate();
}
public void Recycle2Cache()
{
SafeObjectPool.Instance.Recycle(this);
}
}
public interface IAudioLoaderPool
{
IAudioLoader AllocateLoader();
void RecycleLoader(IAudioLoader loader);
}
public abstract class AbstractAudioLoaderPool : IAudioLoaderPool
{
private Stack mPool = new Stack(16);
public IAudioLoader AllocateLoader()
{
return mPool.Count > 0 ? mPool.Pop() : CreateLoader();
}
protected abstract IAudioLoader CreateLoader();
public void RecycleLoader(IAudioLoader loader)
{
mPool.Push(loader);
}
}
public class DefaultAudioLoaderPool : AbstractAudioLoaderPool
{
protected override IAudioLoader CreateLoader()
{
return new DefaultAudioLoader();
}
}
public class DefaultAudioLoader : IAudioLoader
{
private AudioClip mClip;
public AudioClip Clip => mClip;
public AudioClip LoadClip(AudioSearchKeys panelSearchKeys)
{
mClip = Resources.Load(panelSearchKeys.AssetName);
return mClip;
}
public void LoadClipAsync(AudioSearchKeys audioSearchKeys, Action onLoad)
{
var resourceRequest = Resources.LoadAsync(audioSearchKeys.AssetName);
resourceRequest.completed += operation =>
{
var clip = resourceRequest.asset as AudioClip;
onLoad(clip, clip);
};
}
public void Unload()
{
Resources.UnloadAsset(mClip);
}
}
}