Unity 回合制战斗系统(初级篇)

项目文件找出来了(后面中级/高级的),老版本的脚本有报错,我在新版2019.4.21f1c1下解决了报错,战斗场景可以正常跑的。

需要的同学点下面地址下载(关注就行啦不用积分),祝大家都早日学成

项目包下载

————————————————————————

最近学习了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;
            }
        }
        
    }

}


添加完脚本后即可测试这个战斗系统了~

猜你喜欢

转载自blog.csdn.net/c252270036/article/details/77126777