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

Unity 2D平台游戏敌人无法向玩家移动攻击的问题求助

Unity 2D敌人跳跃后追踪玩家功能失效的排查与修复

问题说明

在2D平台游戏中设置的敌人,预期跳跃后会向玩家当前位置移动,但代码中的transform.position = Vector2.MoveTowards(transform.position, playerPosition, JumpAttackSpeed * Time.deltaTime);语句未生效,导致追踪功能失败。

核心问题分析

  1. 协程重复触发:Update函数中if (distance < AttackRange || canAttack)的条件会每帧启动Attack协程,多个协程同时运行会频繁修改canAttack状态,干扰跳跃后的移动逻辑。
  2. 位置判断精度问题:直接用transform.position != playerPosition判断到达目标位置,由于浮点精度误差,这个条件几乎永远为真,会提前触发冷却,打断移动。
  3. 冷却协程重复启动:Update的else分支每帧都会启动AttackCooldawn协程,导致canAttack被提前设为true,跳跃移动阶段被强制终止。
  4. 状态流转不完整:Attack协程结束后没有正确衔接冷却流程,导致状态逻辑混乱。

修复方案与代码调整

修复关键点

  • 新增isCooldownRunning标志位,避免冷却协程重复启动。
  • 用距离阈值判断是否到达目标位置,替代直接的Vector3相等比较。
  • 调整攻击触发逻辑,仅当canAttack为true且距离符合条件时启动Attack协程。
  • 完善Attack协程的流程,在跳跃攻击结束后主动启动冷却。

修复后的完整代码

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

public class EnemyScript : MonoBehaviour
{
    public Rigidbody2D rb;
    public GameObject player;
    private Vector3 playerPosition;
    public float NormalSpeed;
    private float distance;
    private bool canAttack = true;
    private bool isCooldownRunning = false; // 防止冷却协程重复启动
    public float AttackRange;
    public float JumpAttackRange;
    public float JumpForce;
    public float JumpAttackPreTime;
    public float JumpAttackTime;
    public float JumpAttackSpeed;
    public float AttackCooldawnTime;
    public float PositionCheckThreshold = 0.1f; // 位置判断的误差阈值

    void Update()
    {
        distance = Vector2.Distance(transform.position, player.transform.position);

        // 跳跃攻击阶段:向目标位置移动
        if (!canAttack)
        {
            float distanceToTarget = Vector2.Distance(transform.position, playerPosition);
            if (distanceToTarget > PositionCheckThreshold)
            {
                transform.position = Vector2.MoveTowards(transform.position, playerPosition, JumpAttackSpeed * Time.deltaTime);
            }
            else
            {
                // 到达目标后启动冷却
                if (!isCooldownRunning)
                {
                    StartCoroutine(AttackCooldawn());
                }
            }
        }
        else
        {
            // 可攻击状态:检查是否满足跳跃攻击条件
            if (distance < AttackRange && distance < JumpAttackRange)
            {
                StartCoroutine(Attack());
            }
        }
    }

    private IEnumerator Attack()
    {
        canAttack = false;
        isCooldownRunning = false;

        // 执行跳跃
        rb.velocity = new Vector2(rb.velocity.x, JumpForce);
        yield return new WaitForSeconds(JumpAttackPreTime);

        // 停止垂直移动并关闭重力
        rb.velocity = new Vector2(0, 0);
        float normalGravity = rb.gravityScale;
        rb.gravityScale = 0;
        // 记录当前玩家位置作为追踪目标
        playerPosition = player.transform.position;

        // 保持追踪状态一段时间
        yield return new WaitForSeconds(JumpAttackTime);

        // 恢复重力
        rb.gravityScale = normalGravity;

        // 启动冷却流程
        StartCoroutine(AttackCooldawn());
    }

    private IEnumerator AttackCooldawn()
    {
        isCooldownRunning = true;
        yield return new WaitForSeconds(AttackCooldawnTime);
        canAttack = true;
        isCooldownRunning = false;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 20:05:38