1. 程式人生 > >Unity 回合制戰鬥系統(初級篇)

Unity 回合制戰鬥系統(初級篇)

專案資源傳了,請看1樓

本人遊戲策劃一枚,愛好遊戲設計開發

最近學習了Unity之後,結合各種網上的教材和資料後自己實現了一套簡單的回合制戰鬥系統,如下



系統實現效果簡介:

1. 目前為1V1的固定回合戰鬥

2. 玩家操作通過介面按鈕輸入,怪物操作為自動

3. 包含了簡單的遊戲狀態控制(選單狀態、戰鬥狀態、結束狀態)

4. 單位攻擊、受擊、死亡時播放對應動畫

裝備工作:

1. 模型動畫資源

下載自AssetStore,資源名:Animated Knight and Slime Monster(免費)

2. 場景新增玩家和怪物模型

為了方便怪物和角色用了相同的模型和Animator

,建立空物體用於掛載控制回合戰鬥的指令碼

3. 為角色模型新增Animator

,新增待機、攻擊和受擊3個動畫片段至Animator,設定待機動畫為預設狀態

建立從Any State到待機、攻擊和死亡的狀態轉移,並新增trigger型別的Parameters,作為對應狀態轉移的條件,不勾選Has Exit Time


指令碼:

新增到玩家物件的指令碼

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerControl : MonoBehaviour {
    //主角屬性
    public int hp = 100;
    public int attack = 10;
    public int defence = 2;

    //回合控制指令碼
    private TurnControl turnScript;

    //動畫元件  
    private Animator playerAnimator;

    //獲取敵人指令碼的引用 
    private EnemyControl enemyScript;

    void Start()
    {
        turnScript = GameObject.Find("TurnSystem").GetComponent<TurnControl>();
        playerAnimator = GetComponent<Animator>();
        
        enemyScript = GameObject.FindGameObjectWithTag("EnemyUnit").GetComponent<EnemyControl>();
    }

    void OnGUI()
    {
        //遊戲狀態是Game才會進行
        if (turnScript.currentState == TurnControl.GameState.Game)
        {
            //如果處於等待玩家輸入狀態,則顯示操作視窗
            if (turnScript.isWaitForPlayer)
            {
                GUI.Window(1, new Rect(Screen.width / 2 + 200, Screen.height / 2, 100, 100), PlayerUnitAction, "選擇技能");
            }
        } 
    }

    void PlayerUnitAction(int ID)
    {
        if (GUI.Button(new Rect(10, 20, 80, 30), "普通攻擊"))
        {
            turnScript.isWaitForPlayer = false;
            playerAnimator.SetTrigger("attack");
            int damage = Mathf.Max(0, attack - enemyScript.defence);
            enemyScript.ReceiveDamage(damage);
            Debug.Log("主角使用了普通攻擊");
            StartCoroutine("EnemyWait");
        }
        if (GUI.Button(new Rect(10, 60, 80, 30), "英勇打擊"))
        {
            turnScript.isWaitForPlayer = false;
            playerAnimator.SetTrigger("attack");
            int damage = Mathf.Max(0, attack - enemyScript.defence);
            enemyScript.ReceiveDamage(damage);
            Debug.Log("主角使用了英勇打擊");
            StartCoroutine("EnemyWait");
        }
    }

    //在切換到敵人操作前新增延遲
    IEnumerator EnemyWait()
    {
        yield return new WaitForSeconds(1);
        turnScript.isEnemyAction = true;
    }
    
    //承受傷害  
    public void ReceiveDamage(int damage)
    {
        hp -= damage;
        playerAnimator.SetTrigger("damage");
        if (hp <= 0)
        {
            playerAnimator.SetTrigger("dead");
        }
    }
}
怪物物件指令碼
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyControl : MonoBehaviour {
    //怪物屬性
    public int hp = 50;
    public int attack = 10;
    public int defence = 1;

    //回合控制指令碼
    private TurnControl turnScript;

    //動畫元件  
    private Animator enemyAnimator;

    //獲取玩家指令碼的引用 
    private PlayerControl playerScript;

    void Start()
    {
        turnScript = GameObject.Find("TurnSystem").GetComponent<TurnControl>();
        enemyAnimator = GetComponentInChildren<Animator>();

        playerScript = GameObject.FindGameObjectWithTag("PlayerUnit").GetComponent<PlayerControl>();
    }

    void Update()
    {
        //遊戲狀態是Game才會進行
        if (turnScript.currentState == TurnControl.GameState.Game)
        {
            if (turnScript.isEnemyAction)
            {
                Debug.Log("敵人使用了普通攻擊");
                //播放攻擊動畫
                enemyAnimator.SetTrigger("attack");
                int damage = Mathf.Max(0, attack - playerScript.defence);
                playerScript.ReceiveDamage(damage);
                //延遲1s出現玩家操作UI
                StartCoroutine("PlayerUIWait");
                turnScript.isEnemyAction = false;
            }
        }
    }

    //在切換到玩家UI前延遲
    IEnumerator PlayerUIWait()
    {
        yield return new WaitForSeconds(1);
        turnScript.isWaitForPlayer = true;
    }

    //承受傷害  
    public void ReceiveDamage(int damage)
    {
        hp -= damage;
        enemyAnimator.SetTrigger("damage");
        if (hp <= 0)
        {
            enemyAnimator.SetTrigger("dead");
        }
    }

}

回合控制物件指令碼
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TurnControl : MonoBehaviour {

    //控制玩家操作及操作視窗是否出現
    public bool isWaitForPlayer = true;
    //控制怪物操作
    public bool isEnemyAction = false;

    //獲取玩家及敵人指令碼的引用 
    private PlayerControl playerScript;
    private EnemyControl enemyScript;

    //定義遊戲狀態列舉  
    public enum GameState
    {
        Menu,//遊戲開始選單  
        Game,//遊戲中 
        Over//遊戲結束
    }
    //遊戲初始狀態
    public GameState currentState = GameState.Menu;

    void Start()
    {
        //獲取玩家及敵人指令碼引用 
        playerScript = GameObject.FindGameObjectWithTag("PlayerUnit").GetComponent<PlayerControl>();
        enemyScript = GameObject.FindGameObjectWithTag("EnemyUnit").GetComponent<EnemyControl>();
    }
    
    void OnGUI()
    {
        if (currentState == GameState.Menu)
        {
            GUI.Window(0, new Rect(Screen.width / 2-100, Screen.height / 2-30, 200, 60), GameStartConfirm, "戰鬥開始確認");
        }
        else if (currentState == GameState.Over)
        {
            GUI.Window(2, new Rect(Screen.width / 2 - 100, Screen.height / 2 - 30, 200, 60), GameRestartConfirm, "戰鬥結束");
        }
    }



    void GameStartConfirm(int ID)
    {
        if (GUI.Button(new Rect(50, 30, 100, 20), "開始戰鬥"))
        {
            currentState = GameState.Game;
        }
    }

    void GameRestartConfirm(int ID)
    {
        if (GUI.Button(new Rect(50, 30, 100, 20), "重新開始"))
        {
            playerScript.hp = 100;
            enemyScript.hp = 50;
            isWaitForPlayer = true;
            isEnemyAction = false;
            currentState = GameState.Game;
        }
    }

    void Update()
    {
        if (currentState == GameState.Game)
        {
            //如果任意一方生命值為0,則遊戲結束  
            if (playerScript.hp <= 0)
            {
                Debug.Log("戰鬥失敗");
                currentState = GameState.Over;
            }
            if (enemyScript.hp <= 0)
            {
                Debug.Log("戰鬥勝利");
                currentState = GameState.Over;
            }
        }
        
    }

}

新增完指令碼後即可測試這個戰鬥系統了~