You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 21:55:33