Files
MedievalShopkeeper/Assets/Scripts/AudioManager.cs

170 lines
5.5 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MedievalShopkeeper
{
public class AudioManager : MonoBehaviour
{
public static AudioManager Instance { get; private set; }
[Header("Audio Sources")]
[Tooltip("Source for background music.")]
[SerializeField] private AudioSource bgmSource;
[Tooltip("Source for sound effects.")]
[SerializeField] private AudioSource sfxSource;
[Header("Playlists")]
[Tooltip("Music tracks played during the day (08:00 - 20:00).")]
[SerializeField] private List<AudioClip> dayPlaylist;
[Tooltip("Music tracks played during the night (20:00 - 08:00).")]
[SerializeField] private List<AudioClip> nightPlaylist;
[Tooltip("Music played when a Shoplifter or Raider is active in the shop!")]
[SerializeField] private AudioClip actionMusic;
[Header("Sound Effects")]
[SerializeField] private AudioClip saleSFX;
[SerializeField] private AudioClip buyStockSFX;
[SerializeField] private AudioClip buildSFX;
[SerializeField] private AudioClip destroySFX;
[SerializeField] private AudioClip repairSFX;
[SerializeField] private AudioClip alertSFX;
private int activeThreats = 0;
private bool isNightTime = false;
// Track the current index in each playlist
private int currentDayTrack = 0;
private int currentNightTrack = 0;
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
}
private void Start()
{
if (bgmSource == null) bgmSource = gameObject.AddComponent<AudioSource>();
if (sfxSource == null) sfxSource = gameObject.AddComponent<AudioSource>();
bgmSource.loop = false;
if (GameManager.Instance != null)
{
// Hook into GameManager events
GameManager.Instance.OnTimeChanged += CheckDayNight;
GameManager.Instance.OnRandomEventTriggered += (e) => PlayAlert();
// Initialize state
isNightTime = (GameManager.Instance.CurrentHour >= 20 || GameManager.Instance.CurrentHour < 8);
}
PlayNextBGM();
}
private void Update()
{
// Automatically play the next track if the current one finishes (and we aren't looping action music)
if (bgmSource != null && !bgmSource.isPlaying && bgmSource.clip != null && activeThreats == 0)
{
PlayNextBGM();
}
}
private void CheckDayNight(int hour, int minute)
{
bool isNowNight = (hour >= 20 || hour < 8);
if (isNowNight != isNightTime)
{
isNightTime = isNowNight;
// Only swap music immediately if we aren't currently in combat/raid mode
if (activeThreats == 0)
{
PlayNextBGM();
}
}
}
public void AddThreat()
{
activeThreats++;
if (activeThreats == 1) // Switched from 0 to 1
{
PlayActionMusic();
}
}
public void RemoveThreat()
{
activeThreats = Mathf.Max(0, activeThreats - 1);
if (activeThreats == 0)
{
// The threat is over, return to normal playlist
PlayNextBGM();
}
}
private void PlayActionMusic()
{
if (actionMusic == null || bgmSource == null) return;
bgmSource.Stop();
bgmSource.clip = actionMusic;
bgmSource.loop = true; // Action music loops continuously until the threat is gone
bgmSource.Play();
}
private void PlayNextBGM()
{
if (bgmSource == null) return;
bgmSource.loop = false;
bgmSource.Stop();
List<AudioClip> activePlaylist = isNightTime ? nightPlaylist : dayPlaylist;
if (activePlaylist == null || activePlaylist.Count == 0) return;
// Choose the correct index based on time of day
if (isNightTime)
{
if (currentNightTrack >= activePlaylist.Count) currentNightTrack = 0;
bgmSource.clip = activePlaylist[currentNightTrack];
currentNightTrack++;
}
else
{
if (currentDayTrack >= activePlaylist.Count) currentDayTrack = 0;
bgmSource.clip = activePlaylist[currentDayTrack];
currentDayTrack++;
}
bgmSource.Play();
}
// --- SFX Triggers ---
public void PlaySale() => PlaySFX(saleSFX);
public void PlayBuyStock() => PlaySFX(buyStockSFX);
public void PlayBuild() => PlaySFX(buildSFX);
public void PlayDestroy() => PlaySFX(destroySFX);
public void PlayRepair() => PlaySFX(repairSFX);
public void PlayAlert() => PlaySFX(alertSFX);
private void PlaySFX(AudioClip clip)
{
if (clip != null && sfxSource != null)
{
sfxSource.PlayOneShot(clip);
}
}
}
}