Unity回合制战斗:将WaitForSeconds改为按F键触发剧情推进
解决方案
1. 先写通用的按键等待协程
不用在每个节点重复写循环,直接写一个可复用的协程函数,专门处理“等待指定按键按下”的逻辑:
// 等待指定按键按下的通用协程 private IEnumerator WaitForKeyPress(KeyCode key) { // 每帧检测按键,直到按下为止 while (!Input.GetKeyDown(key)) { yield return null; // 让出帧时间,避免阻塞主线程 } }
这里用Input.GetKeyDown是因为它只在按键按下的第一帧返回true,防止按住F键时连续触发剧情推进。
2. 替换所有自动等待的代码
把原来所有用WaitForSeconds自动等待的地方,替换成调用上面的按键等待协程:
修改SetupBattle方法
原代码:
yield return new WaitForSeconds(2f);
改成:
yield return StartCoroutine(WaitForKeyPress(KeyCode.F));
修改PlayerAttack方法
原代码:
yield return new WaitForSeconds(2f);
改成:
yield return StartCoroutine(WaitForKeyPress(KeyCode.F));
修改EnemyTurn方法
把两处yield return new WaitForSeconds(1f);都改成:
yield return StartCoroutine(WaitForKeyPress(KeyCode.F));
3. 可选优化:给玩家加按键提示
在剧情文本里加上Press F to continue的提示,让玩家明确知道需要操作,比如:
SetupBattle里的文本改成:dialogueText.text = enemyUnit.unitName + " Attacked!\nPress F to continue";PlayerAttack里的文本改成:dialogueText.text = "The attack hits!\nPress F to continue";
完整修改后的代码
using System.Collections; using System.Collections.Generic; using UnityEngine; using TMPro; public enum BattleState { START, PLAYERTURN, ENEMYTURN, WON, LOST } public class BattleSystem : MonoBehaviour { public GameObject playerPrefab; public GameObject enemyPrefab; public Transform playerBattleStation; public Transform enemyBattleStation; public TMP_Text dialogueText; Unit playerUnit; Unit enemyUnit; public BattleHUDScript playerHUD; public BattleHUDScript enemyHUD; public BattleState state; void Start() { state = BattleState.START; StartCoroutine(SetupBattle()); } // 新增:通用按键等待协程 private IEnumerator WaitForKeyPress(KeyCode key) { while (!Input.GetKeyDown(key)) { yield return null; } } private IEnumerator SetupBattle() { GameObject playerGO = Instantiate(playerPrefab, playerBattleStation); playerUnit = playerGO.GetComponent<Unit>(); GameObject enemyGO = Instantiate(enemyPrefab, enemyBattleStation); enemyUnit = enemyGO.GetComponent<Unit>(); enemyUnit.basedamage = PlayerPrefs.GetInt("playerMaxDamage"); enemyUnit.baseHP = PlayerPrefs.GetInt("playerMaxHP"); enemyUnit.baseMP = PlayerPrefs.GetInt("playerMaxMana"); enemyUnit.basespeed = PlayerPrefs.GetInt("playerMaxSpeed"); enemyUnit.currHP = enemyUnit.baseHP; enemyUnit.currMP = enemyUnit.baseMP; enemyUnit.currspeed = enemyUnit.basespeed; enemyUnit.currdamage = enemyUnit.basedamage; // 新增按键提示 dialogueText.text = enemyUnit.unitName + " Attacked!\nPress F to continue"; playerHUD.SetHUD(playerUnit); enemyHUD.SetHUD(enemyUnit); // 替换自动等待为按键等待 yield return StartCoroutine(WaitForKeyPress(KeyCode.F)); state = BattleState.PLAYERTURN; PlayerTurn(); } private void PlayerTurn() { dialogueText.text = "Choose an action: "; } IEnumerator PlayerAttack() { bool isDead = enemyUnit.TakeDamage(playerUnit.currdamage); enemyHUD.SetHP(enemyUnit.currHP); // 新增按键提示 dialogueText.text = "The attack hits!\nPress F to continue"; // 替换自动等待为按键等待 yield return StartCoroutine(WaitForKeyPress(KeyCode.F)); if (isDead) { state = BattleState.WON; EndBattle(); } else { state = BattleState.ENEMYTURN; StartCoroutine(EnemyTurn()); } } IEnumerator EnemyTurn() { // 新增按键提示 dialogueText.text = enemyUnit.unitName + " attacks!\nPress F to continue"; // 替换自动等待为按键等待 yield return StartCoroutine(WaitForKeyPress(KeyCode.F)); bool isDead = playerUnit.TakeDamage(enemyUnit.currdamage); playerHUD.SetHP(playerUnit.currHP); // 新增按键提示 dialogueText.text = "You took damage!\nPress F to continue"; // 替换自动等待为按键等待 yield return StartCoroutine(WaitForKeyPress(KeyCode.F)); 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"; } } public void OnFightButton() { if (state != BattleState.PLAYERTURN) { return; } StartCoroutine(PlayerAttack()); } }
为什么用通用协程?
- 复用性强:所有需要等待按键的地方直接调用,不用重复写循环代码
- 易维护:以后要改按键(比如换成空格),只需要修改调用时的
KeyCode参数,或者在WaitForKeyPress里统一调整 - 代码更简洁:避免每个协程里都堆重复的等待逻辑
内容的提问来源于stack exchange,提问作者HGBadger
相关产品推荐
相关产品推荐

