iT邦幫忙

2026 iThome 鐵人賽

DAY 26
0
Vibe Coding

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

【DAY26】Unity 2D 敘事遊戲開發:除蟲特輯:從崩潰邊緣到主動防禦(Debugging & NullReference Prevention)

  • 分享至 

  • xImage
  •  

一、前言
在前面的文章中,我們陸續完成了成就系統、UI 介面、對話觸發與本地存檔。當專案的規模越來越大、元件愈拉愈多時,最讓人頭痛的日常就是「執行遊戲時突然卡住或噴一堆紅字」。今天這篇除蟲特輯,我們要來聊聊開發者必經的痛點——如何擺脫不友善的 NullReferenceException,並透過主動防禦性編程(Defensive Programming)來拯救常忘記拉線的自己。

二、核心痛點剖析:為什麼總是漏拉 Inspector 欄位?
在 Unity 中,我們習慣用 [SerializeField] 將腳本的變數暴露在 Inspector 給美術或自己拉線(例如 UI 圖片、文字、音效來源等)。但隨著場景越來越多,常常會發生一種狀況:

  • 慘況重現: 複製了一個新的對話物件或切換了場景,結果忘記把對應的 AudioSource 或 Text 拖進 Inspector。
  • 傳統痛點: 一按下 Play 觸發到該行程式碼,Unity 就直接噴出長長的紅字 NullReferenceException: Object reference not set to an instance of an object,不僅遊戲當場停擺,還得花時間去追查到底是哪一個變數是 null。
    https://ithelp.ithome.com.tw/upload/images/20261002/20184073bFYlUJtbQy.png
    圖一、傳統寫法痛點-NullReferenceException

三、核心程式實作:用主動防禦取代被動崩潰
與其讓 Unity 丟出難以追查的系統崩潰,我們不如在程式碼進入核心邏輯前,先主動進行空值檢查(Null Check),並用帶有提示性的 Debug.LogError 幫自己「抓蟲」。
以我們專案中的 DialogueManager 為例,我們加入了以下防禦性檢查:

using UnityEngine;
public class DialogueManager : MonoBehaviour {
    [Header("音效元件參考")]
    [SerializeField] private AudioSource voiceAudioSource;

    public void PlayVoice(AudioClip clip) {
        // 主動防禦:在呼叫前先檢查是否有漏拉 Inspector 欄位
        if (voiceAudioSource == null)  {
            Debug.LogError("【DialogueManager】錯誤:你忘記在 Inspector 裡把 Voice Audio Source 欄位拉入了!", this);
            return;
        }
        voiceAudioSource.PlayOneShot(clip);
    }
}

這樣一來,就算哪天不小心手殘或眼殘漏拉了欄位,遊戲也不會直接暴斃,而是會在 Console 精準地跳出專屬的警告紅字,一眼就能知道問題出在哪裡!
https://ithelp.ithome.com.tw/upload/images/20261002/20184073BqFYVpCUOg.png
圖二、改良後的噴錯警告

四、Unity Editor 與除錯工具應用步驟
1. 善用 Console 的錯誤導航:

  • 當 Console 跳出我們自定義的 Debug.LogError 時,直接雙擊該行錯誤訊息,Unity 會自動跳轉並高亮顯示是哪一支腳本、哪一行漏掉了設定。
    https://ithelp.ithome.com.tw/upload/images/20261002/20184073MdaxqAX1K8.png
    圖三、高亮顯示哪一行漏掉了設定

2. 利用物件關聯(Context)快速定位:

  • 在寫 Debug.LogError("...", this) 時帶入第二個參數 this,點擊錯誤訊息時,Unity 的階層視窗(Hierarchy)甚至會自動幫你選中出問題的那個 GameObject,省去大海撈針的時間。
    https://ithelp.ithome.com.tw/upload/images/20261002/20184073bjxB5UDjXZ.png
    圖四、點擊自動選中出問題的那個 GameObject
  1. 建立常態檢查機制:
  • 在遊戲進入的關鍵初始化點(如 Awake 或 Start)統一對核心管理器進行一次完整性驗證,確保萬事俱備才開始執行劇情。

五、開發實戰經驗:踩坑與架構反思

  • Pitfall:依賴記憶力而非系統防呆:
    • 狀況:總覺得自己拉線很小心,結果隔了幾天開新場景還是漏掉,導致測試時頻繁中斷。
    • 解法:團隊開發或個人專案都一樣,把「可能忘記的事」交給程式碼去攔截。寫一次防禦性檢查,就能終身免疫該類型的崩潰。

六、今日成果與小結

  • 主動式除蟲:學會了用 Debug.LogError 代替被動的 NullReference 崩潰,讓除錯效率呈倍數提升。
  • 專案強健度:為對話與音效系統鋪好了安全網,讓整個敘事遊戲的運作更加穩固!

範例影片:Yes

今天的內容是關於「防禦性編程(Defensive Programming)與除蟲優化」,透過在程式碼中加入空值檢查(Null Check)與帶有上下文的 Debug.LogError(..., this) 來優化對話與音效系統的錯誤處理機制。因為這屬於專案整體的程式碼重構、品質優化與除錯防護,它通常不屬於單一功能的新分支,而是適合放在 main 分支。

1.檢查修改狀態
git status

2.切換回主分支 main
git checkout main

3.同步一下遠端的最新狀態
git pull origin main

4.加入暫存區並提交 Commit
git add .
git commit -m "refactor: 導入防禦性編程與空值檢查,優化 NullReferenceException 錯誤提示與除錯效率"
5.推送到遠端主分支
git push origin main


上一篇
【DAY25】Unity 2D 敘事遊戲開發:遊戲內道具觸發與彈窗通知回饋(Achievement System Part 3 - In-Game Triggers & Popup UI)
下一篇
【DAY27】Unity 2D 敘事遊戲開發:效能優化與記憶體管理(Optimization & Garbage Collection)
系列文
從課堂半成品到完整發布:獨立遊戲的30天重生記 共 28 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言