iT邦幫忙

2026 iThome 鐵人賽

DAY 10
0
Vibe Coding

從課堂半成品到完整發布:獨立遊戲的30天重生記系列 第 10

【DAY10】Unity 2D 敘事遊戲開發: Unity 2D 敘事遊戲開發:對話音效事件與氛圍切斷控制 (Audio Events & Stop All SFX)

  • 分享至 

  • xImage
  •  

一、前言:
昨天我們完成了關鍵劇情抉擇與 PlayerStatsManager 數值連動後,我們的敘事框架已經具備了完整的遊戲性。但一個真正能打動玩家的文字冒險遊戲,除了畫面與文字,「聲音」 是營造沉浸感絕不可少的一部分!今天我們要為 StoryFlowManager 補上音效控制功能,實現段落音效播放、前音效強制切斷以及對話氛圍營造!

二、敘事遊戲中的音效控制需求
在對話系統中播放音效,不能只是單純地「播放聲音」,必須精準滿足以下幾種情境:

  1. 音效事件觸發 (Audio Events):
  • 當對話推進到特定段落時,可直接勾選對應的音效開關(如敲門聲 Knock、緊張音效 Tense、警報聲 Siren),讓程式自動播送特定的 AudioClip。

2.聲音重疊控制 (Stop All SFX):

  • 某些關鍵音效(如:緊張的警告聲或長音效)需要立刻中斷上一次還沒播完的聲音,避免多重音效堆疊造成聽覺混亂。
  1. 組件自動備援機制:
  • 如果 Inspector 忘記手動拖曳 AudioSource,程式應能自動透過 GetComponent() 進行自我修復,提升系統穩定度。

三、音效控制程式實作: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 中設定:

  1. 指定音源庫 (AudioClip):H把專案中的音效檔分別拉入 Knock Door SFX、Tense SFX 與 Siren SFX 欄位作為音源庫備用。
  2. 勾選觸發開關:展開特定的劇情段落(例如第 2 幕),直接勾選對應的音效開關(如 Play Knock SFX)。若希望發聲前清空之前的殘音,直接勾選 Stop All SFX 即可。

https://ithelp.ithome.com.tw/upload/images/20260917/20184073Du3obiKmUc.png
圖一、設定對話音效(以第2幕的一小部分為例)

五、開發實戰經驗:PlayOneShot 與通道獨立管理
在 Unity 音效開發中,選擇 AudioSource.PlayOneShot() 的優勢如下:

  1. 支援快速連續點擊: 玩家快速點擊推進對話時,PlayOneShot 可以重疊播放短音效,不會因為前一次播到一半而被截斷。
  2. 獨立頻道隔離: Stop All SFX 會中斷該 AudioSource 上播放的所有聲音。建議將 BGM 與 SFX 的 AudioSource 物件拆開管理(如 Inspector 上的 Sfx Audio Source 與 Bgm Audio Source),避免切斷音效時誤切背景音樂。

六、今日成果與小結

  • 對話音效開關綁定: 完成了 DialogueSegment 音效事件開關與 HandleAudioEvents() 邏輯。
  • 動態切斷機制: 實現 stopAllSFX 與 stopBGM,避免聽覺雜亂與殘音問題。
  • 音效播放器防呆: 實裝 sfxAudioSource 在 Awake() 中的自動取得與備援機制。

範例影片:Yes

今天是音效的創建,與先前劇情部分屬不同分支,記得修改並發布:

  1. 檢查修改狀態

git status

  1. 加入暫存區並提交 Commit

git add .

git commit -m "feat: 重構 StorySceneManager 音效模組並實作 Stop All SFX 觸發機制"

  1. 推送到遠端開發分支

git push origin refactor/audio-system


上一篇
【DAY9】Unity 2D 敘事遊戲開發:對話系統 (2) — 關鍵劇情分歧與數值連動
下一篇
【DAY11】Unity 2D 敘事遊戲開發: Unity 2D 敘事遊戲開發:跨場景資料持久化 — PlayerStatsManager 單例與 DontDestroyOnLoad 狀態同步
系列文
從課堂半成品到完整發布:獨立遊戲的30天重生記17
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言