2025-05-28 21:52:46 +08:00

185 lines
5.4 KiB
C#

/*
* @Author: 白哉
* @Description:
* @Date: 2025年05月22日 星期四 14:05:32
* @Modify:
*/
using System.Collections.Generic;
using UnityEngine;
namespace Logic.Audio
{
public class AudioManager
{
public static AudioManager Instance = new AudioManager();
private AudioPlayer _musicPlayer;
private List<AudioPlayer> _allPlayer;
private Dictionary<string, AudioClip> _clips;
private GameObject AudioRoot;
public void Init()
{
_allPlayer = new List<AudioPlayer>();
_clips = new Dictionary<string, AudioClip>();
_clips["Main"] = Resources.Load<AudioClip>("Audio/Main");
_clips["RemiliaEgyptian"] = Resources.Load<AudioClip>("Audio/RemiliaEgyptian");
_clips["SatoriIndian"] = Resources.Load<AudioClip>("Audio/SatoriIndian");
_clips["KanakoGermany"] = Resources.Load<AudioClip>("Audio/KanakoGermany");
_clips["KaguyaFrench"] = Resources.Load<AudioClip>("Audio/KaguyaFrench");
if (!AudioRoot) AudioRoot = new GameObject();
AudioRoot.name = "AudioRoot";
var cfg = Object.FindObjectOfType<AudioClipConfig>();
if (cfg != null) foreach (var clip in cfg.Clips) _clips[clip.name] = clip;
}
public void Update()
{
foreach (var player in _allPlayer) player.Update();
}
public void PlayMusic(string musicName, float fadeIn, float fadeOut, bool isLoop)
{
if (!_clips.ContainsKey(musicName)) return;
if (_musicPlayer != null && _musicPlayer.State == PlayerState.Playing) _musicPlayer.Stop();
_musicPlayer = GetPlayer();
_musicPlayer.Clip = _clips[musicName];
_musicPlayer.IsLoop = isLoop;
_musicPlayer.Length = _clips[musicName].length;
_musicPlayer.FadeInDuration = fadeIn;
_musicPlayer.FadeOutDuration = fadeOut;
_musicPlayer.Play();
}
public void StopMusic()
{
_musicPlayer?.Stop();
}
public void PlayAudio(string musicName, float fadeIn, float fadeOut, bool isLoop)
{
if (!_clips.ContainsKey(musicName)) return;
var player = GetPlayer();
player.Clip = _clips[musicName];
player.IsLoop = isLoop;
player.Length = _clips[musicName].length;
player.FadeInDuration = fadeIn;
player.FadeOutDuration = fadeOut;
player.Play();
}
private AudioPlayer GetPlayer()
{
foreach (var player in _allPlayer)
{
if (player.State == PlayerState.Finished || player.State == PlayerState.Prepare) return player;
}
var sourceObj = new GameObject();
sourceObj.transform.SetParent(AudioRoot.transform);
var source = sourceObj.AddComponent<AudioSource>();
var newPlayer = new AudioPlayer(source);
_allPlayer.Add(newPlayer);
return newPlayer;
}
}
public enum PlayerState
{
Prepare,
FadeIn,
FadeOut,
Playing,
Finished,
}
public class AudioPlayer
{
public AudioSource Source;
public AudioClip Clip;
public bool IsLoop;
public float Length;
public float FadeInDuration;
public float FadeOutDuration;
public float StartTime;
public float EndTime;
public PlayerState State;
public AudioPlayer(AudioSource source)
{
Source = source;
State = PlayerState.Prepare;
}
public void Play()
{
StartTime = Time.time;
Source.clip = Clip;
Source.volume = 0;
Source.loop = IsLoop;
Source.Play();
State = PlayerState.FadeIn;
}
public void Update()
{
if (Source == null || !Source.isPlaying) return;
UpdateSourceVolume();
}
public void Stop()
{
State = PlayerState.FadeOut;
EndTime = Time.time;
}
private void UpdateSourceVolume()
{
if (State == PlayerState.Finished || State == PlayerState.Prepare) return;
if (State == PlayerState.FadeIn)
{
if (Time.time - StartTime < FadeInDuration)
{
Source.volume = (Time.time - StartTime) / FadeInDuration;
}
else
{
Source.volume = 1;
State = PlayerState.Playing;
}
}
if (State == PlayerState.Playing && !IsLoop)
{
if (Time.time - StartTime >= Length - FadeOutDuration)
{
EndTime = Time.time;
State = PlayerState.FadeOut;
}
}
if (State == PlayerState.FadeOut)
{
if (Time.time - EndTime >= FadeOutDuration)
{
Source.volume = 0;
Source.Stop();
State = PlayerState.Finished;
}
else
{
Source.volume = (FadeOutDuration - Time.time + EndTime) / FadeOutDuration;
}
}
}
}
}