一、前言
在前幾天陸續搞定主選單、場景轉換、Bad End 條件判定之後,我們的敘事遊戲已經具備了完整的核心循環與生死機制。但一款耐玩的遊戲,絕對少不了讓玩家在探索、抉擇、甚至是推進劇情時獲得額外的「成就感回饋」。今天我們就要正式動工,打造成就系統的第一步——利用 ScriptableObject 建立擴充性極高的成就資料模型與全域管理器!
二、 成就系統架構與設計挑戰
在設計一款包含多種成就且需要跨場景持久化的成就系統時,程式架構必須克服以下痛點:
三、 核心程式實作:Achievement 數據結構與管理器
using UnityEngine;
[CreateAssetMenu(fileName = "NewAchievement", menuName = "Achievement System/Achievement Data")]
public class AchievementData : ScriptableObject {
[Header("成就基本資訊")]
public string achievementID; // 唯一識別碼 (例如: "ITEM_CAPYBARA")
public string achievementName; // 成就顯示名稱 (例如: "卡皮巴拉的溫暖")
[TextArea(3, 5)]
public string description; // 成就解鎖條件描述
public Sprite iconSprite; // 成就圖標 (彩色版)
[Header("狀態設定")]
public bool isUnlocked = false; // 當前是否已解鎖
}
using UnityEngine;
using System.Collections.Generic;
public class AchievementManager : MonoBehaviour {
public static AchievementManager Instance { get; private set; }
[Header("所有成就清單")]
[Tooltip("把專案中建立好的所有 AchievementData 拖進這裡")]
public List<AchievementData> allAchievements = new List<AchievementData>();
private void Awake() {
if (Instance == null) {
Instance = this;
DontDestroyOnLoad(gameObject);
LoadAchievements();
}
else {
Destroy(gameObject);
}
}
/// 解鎖指定 ID 的成就
public void UnlockAchievement(string id) {
AchievementData target = allAchievements.Find(a => a.achievementID == id);
if (target != null && !target.isUnlocked) {
target.isUnlocked = true;
SaveAchievements();
Debug.Log($"[Achievement] 恭喜解鎖成就:{target.achievementName}!");
}
}
/// 儲存所有成就的解鎖狀態
private void SaveAchievements() {
foreach (var achievement in allAchievements) {
PlayerPrefs.SetInt("ACH_" + achievement.achievementID, achievement.isUnlocked ? 1 : 0);
}
PlayerPrefs.Save();
}
/// 讀取成就解鎖狀態
private void LoadAchievements() {
foreach (var achievement in allAchievements) {
if (PlayerPrefs.HasKey("ACH_" + achievement.achievementID)) {
int status = PlayerPrefs.GetInt("ACH_" + achievement.achievementID, 0);
achievement.isUnlocked = (status == 1);
}
else {
achievement.isUnlocked = false;
}
}
}
}
四、 Unity Editor 實作步驟


圖二、腳本掛載與成就代入(如圖一內容所示)
五、 開發實戰經驗:踩坑與架構反思
六、 今日成果與小結
DAY 23 的內容主要是開始打造全新的 成就系統(Achievement System),包含了透過 ScriptableObject 建立資料模型(AchievementData)以及跨場景持久化的全域管理器(AchievementManager)。因為這是一個全新獨立的功能模組,它不屬於前面的存讀檔、常駐 UI 或 Bad End 分支,所以為它開立一個專屬的新分支--feature/achievement-system:
1.檢查目前修改狀態
git status
2.建立並切換至新的獨立分支:
git checkout -b feature/achievement-system
3.將今天的程式碼與修改加入暫存區並提交 Commit:
git add .
git commit -m "feat: 實作 AchievementData ScriptableObject 與 AchievementManager,建立成就系統底層與持久化管理"
4.將新分支推送到遠端倉庫:
git push origin feature/achievement-system