b6393449c9
修复FadeIn读取了FadeOut参数的问题。 增加Initial Delay功能。 重构AudioScheduler.ConfigureSource() -> SetupSource(), RegisterActiveSound(), StartPlayBack()。 移动长音频相关功能至LongAudio文件夹。
143 lines
5.6 KiB
C#
143 lines
5.6 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
namespace OCES.Audio
|
||
{
|
||
/// <summary>
|
||
/// 维护当前激活的游戏状态,在状态变化时全量匹配 Path 表,返回应当播放的 ContainerId。
|
||
/// </summary>
|
||
public class MusicStateRouter
|
||
{
|
||
// key: StateGroup enum Type,value: 当前激活的 enum 整数值
|
||
readonly Dictionary<Type, int> m_activeStates = new();
|
||
|
||
readonly MusicPathConfig m_musicPaths;
|
||
readonly AmbiencePathConfig m_ambiencePaths;
|
||
|
||
// 上一次匹配到的 PathId,用于 Transition 表的 FromPathId 查询
|
||
public uint LastMusicPathId { get; private set; }
|
||
public uint LastAmbiencePathId { get; private set; }
|
||
|
||
public MusicStateRouter(MusicPathConfig musicPaths, AmbiencePathConfig ambiencePaths)
|
||
{
|
||
this.m_musicPaths = musicPaths;
|
||
this.m_ambiencePaths = ambiencePaths;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新某个 StateGroup 的当前值,并重新全量匹配两张 Path 表。
|
||
/// </summary>
|
||
public void SetState<TEnum>(TEnum state, out uint musicContainerId, out uint ambienceContainerId)
|
||
where TEnum : Enum
|
||
{
|
||
// Dictionary<Type, int> 天然保证同一 StateGroup 只保留最新值,直接覆盖即可
|
||
this.m_activeStates[typeof(TEnum)] = Convert.ToInt32(state);
|
||
|
||
musicContainerId = MatchBestPath(this.m_musicPaths.MusicPathList(), out uint musicPathId);
|
||
ambienceContainerId = MatchBestPath(this.m_ambiencePaths.AmbiencePathList(), out uint ambiencePathId);
|
||
|
||
LastMusicPathId = musicPathId;
|
||
LastAmbiencePathId = ambiencePathId;
|
||
|
||
#if UNITY_EDITOR
|
||
Editor.DebugInfoCollector.Instance.ActiveStates = this.m_activeStates;
|
||
#endif
|
||
}
|
||
|
||
// ─────────────────────────────────────────────
|
||
// 内部匹配逻辑
|
||
// ─────────────────────────────────────────────
|
||
|
||
/// <summary>
|
||
/// 遍历路径列表,找到所有满足当前状态的规则,返回 priority 最小(最高优先级)的那条的 ContainerId。
|
||
/// </summary>
|
||
uint MatchBestPath<T>(List<T> paths, out uint matchedPathId) where T : IPathEntry
|
||
{
|
||
IPathEntry best = null;
|
||
foreach (T path in paths)
|
||
{
|
||
if (PathMatches(path.Path) && (best == null || path.Priority < best.Priority))
|
||
best = path;
|
||
}
|
||
|
||
if (best != null)
|
||
{
|
||
matchedPathId = best.Id;
|
||
return best.ContainerId;
|
||
}
|
||
|
||
matchedPathId = 0;
|
||
return 0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 解析 path 字符串,判断当前激活状态是否满足该条规则。
|
||
/// 格式:TypeID1,子状态|TypeID2,子状态……
|
||
/// 规则中的每一个条件都必须满足(AND 关系)。
|
||
/// </summary>
|
||
bool PathMatches(string pathStr)
|
||
{
|
||
if (string.IsNullOrEmpty(pathStr))
|
||
return true; // 空 path 视为无条件匹配(默认兜底规则)
|
||
|
||
string[] conditions = pathStr.Split('|');
|
||
foreach (string condition in conditions)
|
||
{
|
||
string[] parts = condition.Split(',');
|
||
if (parts.Length != 2)
|
||
{
|
||
Debug.LogWarning($"[MusicStateRouter] Path格式错误: '{condition}'");
|
||
return false;
|
||
}
|
||
|
||
if (!int.TryParse(parts[0].Trim(), out int typeId) ||
|
||
!int.TryParse(parts[1].Trim(), out int stateValue))
|
||
{
|
||
Debug.LogWarning($"[MusicStateRouter] Path解析失败: '{condition}'");
|
||
return false;
|
||
}
|
||
|
||
bool conditionMet = false;
|
||
foreach (KeyValuePair<Type, int> kv in this.m_activeStates)
|
||
{
|
||
if (StateGroupRegistry.GetTypeId(kv.Key) != typeId || kv.Value != stateValue)
|
||
continue;
|
||
conditionMet = true;
|
||
break;
|
||
}
|
||
|
||
if (!conditionMet)
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
}
|
||
|
||
// ─────────────────────────────────────────────
|
||
// StateGroup 注册表:将 enum Type 映射为策划表中填写的 TypeId 整数
|
||
// ─────────────────────────────────────────────
|
||
|
||
/// <summary>
|
||
/// 程序员在此注册所有 StateGroup enum 与其对应 TypeId 的映射关系。
|
||
/// 策划在 MusicPath.path 字段中填写的 TypeId 数字必须与此处一致。
|
||
/// </summary>
|
||
public static class StateGroupRegistry
|
||
{
|
||
static readonly Dictionary<Type, int> s_typeIdMap = new();
|
||
|
||
public static void Register<TEnum>(int typeId) where TEnum : Enum
|
||
{
|
||
s_typeIdMap[typeof(TEnum)] = typeId;
|
||
}
|
||
|
||
public static int GetTypeId(Type enumType)
|
||
{
|
||
if (s_typeIdMap.TryGetValue(enumType, out int id))
|
||
return id;
|
||
Debug.LogWarning($"[StateGroupRegistry] 未注册的StateGroup类型: {enumType.Name},请调用StateGroupRegistry.Register<T>()");
|
||
return -1;
|
||
}
|
||
}
|
||
} |