給Unity新手的話: 想知道那些經典的捕魚機遊戲是怎麼做出來的嗎?今天我們要深入解析一個完整的捕魚機遊戲專案,從最核心的GameController開始,帶你一步步理解遊戲開發的精髓!
🎮 捕魚機遊戲到底有哪些核心功能?
在開始寫程式之前,我們先來分析一下捕魚機遊戲需要哪些主要功能。想像一下你在遊樂場玩捕魚機的體驗:你坐在機台前,操控砲台瞄準魚群,發射子彈,擊中魚類後獲得金幣和分數,隨著遊戲進行還能升級解鎖更強的武器。

如上圖所示,遊戲介面包含了等級顯示(左上角的99級「大師」段位)、金幣數量(底部的$9999999)、經驗條(藍色進度條)、倒數計時(右上角240s)、以及中央的砲台和各種魚類。這個看似簡單的遊戲其實包含了許多複雜的系統。玩家需要一個射擊系統來發射子彈,砲台系統要能跟隨滑鼠移動,魚群系統負責生成各種魚類,經濟系統管理金幣和經驗值,等級系統處理升級邏輯,還有音效系統提供聽覺回饋。每個系統都需要與其他系統協調運作,這就需要一個總指揮來管理所有這些功能。
🔧 Unity實現架構:腳本分工的藝術
在Unity中實現捕魚機遊戲,我們需要將這些功能分解成不同的腳本來處理。這就像是經營一家餐廳,你需要廚師、服務生、收銀員各司其職,但同時也需要一個店長來協調所有人的工作。
我們的捕魚機專案包含了以下主要腳本:
GameController.cs 就是那個店長,負責統籌管理整個遊戲的運行。它管理UI更新、處理玩家輸入、控制遊戲狀態,是整個遊戲的大腦。FishMaker.cs 像是負責魚類供應的廚師,持續生成各種魚類讓遊戲保持活力。GunFollow.cs 是砲台的控制員,讓砲台能夠精準跟隨玩家的滑鼠移動。
AudioManager.cs 是音響師,管理所有的背景音樂和音效。FishAttr.cs、BulletAttr.cs、WebAttr.cs 分別定義了魚類、子彈、漁網的屬性和行為,就像是為每種遊戲物件制定的行為規範。

上圖清楚展示了GameController如何統籌管理各個系統。從圖中可以看出,GameController分別控制UI系統、遊戲邏輯和資料管理三大區塊,再透過事件分發來協調FishMaker(魚群生成)、AudioManager(音效管理)、GunFollow(輸入處理)等子系統的運作。
📥 開始實戰:下載專案並打開Unity
在我們深入程式碼之前,你需要先準備好實戰環境。請前往 GitHub專案頁面 下載完整的捕魚機專案原始碼。下載後解壓縮,用Unity打開這個專案。
打開專案後,你會看到完整的遊戲場景和所有腳本檔案。建議你先試玩一下遊戲,感受一下各種功能的運作,這樣在閱讀程式碼時會更有感覺。接下來我們就要深入探討這個遊戲的核心——GameController腳本。
🎯 GameController:遊戲的大腦與神經中樞
GameController.cs 是整個捕魚機遊戲的核心控制器,它就像是遊戲的大腦,負責協調所有系統的運作。這個腳本採用了單例模式設計,確保整個遊戲中只有一個GameController實例,方便其他腳本隨時調用。

打開Unity後,你可以在Inspector視窗看到GameController的完整設定(如上圖)。這些公開變數讓我們能在不修改程式碼的情況下調整遊戲參數,比如金幣初始值500、大獎勵倒數240秒等。
單例模式:確保唯一性的設計智慧
private static GameController _instance;
public static GameController Instance
{
get
{
return _instance;
}
}
void Awake()
{
_instance = this;
}
這個設計讓任何其他腳本都可以通過 GameController.Instance 來訪問遊戲控制器,就像是給了每個員工店長的直撥電話,需要什麼資訊或指示都可以直接聯繫。比如當魚類被擊中時,FishAttr腳本就會呼叫 GameController.Instance.gold += gold 來增加玩家的金幣。
資料管理:玩家進度的守護者
GameController管理著遊戲中所有重要的玩家資料,包括等級、經驗值、金幣等。這些資料不僅在遊戲運行時需要即時更新,還要在玩家關閉遊戲後能夠保存下來。
public int lv = 0; // 玩家等級
public int exp = 0; // 經驗值
public int gold = 500; // 金幣
void Start()
{
// 讀取上次保存的遊戲資料
gold = PlayerPrefs.GetInt("gold", gold);
lv = PlayerPrefs.GetInt("lv", lv);
exp = PlayerPrefs.GetInt("exp", exp);
}
這個系統使用Unity的PlayerPrefs來持久化資料,就像是遊戲的記憶系統,記住玩家的所有進度。每次遊戲開始時會自動讀取之前的記錄,讓玩家可以從上次結束的地方繼續遊戲。
射擊系統:從輸入到子彈發射的完整流程
射擊系統是捕魚機遊戲的核心玩法,GameController在這裡展現了複雜的邏輯處理能力。當玩家點擊滑鼠時,系統需要經過多重檢查和處理才能成功發射子彈。
void Fire()
{
if (Input.GetMouseButtonDown(0) && EventSystem.current.IsPointerOverGameObject() == false)
{
if (gold - oneShootCosts[costIndex] >= 0)
{
// 扣除金幣
gold -= oneShootCosts[costIndex];
// 播放音效和特效
AudioManager.Instance.PlayEffectSound(AudioManager.Instance.fireClip);
Instantiate(fireEffect);
// 創建子彈並設定屬性
GameObject bullet = Instantiate(useBullets[bulletIndex]);
bullet.GetComponent<BulletAttr>().damage = oneShootCosts[costIndex];
}
}
}
這個流程會先檢查玩家有沒有點擊滑鼠左鍵,確定沒有點到UI上(避免誤觸),再看看玩家的金幣夠不夠發射子彈。條件都符合的話,就扣掉相應的金幣、播放音效特效、產生子彈物件。這樣的處理順序讓遊戲邏輯能正常運作。
武器系統:多層次的威力選擇
捕魚機遊戲的一個重要特色是玩家可以調整砲台的威力,威力越大的武器消耗更多金幣但造成更高傷害。GameController通過一個巧妙的索引系統來管理這個功能。
private int costIndex = 0;
private int[] oneShootCosts = { 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 };
public void OnButtonPDown() // 調大威力
{
gunGos[costIndex / 4].SetActive(false); // 隱藏當前武器
costIndex++;
costIndex = (costIndex > oneShootCosts.Length - 1) ? 0 : costIndex;
gunGos[costIndex / 4].SetActive(true); // 顯示新武器
oneShootCostText.text = "$" + oneShootCosts[costIndex];
}
這個系統設計通過 costIndex / 4 來決定使用哪種類型的砲台(共5種),每4個費用等級對應一種砲台外觀。這樣既提供了細膩的威力調整,又有明顯的視覺回饋讓玩家知道自己使用的是哪種等級的武器。
等級系統:成長與獎勵的循環
遊戲的長期吸引力很大程度上來自於角色成長系統。GameController實現了一個基於經驗值的等級系統,讓玩家在遊戲過程中持續感受到進步。
void UpdateUI()
{
// 等級提升檢查
while (exp >= 1000 + 200 * lv)
{
exp = exp - (1000 + 200 * lv);
lv++;
lvUpTips.SetActive(true);
AudioManager.Instance.PlayEffectSound(AudioManager.Instance.lvUpClip);
Instantiate(lvEffect);
}
}
升級公式 1000 + 200 * 當前等級 讓升級所需的經驗會越來越多,玩家剛開始升級很快,後面就需要花更多時間。每次升級都會播放音效和特效,馬上給玩家回饋。
時間系統:持續的獎勵機制
為了維持玩家的參與度,遊戲設計了定時獎勵系統。即使玩家暫時沒有進行射擊,也能通過等待獲得一些基礎獎勵。
public float bigTimer = 240; // 4分鐘大獎勵
public float smallTimer = 60; // 1分鐘小獎勵
void UpdateUI()
{
bigTimer -= Time.deltaTime;
smallTimer -= Time.deltaTime;
if (smallTimer <= 0)
{
smallTimer = 60;
gold += 50; // 每分鐘獎勵50金幣
}
if (bigTimer <= 0)
{
// 顯示大獎勵按鈕
bigCountdownButton.gameObject.SetActive(true);
}
}
這個機制讓玩家就算不射擊也能拿到一些基本收入,金幣不夠的時候也還能繼續玩。大獎勵要玩家自己點才能領取,增加了互動的部分。
UI管理:資訊展示的藝術
GameController負責管理遊戲中所有UI元素的更新,讓玩家能即時看到自己目前的遊戲狀態。從金幣數量、等級顯示到經驗條進度,每個資訊都需要準確的計算和更新。
void UpdateUI()
{
goldText.text = "$" + gold;
lvText.text = lv.ToString();
lvNameText.text = lvName[lv / 10]; // 段位名稱
expSlider.value = ((float)exp) / (1000 + 200 * lv); // 經驗條進度
}
段位系統用 lv / 10 來劃分,每10級就是一個段位,從「新手」到「宗師」,讓玩家清楚知道自己的進度和目標。經驗條的計算則讓玩家一眼就能看出還差多少經驗才能升級。
🎨 背景系統:視覺進化的驚喜
隨著玩家等級的提升,遊戲背景也會發生變化,這是一個很有趣的視覺獎勵系統。每20級遊戲就會切換到新的背景,並播放海浪特效來慶祝這個里程碑。
void ChangeBg()
{
if (bgIndex != lv / 20)
{
bgIndex = lv / 20;
AudioManager.Instance.PlayEffectSound(AudioManager.Instance.seaWaveClip);
Instantiate(seaWaveEffect);
bgImage.sprite = bgSprites[bgIndex];
}
}
這個設定雖然不會影響主要玩法,但讓遊戲畫面有了變化。背景換了之後,玩家能感覺到自己有在進步,這種回饋有助於保持玩下去的動力。
🎯 總結:GameController的基本架構
GameController.cs 展現了遊戲控制器的基本寫法:把主要邏輯集中管理,同時跟其他系統配合。它處理了從玩家操作到遊戲狀態更新的整個流程,雖然有些地方還能再改進,但作為學習範例已經包含了遊戲開發的重要觀念。
用單例模式讓所有地方都能存取,用資料持久化儲存玩家進度,用輸入檢查維護遊戲邏輯,用UI更新反映遊戲狀態。這些基本模式組成了遊戲系統的基礎架構,了解這些概念對後續學習和改進都很重要。
🚀 下期預告:深入魚群與砲台系統
在下一篇文章中,我們將深入探討 FishMaker.cs 和 GunFollow.cs 這兩個同樣重要的腳本。FishMaker負責動態生成各種魚類,創造豐富多變的遊戲內容;GunFollow則處理砲台的精準跟隨控制,讓玩家能夠靈活瞄準目標。
這兩個系統與GameController協同工作,共同創造出流暢而有趣的遊戲體驗。我們會詳細分析魚群生成的隨機演算法、砲台跟隨的數學計算,以及這些系統如何與遊戲的其他部分無縫整合。敬請期待!
請先 登入 以發表留言。