Add system using guide.
This commit is contained in:
@@ -0,0 +1,224 @@
|
|||||||
|
# AudioSystem 使用说明
|
||||||
|
|
||||||
|
## 播放音效
|
||||||
|
|
||||||
|
### 基本播放
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 通过 uint audioID 播放(推荐)
|
||||||
|
AudioSystem.Instance.Play(Cues.Play_sfx_ui_button_common);
|
||||||
|
|
||||||
|
// 通过 int 播放(便捷重载,内部转为 uint)
|
||||||
|
AudioSystem.Instance.Play(3);
|
||||||
|
|
||||||
|
// 带回调的播放(音频启动后回调)
|
||||||
|
AudioSystem.Instance.Play(Cues.Play_sfx_ui_button_common, () => Debug.Log("音效开始播放"));
|
||||||
|
```
|
||||||
|
|
||||||
|
`OCES.Audio.Cues` 类提供所有可用 audioID 常量,例如 `Cues.Play_sfx_ui_button_common`。通过代码补全即可快速访问全部已注册音效。
|
||||||
|
|
||||||
|
### 通过字符串播放(已废弃)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
[Obsolete("Use Play(uint) instead")]
|
||||||
|
AudioSystem.Instance.Play("sfx_ui_button_common");
|
||||||
|
```
|
||||||
|
|
||||||
|
字符串接口仅用于向后兼容。同名或容器内共享 ID 的资源会产生歧义,请始终使用 `uint` ID。
|
||||||
|
|
||||||
|
### 直接传入 AudioObject 播放
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
AudioObject obj = /* 从某处获取 */;
|
||||||
|
AudioSystem.Instance.Play(obj, () => Debug.Log("播放完毕"));
|
||||||
|
```
|
||||||
|
|
||||||
|
Switch 类型的 Container 会自动解析当前状态对应的子节点。
|
||||||
|
|
||||||
|
### 在拍子/小节/网格上播放
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// CallbackFlags 可选值: MusicSyncBeat | MusicSyncBar | MusicSyncGrid
|
||||||
|
AudioSystem.Instance.PlayOnTrigger(Cues.Play_Beat, CallbackFlags.MusicSyncBeat);
|
||||||
|
```
|
||||||
|
|
||||||
|
音效会等到下一次对应节拍回调时播放。如果 `audioId` 本身也是同步回调的 Container(Beat/Bar/Grid),该音效会被忽略,避免自触发循环。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 停止音效
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
AudioSystem.Instance.Stop(audioId);
|
||||||
|
```
|
||||||
|
|
||||||
|
停止指定 audioID 的所有正在播放的活跃实例。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 修改游戏状态(驱动音乐/环境音)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 泛型接口,支持任意已注册的枚举类型
|
||||||
|
AudioSystem.Instance.SetState(Parameters.GameState.Game);
|
||||||
|
AudioSystem.Instance.SetState(MyCustomEnum.SomeState); // 需先通过 StateGroupRegistry 注册
|
||||||
|
```
|
||||||
|
|
||||||
|
`SetState` 内部触发 `MusicStateRouter` 全量匹配,根据 `MusicPath` / `AmbiencePath` 表格切换到对应的音乐与环境音 Container。
|
||||||
|
|
||||||
|
### 启动时的默认状态
|
||||||
|
|
||||||
|
- 在 Inspector 设置 `startWithMusic = true` 并指定 `startMusicWith`(GameState 枚举值),`AudioSystem.Start()` 会自动调用 `SetState`。
|
||||||
|
- 游戏启动时的首次状态设置**必须放在 `Start` 内**,晚一点可以,早了容易出问题。
|
||||||
|
- 若需在其他位置进行首次初始化,请注释掉 `AudioSystem.Start()` 中的相关代码。
|
||||||
|
|
||||||
|
### Inspector 参数
|
||||||
|
|
||||||
|
| 字段 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `startWithMusic` | 是否在 Start 时自动设置初始状态 |
|
||||||
|
| `startMusicWith` | 初始 GameState 值 |
|
||||||
|
| `logLevel` | 控制台日志级别(`Off` / `Log` / `Warning` / `Error`) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 音乐同步回调
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 订阅节拍回调(参数为当前正在播放的 ContainerId)
|
||||||
|
AudioSystem.Instance.OnBeat += containerId => { };
|
||||||
|
AudioSystem.Instance.OnBar += containerId => { };
|
||||||
|
AudioSystem.Instance.OnGrid += containerId => { };
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Beat**:每拍触发
|
||||||
|
- **Bar**:每小节触发(根据 `MusicContainer.TimeSig` 计算)
|
||||||
|
- **Grid**:每 N 小节触发(根据 `MusicContainer.Grid` 字段)
|
||||||
|
|
||||||
|
Blend Container 内如果有多个不同 BPM 的子段,回调会自动禁用。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 获取当前活跃状态
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
IReadOnlyDictionary<Type, Enum> states = AudioSystem.Instance.ActiveStates;
|
||||||
|
```
|
||||||
|
|
||||||
|
返回 `SetState` 设置的所有枚举类型及其当前值。可用于 Switch Container 的运行时状态查询。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 设置高切(Lowpass Filter)
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
AudioSystem.Instance.SetLowpass(true); // 启用高切(440Hz)
|
||||||
|
AudioSystem.Instance.SetLowpass(false); // 恢复正常(22000Hz)
|
||||||
|
```
|
||||||
|
|
||||||
|
在需要凸显某个音效时,调用 `SetLowpass(true)` 将其它声音"放远"。切换过程中有平滑 Tween(时长由 `AudioExtendSettings.lowpassTweenDuration` 控制)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 修改音效播放属性
|
||||||
|
|
||||||
|
### 音量
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 设置音量 (0.0 ~ 1.0)
|
||||||
|
AudioSystem.Instance.SetVolume(audioId, 0.5f);
|
||||||
|
// int 重载
|
||||||
|
AudioSystem.Instance.SetVolume(3, 0.8f);
|
||||||
|
|
||||||
|
// 重置为默认值
|
||||||
|
AudioSystem.Instance.ResetVolume(audioId);
|
||||||
|
```
|
||||||
|
|
||||||
|
`SetVolume` 会实时修改指定 audioID 的**所有活跃实例**的音量。超出 `[0, 1]` 范围会打印 Warning 并忽略。
|
||||||
|
|
||||||
|
### 音高
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 设置音高 (-3.0 ~ 3.0,1.0 为正常音高)
|
||||||
|
AudioSystem.Instance.SetPitch(audioId, 1.5f);
|
||||||
|
// int 重载
|
||||||
|
AudioSystem.Instance.SetPitch(3, 0.8f);
|
||||||
|
|
||||||
|
// 重置为默认值
|
||||||
|
AudioSystem.Instance.ResetPitch(audioId);
|
||||||
|
```
|
||||||
|
|
||||||
|
`SetPitch` 会实时修改指定 audioID 的**所有活跃实例**的音高。**
|
||||||
|
|
||||||
|
**注意**:`LoadType` 为 `Streaming` 的 AudioClip **不支持将 Pitch 设置为负值**。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 触感反馈(HapticSystem)
|
||||||
|
|
||||||
|
触感系统由音效系统自动驱动(`AudioObject.Haptic` 配置不为空时自动触发)。手动调用仅用于调试:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 手动触发触感(调试用,会打印 Warning)
|
||||||
|
HapticSystem.Instance.Play(hapticId);
|
||||||
|
|
||||||
|
// 停止当前触感
|
||||||
|
HapticSystem.Instance.Stop();
|
||||||
|
```
|
||||||
|
|
||||||
|
四种触感类型:`Preset`、`Emphasis`、`Constant`、`Advance`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MonoBehaviour 辅助组件
|
||||||
|
|
||||||
|
### PlaySoundBind
|
||||||
|
|
||||||
|
绑定 UI 事件以播放/停止/节拍触发音效:
|
||||||
|
|
||||||
|
- `PlaySound()` — 播放 `InputField` 中的 audioID
|
||||||
|
- `StopSound()` — 停止 `InputField` 中的 audioID
|
||||||
|
- `PlaySoundOnTrigger()` — 在节拍/小节/网格上播放(通过 `callbackFlags` 选择回调类型)
|
||||||
|
- Inspector 字段:`inputField`(InputField 引用)、`callbackFlags`(CallbackFlags)
|
||||||
|
|
||||||
|
### SetStateBind
|
||||||
|
|
||||||
|
绑定按钮以切换游戏状态:
|
||||||
|
|
||||||
|
- `OnButtonPressed()` — 调用 `SetState(targetGameState)` + `SetLowpass(enableLowpass)`
|
||||||
|
- Inspector 字段:`targetGameState`(Parameters.GameState)、`enableLowpass`(bool)、`buttonText`(Text 引用,自动替换占位符)
|
||||||
|
|
||||||
|
### SetPropertyBind
|
||||||
|
|
||||||
|
绑定 UI 事件以修改音效属性:
|
||||||
|
|
||||||
|
- `SetVolume()` — 设置音量
|
||||||
|
- `SetPitch()` — 设置音高
|
||||||
|
- `ResetVolume()` — 重置音量
|
||||||
|
- `ResetPitch()` — 重置音高
|
||||||
|
- Inspector 字段:`inputField`(InputField 引用,填写 audioID)、`targetValue`(float,目标值)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 添加新的状态枚举
|
||||||
|
|
||||||
|
如果你的游戏需要自定义状态枚举(除 `Parameters.GameState` 外),需要:
|
||||||
|
|
||||||
|
1. 在 Excel 表格中配置对应的 `MusicPath` / `AmbiencePath` 条目,指定 `TypeId`
|
||||||
|
2. 在代码中注册:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
StateGroupRegistry.Register<MyCustomEnum>(typeId);
|
||||||
|
```
|
||||||
|
|
||||||
|
`Parameters.EnumIds.RegisterAllGameState()` 在 `AudioSystem.Awake()` 中自动调用,已注册默认的 `GameState`(TypeId=1)。自定义枚举的注册请在 `Awake` 或更早时机完成。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常见注意事项
|
||||||
|
|
||||||
|
1. **始终使用 uint ID 播放**:字符串接口已废弃,Container 内共享 ID 的 AudioClip 只能通过 ID 精确访问。
|
||||||
|
2. **Streaming 音频不支持负 Pitch**:`SetPitch` 传入负值时 Streaming 剪辑无声。
|
||||||
|
3. **首次 SetState 放在 Start 里**:晚一点没问题,放在 `Awake` 中可能因初始化未完成而出错。
|
||||||
|
4. **Switch Container 依赖 ActiveStates**:确保在播放 Switch 类型 AudioObject 之前已调用 `SetState` 设置所需状态。
|
||||||
|
5. **Blend Container 内 BPM 不一致**:会导致 Beat/Bar/Grid 回调自动禁用。
|
||||||
Reference in New Issue
Block a user