iT邦幫忙

2026 iThome 鐵人賽

DAY 8
0
Vibe Coding

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

【DAY8】Unity 2D 敘事遊戲開發:對話系統 (1) — StoryFlowManager 劇情對話與人物立繪切換

  • 分享至 

  • xImage
  •  

一、前言:
昨天我們完成了角色立繪與 UI 對話框的靜態舞台佈局後,今天我們要正式為對話框注入靈魂——對話流程控制、文字動態印出與人物立繪切換
在 2D 敘事/文字冒險遊戲中,對話進行時「誰在說話」、「說了什麼」以及對應的角色立繪(Sprite)切換,是視覺呈現的核心。今天就來揭密我們專案中掛載於 ChoiceManager 物件上的關鍵腳本 —— StoryFlowManager.cs!

二、對話系統的核心架構需求
在我們的專案中,一個標準的對話顯示流程需要滿足以下條件:
1. 結構化對話資料(DialogueSegment):

  • speakerName:發言者姓名(支援 [NAME] 玩家名字動態替換)。
  • text:對話內容。
  • showCharacter & characterSprite:控制該句對話是否顯示人物立繪,以及對應的角色圖片。

2. UI 綁定與立繪切換:

  • speakerText / dialogueText:TextMeshPro 文字組件。
  • characterDisplayImage:畫面上負責渲染角色立繪的 Image 組件。

3. Coroutine 協程推進機制:

  • 使用 IEnumerator 搭配 yield return new WaitUntil(() => !isPaused) 暫停流程,直到玩家按下全螢幕 continueButton 才推進至下一句。

三、核心對話控制器實作:StoryFlowManager.cs
這是專案的核心對話控制腳本基礎架構,保留了良好的擴充介面,方便後續疊加音效與互動鎖定功能:

using UnityEngine;
using System.Collections;
using TMPro;
using UnityEngine.UI; 

public class StoryFlowManager : MonoBehaviour 
{
    [System.Serializable]
    public struct DialogueSegment {
        public string speakerName;
        [TextArea(1, 3)] public string text;
        public bool showCharacter;     
        public Sprite characterSprite; 
    }

    [Header("UI 與劇情設定")]
    [SerializeField] private string playerName = "訪客";
    [SerializeField] private TextMeshProUGUI speakerText; 
    [SerializeField] private TextMeshProUGUI dialogueText; 
    [SerializeField] private Image characterDisplayImage; 
    [SerializeField] private Button continueButton; 
    [SerializeField] private DialogueSegment[] preChoiceSegments; 
    
    private bool isPaused = false;

    void Start() {
        playerName = PlayerPrefs.GetString("PlayerName", "訪客"); 
        if (continueButton != null) {
            continueButton.onClick.AddListener(ContinueStory);
        }
        StartCoroutine(StartStoryFlow());
    }

    // 核心:依序播放對話並透過 WaitUntil 實現點擊暫停
    IEnumerator PlaySegments(DialogueSegment[] segments) {
        if (continueButton != null) continueButton.interactable = true; 
        
        foreach (var segment in segments) {
            UpdateCharacterPortrait(segment);

            // 更新 UI 並自動替換 [NAME] 關鍵字
            if (speakerText != null) speakerText.text = segment.speakerName.Replace("[NAME]", playerName);
            if (dialogueText != null) dialogueText.text = segment.text.Replace("[NAME]", playerName);

            // 關鍵防呆與暫停機制:等待玩家點擊按鈕解除 isPaused
            isPaused = true;
            yield return new WaitUntil(() => !isPaused);
        }
    }

    private void UpdateCharacterPortrait(DialogueSegment segment) {
        if (characterDisplayImage != null) {
            characterDisplayImage.gameObject.SetActive(segment.showCharacter);
            if (segment.showCharacter && segment.characterSprite != null) {
                characterDisplayImage.sprite = segment.characterSprite;
            }
        }
    }

    public void ContinueStory() {
        if (isPaused) isPaused = false;
    }
}

三、在 Unity 中的實裝與設定
以我們實際場景 OfficeScene 35 的 Inspector 畫面為例:

  1. Hierarchy 配置:將 StoryFlowManager.cs 掛載於 ChoiceManager 物件上,並將 Woman (Image) 拖入 Character Display Image 欄位。
  2. 拖曳綁定:
  • 將 Canvas 中的 SpeakerNameText 拖入 Speaker Text 欄位。
  • 將 DialogueContentText 拖入 Dialogue Text 欄位。
  • 將全螢幕點擊按鈕拖入 Continue Button (click) 欄位。

https://ithelp.ithome.com.tw/upload/images/20260915/201840738aNfNtYDTx.png
圖一、Hierarchy 配置與UI 組件示意圖

3.劇本資料編輯: 在 Inspector 的 Pre Choice Segments 列表中直接編輯對話陣列。如圖所示,在元素中填入 [NAME],程式執行時就會自動把玩家名稱替換進去;Speaker Name 填入 理事長(依照出場人物不同自行輸入),Text 填入「希望您能贊助我們一些資金...(依照劇幕台詞)」,並綁定對應的角色立繪。

https://ithelp.ithome.com.tw/upload/images/20260915/20184073chKe4LbIZb.png
圖二、劇本資料示意圖

四、架構設計亮點與開發實戰經驗

  1. WaitUntil 狀態鎖與玩家點擊控速: 比起傳統在 Update() 裡面判斷按鈕輸入,使用 Coroutine 搭配 yield return new WaitUntil(() => !isPaused) 更加優雅。每播一句話就把 isPaused 設為 true,當玩家點擊全螢幕 continueButton 呼叫 ContinueStory() 時才把鎖解開(isPaused = false),讓 foreach 繼續走下一圈。
  2. [NAME] 字串動態替換: 利用 segment.text.Replace("[NAME]", playerName),企劃可以在劇本中自由設計 NPC 稱呼玩家的台詞,大幅提升文字冒險遊戲的代入感。
  3. 高度的可延伸性: 這套底層對話結構相當乾淨,未來不論是要在 DialogueSegment 裡加入角色立繪(Sprite)、對話音效(AudioClip),或是控制劇情走完後的選項面板(ChoicePanel),都只要在現有的架構上擴充即可。

五、今日成果與小結

  • 基礎劇情控制器:完成了 StoryFlowManager 對話陣列讀取與 UI 呈現。
  • Coroutine 點擊推進:實裝了利用 WaitUntil 與 continueButton 監聽玩家推進劇本的機制。
  • 動態姓名替換:實現了 [NAME] 占位符號轉換玩家暱稱功能。

範例影片:Yes

一樣別忘了上傳進度,今日主題與前兩天屬於相同分支:

  1. 檢查修改狀態
    git status

  2. 加入暫存區並提交 Commit
    git add .
    git commit -m "feat: 實作 StoryFlowManager 對話流程控制與 Coroutine 點擊推進機制"

  3. 推送到遠端開發分支
    git push origin feature/story-flow


上一篇
【DAY7】Unity 2D 敘事遊戲開發:角色立繪與 UI 對話框佈局(UI Character Setup)
下一篇
【DAY9】Unity 2D 敘事遊戲開發:對話系統 (2) — 關鍵劇情分歧與數值連動
系列文
從課堂半成品到完整發布:獨立遊戲的30天重生記17
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言