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

Unity2D中空格键触发攻击仅生效一次的问题求助

Unity2D攻击功能仅生效一次的问题排查与解决

我正在制作一款Unity2D游戏,玩家控制的盒子需要实现攻击其他盒子的功能。我在玩家盒子下创建了初始禁用的子对象attackArea作为攻击区域,该对象带有碰撞器可与其他盒子碰撞。设计逻辑是:按下空格键时启用attackArea,计时器在0.25秒后禁用该区域,以此实现重复攻击。

但实际运行时攻击仅生效一次,后续按空格键不再触发。我尝试将Attack函数逻辑直接写入空格键检测的if语句中,问题仍未解决。作为重新学习基础的新手,不知道该怎么排查解决。

附相关脚本代码:

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

public class playerAttack : MonoBehaviour
{

    public GameObject attackArea;
    public float timer = 0f;
    public float attackTime = 0.25f;
    public bool attacking = false;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            attackArea = transform.GetChild(0).gameObject;
            Attack();
        }

        if(attacking)
        {
            timer += Time.deltaTime;
            if (timer >= attackTime)
            {
                attacking = false;
                attackArea = transform.GetChild(0).gameObject;
                attackArea.SetActive(false);
            }
        }

    }

    void Attack()
    {
        attacking = true;
        attackArea.SetActive(true);
    }

}

问题根源

  1. 计时器未重置:第一次攻击结束后,timer的值会停留在大于等于attackTime的状态,后续触发攻击时没有重置计时器,导致攻击状态的逻辑判断混乱。
  2. 无攻击状态锁:按下空格键时没有判断当前是否处于攻击状态,多次按键会打乱attacking的状态逻辑。
  3. 冗余的子对象获取:每次按键和结束攻击时都重复调用transform.GetChild(0),不仅冗余,还可能因为子对象顺序变动引发意外问题。

修复后的代码

using UnityEngine;

public class playerAttack : MonoBehaviour
{
    public GameObject attackArea;
    public float attackTime = 0.25f;
    private bool attacking = false;

    void Update()
    {
        // 仅在非攻击状态下响应空格键
        if (Input.GetKeyDown(KeyCode.Space) && !attacking)
        {
            Attack();
        }
    }

    void Attack()
    {
        attacking = true;
        attackArea.SetActive(true);
        // 用Invoke替代手动计时,自动延迟执行结束逻辑
        Invoke(nameof(EndAttack), attackTime);
    }

    void EndAttack()
    {
        attacking = false;
        attackArea.SetActive(false);
    }

    // 兜底逻辑:若Inspector未赋值,自动获取第一个子对象
    private void Awake()
    {
        if (attackArea == null)
        {
            attackArea = transform.GetChild(0).gameObject;
        }
    }
}

修复要点

  • 用Invoke替代手动计时:避免计时器未重置的问题,代码更简洁易维护。
  • 添加攻击状态锁:确保同一时间只能触发一次攻击,防止状态混乱。
  • 预赋值+兜底获取:优先在Inspector面板将attackArea拖入赋值,Awake中做兜底处理,避免重复获取子对象。
  • 分离攻击逻辑:将攻击启动与结束的逻辑拆分为独立方法,职责更清晰。

内容的提问来源于stack exchange,提问作者Jopeez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 14:10:19