这是一个老教程了,但是对于没有写过回合制的初级程序同学来讲是比较适合的,也可以直接看源码,半小时内可以解决战斗
当然,我也没写过回合制系统所以就到处找,思路明白了就能自己修改了
视频教程 - 油管链接
Turn-Based Combat in Unity (youtube.com)
GitHub - 完整工程案例
wBrackeys/Turn-based-combat: Project files for our tutorial on how to create a turn-based battle system. (github.com)
实现效果
流程图
Start进入PlayerAttack,之后便是几个枚举状态之间的循环了
主要代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
// 定义战斗状态的枚举
public enum BattleState { START, PLAYERTURN, ENEMYTURN, WON, LOST }
public class BattleSystem : MonoBehaviour
{
// 玩家和敌人的预制体
public GameObject playerPrefab;
public GameObject enemyPrefab;
// 玩家和敌人的战斗位置
public Transform playerBattleStation;
public Transform enemyBattleStation;
// 玩家和敌人的单位
Unit playerUnit;
Unit enemyUnit;
// 对话文本
public Text dialogueText;
// 玩家和敌人的HUD
public BattleHUD playerHUD;
public BattleHUD enemyHUD;
// 当前战斗状态
public BattleState state;
// Start is called before the first frame update
void Start()
{
// 初始化战斗状态为START
state = BattleState.START;
// 启动设置战斗的协程
StartCoroutine(SetupBattle());
}
// 设置战斗的协程
IEnumerator SetupBattle()
{
// 实例化玩家和敌人的预制体
GameObject playerGO = Instantiate(playerPrefab, playerBattleStation);
playerUnit = playerGO.GetComponent<Unit>();
GameObject enemyGO = Instantiate(enemyPrefab, enemyBattleStation);
enemyUnit = enemyGO.GetComponent<Unit>();
// 更新对话文本
dialogueText.text = "A wild " + enemyUnit.unitName + " approaches...";
// 设置玩家和敌人的HUD
playerHUD.SetHUD(playerUnit);
enemyHUD.SetHUD(enemyUnit);
// 等待2秒
yield return new WaitForSeconds(2f);
// 切换到玩家回合
state = BattleState.PLAYERTURN;
PlayerTurn();
}
// 玩家攻击的协程
IEnumerator PlayerAttack()
{
// 玩家攻击敌人并检查敌人是否死亡
bool isDead = enemyUnit.TakeDamage(playerUnit.damage);
// 更新敌人的HP和对话文本
enemyHUD.SetHP(enemyUnit.currentHP);
dialogueText.text = "The attack is successful!";
// 等待2秒
yield return new WaitForSeconds(2f);
// 如果敌人死亡,结束战斗;否则,切换到敌人回合
if(isDead)
{
state = BattleState.WON;
EndBattle();
} else
{
state = BattleState.ENEMYTURN;
StartCoroutine(EnemyTurn());
}
}
// 敌人回合的协程
IEnumerator EnemyTurn()
{
// 更新对话文本
dialogueText.text = enemyUnit.unitName + " attacks!";
// 等待1秒
yield return new WaitForSeconds(1f);
// 敌人攻击玩家并检查玩家是否死亡
bool isDead = playerUnit.TakeDamage(enemyUnit.damage);
// 更新玩家的HP
playerHUD.SetHP(playerUnit.currentHP);
// 等待1秒
yield return new WaitForSeconds(1f);
// 如果玩家死亡,结束战斗;否则,切换到玩家回合
if(isDead)
{
state = BattleState.LOST;
EndBattle();
} else
{
state = BattleState.PLAYERTURN;
PlayerTurn();
}
}
// 结束战斗的方法
void EndBattle()
{
if(state == BattleState.WON)
{
dialogueText.text = "You won the battle!";
} else if (state == BattleState.LOST)
{
dialogueText.text = "You were defeated.";
}
}
// 玩家回合的方法
void PlayerTurn()
{
dialogueText.text = "Choose an action:";
}
// 玩家治疗的协程
IEnumerator PlayerHeal()
{
// 玩家恢复HP
playerUnit.Heal(5);
// 更新玩家的HP和对话文本
playerHUD.SetHP(playerUnit.currentHP);
dialogueText.text = "You feel renewed strength!";
// 等待2秒
yield return new WaitForSeconds(2f);
// 切换到敌人回合
state = BattleState.ENEMYTURN;
StartCoroutine(EnemyTurn());
}
// 攻击按钮的事件处理方法
public void OnAttackButton()
{
if (state != BattleState.PLAYERTURN)
return;
StartCoroutine(PlayerAttack());
}
// 治疗按钮的事件处理方法
public void OnHealButton()
{
if (state != BattleState.PLAYERTURN)
return;
StartCoroutine(PlayerHeal());
}
}
次要代码
战斗单位脚本,主要是属性
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Unit : MonoBehaviour
{
public string unitName;
public int unitLevel;
public int damage;
public int maxHP;
public int currentHP;
public bool TakeDamage(int dmg)
{
currentHP -= dmg;
if (currentHP <= 0)
return true;
else
return false;
}
public void Heal(int amount)
{
currentHP += amount;
if (currentHP > maxHP)
currentHP = maxHP;
}
}
更新UI代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BattleHUD : MonoBehaviour
{
public Text nameText;
public Text levelText;
public Slider hpSlider;
public void SetHUD(Unit unit)
{
nameText.text = unit.unitName;
levelText.text = "Lvl " + unit.unitLevel;
hpSlider.maxValue = unit.maxHP;
hpSlider.value = unit.currentHP;
}
public void SetHP(int hp)
{
hpSlider.value = hp;
}
}