嘉南藥理大學 2017 - Unity 程式設計基本課程

從基礎程式到多人連線遊戲開發

嘉南藥理大學 2017 - Unity 程式設計基本課程

課程簡介

這是 2017 年在嘉南藥理大學開設的「Unity 程式設計基本課程」,用兩週密集課程帶領學生從 Unity 基礎程式設計到完整的多人連線遊戲開發。

課程特色

目標: 快速掌握 Unity 程式設計,並開發一個多人連線射擊遊戲

課程設計:

技術棧:

Unity + C# + Unity Networking (UNET) → 多人連線 FPS 遊戲

課程大綱

第一週 (4/17) ♥♥ - Unity 程式基礎

千里之行,始於足下

學習內容:

1. 變數與資料型別

string 字串、int 整數、bool 布林

// 要買的飲料是什麼,要幾杯,老闆帥不帥
public string 飲料 = "珍奶";
public int 幾杯 = 1;
public bool 老闆帥 = true;

實用場景:


2. Debug.Log() 輸出訊息

// 將要顯示的句子用 + 組合起來一次顯示出來
Debug.Log("老闆我要" + 幾杯 + "杯" + 飲料);

用途:


3. if-else 條件判斷

// 如果老闆帥就要電話,如果不帥就叫老闆快點
if (老闆帥) {
    Debug.Log("老闆可以給我你的電話號碼嗎");
} else {
    Debug.Log("老闆可以快點嗎 我趕時間");
}

應用:


4. for 迴圈

// 睡不著的時候用迴圈數羊
Debug.Log("睡不著覺來數羊");

// 從第 1 隻開始數,要數到 1000 隻
for (int 第幾 = 1; 第幾 < 1000; 第幾++) {
    Debug.Log(第幾 + "隻羊");  // 現在數到第幾隻

    // 數到 300 隻就睡著了
    if (第幾 == 300) {
        Debug.Log("zzzZZZ");  // 睡著了
        break;  // 已經睡著就不再數了
    }
}

應用:


5. transform.Translate() 物件移動

void OnGUI() {
    // X 軸控制
    if (GUI.Button(new Rect(10, 10, 200, 30), "X ++")) {
        Target.transform.Translate(1, 0, 0);  // 向 X 軸移動 1 單位
    }
    if (GUI.Button(new Rect(210, 10, 200, 30), "X --")) {
        Target.transform.Translate(-1, 0, 0);
    }

    // 鍵盤控制
    if (Input.GetKey(KeyCode.W)) {
        Target.transform.Translate(0, 0, 1);  // 向前移動
    }
    if (Input.GetKey(KeyCode.S)) {
        Target.transform.Translate(0, 0, -1);  // 向後移動
    }
}

控制方式:


6. transform.Rotate() 物件旋轉

void OnGUI() {
    // X 軸旋轉
    if (GUI.Button(new Rect(10, 10, 200, 30), "X ++")) {
        Target.transform.Rotate(10, 0, 0);  // 以 X 軸旋轉 10 度
    }

    // Y 軸旋轉(左右轉)
    if (GUI.Button(new Rect(10, 40, 200, 30), "Y ++")) {
        Target.transform.Rotate(0, 10, 0);
    }

    // Z 軸旋轉(翻滾)
    if (GUI.Button(new Rect(10, 70, 200, 30), "Z ++")) {
        Target.transform.Rotate(0, 0, 10);
    }
}

7. Input.GetMouseButtonDown() 滑鼠輸入

void Update() {
    // 滑鼠按鍵檢測
    if (Input.GetMouseButtonDown(0)) {
        Debug.Log("按下滑鼠左鍵");
    }
    if (Input.GetMouseButtonDown(1)) {
        Debug.Log("按下滑鼠右鍵");
    }

    // 滑鼠移動控制旋轉
    // Input.GetAxis("Mouse X") 可以取得滑鼠左右移動的差值
    Target.transform.Rotate(0, Input.GetAxis("Mouse X"), 0);
}

8. Input.GetKey() 鍵盤輸入

void Update() {
    // 方向鍵檢測
    if (Input.GetKey(KeyCode.UpArrow)) {
        print("向上方向鍵被按了");
    }
    if (Input.GetKey(KeyCode.DownArrow)) {
        print("向下方向鍵被按了");
    }
}

9. 完整的角色控制器

PlayerController.cs

void Update() {
    // 鍵盤控制移動
    if (Input.GetKey(KeyCode.W)) {
        gameObject.transform.Translate(0, 0, .1f);
    }
    if (Input.GetKey(KeyCode.S)) {
        gameObject.transform.Translate(0, 0, -.1f);
    }
    if (Input.GetKey(KeyCode.D)) {
        gameObject.transform.Translate(.1f, 0, 0);
    }
    if (Input.GetKey(KeyCode.A)) {
        gameObject.transform.Translate(-.1f, 0, 0);
    }

    // 鍵盤控制旋轉
    if (Input.GetKey(KeyCode.E)) {
        gameObject.transform.Rotate(0, 10, 0);
    }
    if (Input.GetKey(KeyCode.Q)) {
        gameObject.transform.Rotate(0, -10, 0);
    }

    // 滑鼠控制旋轉
    gameObject.transform.Rotate(0, Input.GetAxis("Mouse X") * 10, 0);
}

功能:


第二週 (4/24) ♥♥♥ - 多人連線遊戲開發

從基礎到實戰

完整的多人連線 FPS 遊戲開發(12 步驟)

步驟 1-3:專案設定與玩家建立

  1. 建立新專案
    • 開新 3D 專案
    • 建立 Main 場景
  2. 設定 NetworkManager
    • 建立空物件命名為 NetworkManager
    • 加入 NetworkManager 組件
    • 加入 NetworkManagerHUD 組件
  3. 建立 Player Prefab
    • 製作 Player 遊戲物件
    • 加入 NetworkIdentity 組件
    • 勾選 Local Player Authority
    • 將 Player Prefab 加入 NetworkManager/Spawn Info

步驟 4-6:玩家移動與同步

  1. 基本玩家控制
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    void Update()
    {
        var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
        var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;

        transform.Rotate(0, x, 0);  // 旋轉
        transform.Translate(0, 0, z);  // 前進後退
    }
}
  1. 網路同步移動
using UnityEngine;
using UnityEngine.Networking;

public class PlayerController : NetworkBehaviour
{
    void Update()
    {
        if (!isLocalPlayer) {
            return;  // 只控制自己的角色
        }

        var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
        var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;

        transform.Rotate(0, x, 0);
        transform.Translate(0, 0, z);
    }
}
  1. 區分本地玩家
public override void OnStartLocalPlayer()
{
    GetComponent<MeshRenderer>().material.color = Color.blue;
}

步驟 7-9:射擊系統

  1. 建立子彈
    • 建立 Bullet 遊戲物件
    • 加入 Rigidbody
    • 製作成 Prefab
  2. 本地射擊
public GameObject bulletPrefab;
public Transform bulletSpawn;

void Update()
{
    // ... 移動程式碼 ...

    if (Input.GetKeyDown(KeyCode.Space)) {
        Fire();
    }
}

void Fire()
{
    var bullet = (GameObject)Instantiate(
        bulletPrefab,
        bulletSpawn.position,
        bulletSpawn.rotation);

    bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * 6;
    Destroy(bullet, 2.0f);
}
  1. 網路同步射擊
void Update()
{
    // ... 移動程式碼 ...

    if (Input.GetKeyDown(KeyCode.Space)) {
        CmdFire();  // 改用 Command
    }
}

[Command]  // 在 Client 呼叫,在 Server 執行
void CmdFire()
{
    var bullet = (GameObject)Instantiate(
        bulletPrefab,
        bulletSpawn.position,
        bulletSpawn.rotation);

    bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * 6;

    // 在所有 Client 上生成子彈
    NetworkServer.Spawn(bullet);

    Destroy(bullet, 2.0f);
}

步驟 10-12:血量系統與死亡重生

  1. 碰撞與血量

Bullet.cs

void OnCollisionEnter(Collision collision)
{
    var hit = collision.gameObject;
    var health = hit.GetComponent<Health>();
    if (health != null) {
        health.TakeDamage(10);
    }
    Destroy(gameObject);
}

Health.cs

public const int maxHealth = 100;
public int currentHealth = maxHealth;
public RectTransform healthBar;

public void TakeDamage(int amount)
{
    currentHealth -= amount;
    if (currentHealth <= 0) {
        currentHealth = 0;
        Debug.Log("Dead!");
    }

    healthBar.sizeDelta = new Vector2(currentHealth, healthBar.sizeDelta.y);
}

Billboard.cs(血條面向鏡頭)

void Update()
{
    transform.LookAt(Camera.main.transform);
}
  1. 網路同步血量
using UnityEngine.Networking;

public class Health : NetworkBehaviour
{
    public const int maxHealth = 100;

    [SyncVar(hook = "OnChangeHealth")]  // 同步變數
    public int currentHealth = maxHealth;

    public RectTransform healthBar;

    public void TakeDamage(int amount)
    {
        if (!isServer)  // 只在 Server 處理
            return;

        currentHealth -= amount;
        if (currentHealth <= 0) {
            currentHealth = 0;
            Debug.Log("Dead!");
        }
    }

    void OnChangeHealth(int health)
    {
        // 當血量改變時更新 UI
        healthBar.sizeDelta = new Vector2(health, healthBar.sizeDelta.y);
    }
}
  1. 死亡與重生
public void TakeDamage(int amount)
{
    if (!isServer)
        return;

    currentHealth -= amount;
    if (currentHealth <= 0) {
        currentHealth = maxHealth;

        // 在 Server 呼叫,在所有 Client 執行
        RpcRespawn();
    }
}

[ClientRpc]
void RpcRespawn()
{
    if (isLocalPlayer) {
        // 回到起始位置
        transform.position = Vector3.zero;
    }
}

技術亮點

1. Unity Networking (UNET) 架構

Client-Server 模型:

Client 1 ←→ Server ←→ Client 2

關鍵組件:


2. 網路同步機制

[Command]:Client → Server

[Command]
void CmdFire() {
    // 在 Client 呼叫,在 Server 執行
}

[ClientRpc]:Server → All Clients

[ClientRpc]
void RpcRespawn() {
    // 在 Server 呼叫,在所有 Client 執行
}

[SyncVar]:自動同步變數

[SyncVar(hook = "OnChangeHealth")]
public int currentHealth;

3. 權威性設計

Server Authority(伺服器權威):

Local Player Authority(本地玩家權威):


4. 完整的遊戲功能

玩家移動 → 射擊 → 子彈飛行 → 碰撞偵測 → 扣血 → 血條更新 → 死亡重生

每個環節都考慮網路同步!


課程特色

1. 循序漸進

第一週:打好 C# 基礎 第二週:實戰多人遊戲

從單機到聯機,步步為營。


2. 實作導向


3. 趣味教學

用生活化的例子教程式:


4. 令人興奮的進度

用 ♥ 符號表示課程的刺激程度:


學習成果

學生將學會:

  1. Unity C# 基礎
    • 變數與資料型別
    • 流程控制(if、for)
    • 物件操作(移動、旋轉)
    • 輸入處理(鍵盤、滑鼠)
  2. Unity Networking
    • Client-Server 架構
    • NetworkManager 設定
    • 網路物件同步
    • Command/ClientRpc/SyncVar
  3. 完整遊戲開發
    • 角色控制系統
    • 射擊系統
    • 血量與 UI 系統
    • 死亡與重生機制
  4. 多人遊戲設計思維
    • 權威性設計
    • 作弊防護
    • 網路延遲處理
    • 狀態同步

課程資源

完整教學網站: https://yazelin.github.io/cnu2017/

GitHub 開源專案: https://github.com/yazelin/cnu2017

範例下載:

參考資源:

相關課程:


課程資訊