一、前言:
昨天我們完成了關鍵劇情抉擇與 PlayerStatsManager 數值連動後,我們的敘事框架已經具備了完整的遊戲性。但一個真正能打動玩家的文字冒險遊戲,除了畫面與文字,「聲音」 是營造沉浸感絕不可少的一部分!今天我們要為 StoryFlowManager 補上音效控制功能,實現段落音效播放、前音效強制切斷以及對話氛圍營造!
二、敘事遊戲中的音效控制需求
在對話系統中播放音效,不能只是單純地「播放聲音」,必須精準滿足以下幾種情境:
2.聲音重疊控制 (Stop All SFX):
三、音效控制程式實作:StorySceneManager.cs 音效模組
我們回顧並補全 StoryFlowManager.cs 裡專門處理聲音的核心結構:
1. 資料結構與 UI/Audio 宣告
在 DialogueSegment 中加上事件觸發的 bool 開關:
[System.Serializable]
public struct DialogueSegment {
public string speakerName;
[TextArea(1, 3)]
public string text;
[Header("角色顯示控制")]
public GameObject character1Object;
public bool showCharacter1;
public GameObject character2Object;
public bool showCharacter2;
[Header("音效事件 (在點擊推進到這一行時播放)")]
public bool playKnockSFX;
public bool playTenseSFX;
public bool playSirenSFX;
public bool stopAllSFX;
public bool stopBGM;
}
[Header("音效播放器與音源庫")]
public AudioSource sfxAudioSource;
public AudioSource bgmAudioSource;
public AudioClip knockDoorSFX;
public AudioClip tenseSFX;
public AudioClip sirenSFX;
2. 初始化與音效播放邏輯
在 Awake() 中進行安全備援,並新增 PlaySFX() 與 HandleAudioEvents() 處理方法:
void Awake() {
// 聲音播放器安全檢查
if (sfxAudioSource == null) {
sfxAudioSource = GetComponent<AudioSource>();
}
}
/// 處理當前段落觸發的音效事件
private void HandleAudioEvents(DialogueSegment segment) {
if (sfxAudioSource == null) return;
// 若勾選 Stop All SFX,先強制停止目前的音效
if (segment.stopAllSFX) {
sfxAudioSource.Stop();
}
// 若勾選 Stop BGM,停止背景音樂
if (segment.stopBGM && bgmAudioSource != null) {
bgmAudioSource.Stop();
}
// 依據勾選的事件觸發對應 AudioClip
if (segment.playKnockSFX && knockDoorSFX != null) {
sfxAudioSource.PlayOneShot(knockDoorSFX);
}
if (segment.playTenseSFX && tenseSFX != null) {
sfxAudioSource.PlayOneShot(tenseSFX);
}
if (segment.playSirenSFX && sirenSFX != null) {
sfxAudioSource.PlayOneShot(sirenSFX);
}
}
3. 對話播放循環鏈接音效
在 PlaySegments 走每句對話時,第一時間呼叫 HandleAudioEvents:
IEnumerator PlaySegments(DialogueSegment[] segments, bool isFinalSequence) {
if (continueButton != null) continueButton.interactable = true;
foreach (var segment in segments) {
// 1. 觸發當前對話段落的音效事件
HandleAudioEvents(segment);
// 2. 更新立繪與文字
UpdateCharacterPortrait(segment);
if (speakerText != null) speakerText.text = segment.speakerName.Replace("[NAME]", playerName);
if (dialogueText != null) dialogueText.text = segment.text.Replace("[NAME]", playerName);
isPaused = true;
yield return new WaitUntil(() => !isPaused);
}
}
四、Unity Inspector 實裝與欄位設定
設定對話音效時,只需在腳本 Inspector 或展開的 Dialogue Sequence 中設定:

圖一、設定對話音效(以第2幕的一小部分為例)
五、開發實戰經驗:PlayOneShot 與通道獨立管理
在 Unity 音效開發中,選擇 AudioSource.PlayOneShot() 的優勢如下:
六、今日成果與小結
今天是音效的創建,與先前劇情部分屬不同分支,記得修改並發布:
git status
git add .
git commit -m "feat: 重構 StorySceneManager 音效模組並實作 Stop All SFX 觸發機制"
git push origin refactor/audio-system