初学者,自用笔记
单例父类模板
by B站 超级依薇尔
//让单例早于awake被创建并调用
//并且不用手动创建一个空对象来装载Manager
public class TheManager<T> : MonoBehaviour where T : MonoBehaviour
{
// 单例实例
public static T Instance
{
get
{
// 若实例为空,在场景中查找
if (_instance == null)
{
_instance = Object.FindAnyObjectByType<T>();
//_instance = Object.FindAnyObjectByType<T>();
// 若场景中未找到实例
if (_instance == null)
{
Debug.Log($"单例模式 {typeof(T).Name} 场景中不存在,尝试创建...");
// 查找带有 "Manager" 标签的游戏对象
GameObject target = GameObject.FindGameObjectWithTag("Manager");
if (target == null)
{
// 若未找到,创建一个新的游戏对象
target = new GameObject();
target.name = $"单例模式管理器 {typeof(T).Name}";
}
try
{
// 尝试在目标游戏对象上添加组件
_instance = target.AddComponent<T>();
}
catch (System.Exception e)
{
// 处理添加组件失败的情况
Debug.LogError($"创建单例 {typeof(T).Name} 失败: {e.Message}");
}
}
}
return _instance;
}
set
{
// 若实例为空,将传入的值赋给实例
if (_instance == null)
{
_instance = value;
}
}
}
// 静态实例变量
private static T _instance;
private void Awake()
{
// 若实例为空,将当前对象赋值给实例
if (_instance == null)
{
_instance = this as T;
// 标记该对象在场景切换时不被销毁
DontDestroyOnLoad(_instance.gameObject);
}
else
{
// 若实例已存在,销毁当前对象
if (this != _instance)
{
Destroy(gameObject);
}
}
}
}
//用例public class GameManager : Singleton<GameManager>
//调用为Manager.Instance,子类无需再次初始化
MusicManager模板
将音频文件存储在Resources文件夹中
using UnityEngine;
using Manager;
using System.Collections.Generic;
public class MusicManager : _Manager<MusicManager>
{
[SerializeField] private AudioSource musicSource; // 背景音乐源
private Dictionary<string, AudioSource> audioSources = new Dictionary<string, AudioSource>();
private Dictionary<string, AudioClip> audioClips = new Dictionary<string, AudioClip>();
//音频路径文件为 public const string BGM_MAIN = "Audio/Music/bgm_main";格式
private void Awake()
{
if (musicSource == null)
{
musicSource = gameObject.AddComponent<AudioSource>();
musicSource.loop = true;
}
}
void Start()
{
}
void Update()
{
}
public AudioClip LoadAudio(string path)//加载音频
{
return (AudioClip)Resources.Load(path);
}
public AudioClip GetAudio(string path)//获取音频资源,避免重复加载
{
if (!audioClips.ContainsKey(path))
{
audioClips[path] = LoadAudio(path);
}
return audioClips[path];
}
public void PlayMainMusic(string path, float volume = 1.0f, bool loop = true)//播放背景音乐
{
AudioClip clip = GetAudio(path);
if (clip == null) return;
musicSource.clip = clip;
musicSource.volume = volume;
musicSource.loop = loop;
musicSource.Play();
}
public void StopMainMusic()
{
musicSource.Stop();
}
public void SetMainMusicVolume(float volume)
{
musicSource.volume = volume;
}
public void PlaySFX(string path, float volume = 1.0f)//playoneshot可以叠加播放,用于音效交叉混合效果
{
this.musicSource.PlayOneShot(GetAudio(path), volume);
}
public AudioSource GetAudioSource(string name,bool loop = true)// 动态获取指定名称的AudioSource
{
if (!audioSources.TryGetValue(name, out AudioSource source))
{
GameObject audioObject = new GameObject($"AudioSource_{name}");
audioObject.transform.SetParent(transform);
source = audioObject.AddComponent<AudioSource>();
source.loop = loop;
audioSources[name] = source;
}
return source;
}
public void PlayAudio(string name, string path, float volume = 1.0f, bool loop = true)// 播放独立命名的音频
{
AudioClip clip = GetAudio(path);
if (clip == null) return;
AudioSource source = GetAudioSource(name, loop);
source.clip = clip;
source.volume = volume;
source.loop = loop;
source.Play();
}
public void StopAudio(string name)// 停止指定音频
{
if (audioSources.TryGetValue(name, out AudioSource source))
{
source.Stop();
}
}
public void SetAudioVolume(string name, float valume = 0f)//设置指定音频音量
{
if (audioSources.TryGetValue(name, out AudioSource source))
{
source.volume = valume;
}
}
public void RemoveAudioSource(string name)//删除不再需要的音频
{
if (audioSources.TryGetValue(name, out AudioSource source))
{
source.Stop(); // 停止播放
Destroy(source.gameObject); // 销毁游戏对象
audioSources.Remove(name); // 从字典中移除
}
}
// 清理所有非保留音频源
public void CleanupAudioSources(List<string> exceptions = null)//exceptions为需要保留的音频
{
List<string> sourcesToRemove = new List<string>();
foreach (var pair in audioSources)
{
// 保留例外列表中的音频
if (exceptions != null && exceptions.Contains(pair.Key))
continue;
sourcesToRemove.Add(pair.Key);
}
foreach (string name in sourcesToRemove)
{
RemoveAudioSource(name);
}
}
}