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

Unity2D敌人未触发攻击问题及敌我击退功能实现求助

Unity2D敌人攻击逻辑修复与双向击退实现

问题描述

使用Unity2D v2022.3.17f1开发游戏时,敌人可在追踪范围内正常跟随玩家,但接触玩家时无法停止并发起攻击。玩家与敌人均挂载BoxCollider2D和RigidBody2D组件,需同时实现敌人攻击玩家时的双向击退功能。

原代码

using System.Collections.Generic;
using UnityEngine;

public class EnemyController : MonoBehaviour
{
    public Player player;

    public float speed = 3f;
    public float damage = 2f;
    public float attackDistance = 1f;
    public float followDistance = 5f;

    private bool isAttacking = false;

    void Update()
    {
        Vector2 direction = player.transform.position - transform.position;
        float distance = direction.magnitude;

        if (distance < followDistance)
        {
            if (distance < attackDistance && !isAttacking)
            {
                Debug.Log("Enemy is attacking");
                StartCoroutine(Attack());
            }
            else
            {
                if (distance > attackDistance)
                {
                    MoveTowardsTarget(direction);
                }
                else
                {
                    StopMoving();
                }
            }
        }
    }

    void MoveTowardsTarget(Vector2 direction)
    {
        direction.Normalize();
        transform.Translate(direction * speed * Time.deltaTime);
    }

    void StopMoving()
    {
        Rigidbody2D rb = GetComponent<Rigidbody2D>();
        rb.velocity = Vector2.zero;
    }

    IEnumerator Attack()
    {
        isAttacking = true;
        StopMoving(); 

        player.TakeDamage(damage);

        yield return new WaitForSeconds(1.0f);

        isAttacking = false;
        MoveTowardsTarget(player.transform.position - transform.position); 
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Player"))
        {
            StopMoving();
        }
    }
}

修复方案与双向击退实现

修改后代码

using UnityEngine;
using System.Collections;

public class EnemyController : MonoBehaviour
{
    public Player player;

    public float speed = 3f;
    public float damage = 2f;
    public float attackDistance = 1.2f; // 建议设为两者碰撞器半径之和
    public float followDistance = 5f;
    public float knockbackForce = 6f; // 双向击退的力度参数

    private bool isAttacking = false;
    private Rigidbody2D rb;

    void Awake()
    {
        rb = GetComponent<Rigidbody2D>(); // 提前获取组件,减少性能消耗
    }

    void Update()
    {
        Vector2 direction = player.transform.position - transform.position;
        float distance = direction.magnitude;

        // 仅在非攻击状态、且在追踪范围内时处理逻辑
        if (distance < followDistance && !isAttacking)
        {
            if (distance <= attackDistance)
            {
                StartCoroutine(Attack(direction));
            }
            else
            {
                MoveTowardsTarget(direction);
            }
        }
    }

    void MoveTowardsTarget(Vector2 direction)
    {
        direction.Normalize();
        rb.velocity = direction * speed; // 改用Rigidbody控制移动,适配物理系统
    }

    void StopMoving()
    {
        rb.velocity = Vector2.zero;
    }

    IEnumerator Attack(Vector2 direction)
    {
        isAttacking = true;
        StopMoving(); 

        // 触发玩家受伤
        player.TakeDamage(damage);

        // 执行双向击退:敌人向后退,玩家向相反方向被推开
        rb.AddForce(-direction.normalized * knockbackForce, ForceMode2D.Impulse);
        player.GetComponent<Rigidbody2D>().AddForce(direction.normalized * knockbackForce, ForceMode2D.Impulse);

        yield return new WaitForSeconds(1.0f);

        isAttacking = false;
    }
}

关键修改说明

  • 移动逻辑优化:替换transform.Translate为Rigidbody2D.velocity,让敌人移动遵循Unity物理规则,避免和碰撞组件冲突,确保接触玩家时能稳定停止。
  • 攻击触发调整:
    • 提前在Awake中获取Rigidbody2D组件,避免重复调用GetComponent。
    • 收紧Update条件判断,确保只有非攻击状态下才会触发移动或攻击。
    • 攻击时传入方向参数,用于计算击退方向。
  • 双向击退实现:在攻击协程中,给敌人和玩家施加相反方向的冲量,实现双向击退效果(需确保玩家Rigidbody2D的约束设置允许受力)。
  • 移除冗余碰撞逻辑:原OnCollisionEnter2D中的停止逻辑会和Update的距离判断冲突,直接移除后用攻击范围判断控制敌人行为更合理。

额外注意事项

  • 调整attackDistance参数:建议设置为敌人与玩家碰撞器的半径之和,确保敌人在即将接触玩家时触发攻击,而非重叠后才触发。
  • 检查Layer设置:确保玩家和敌人的Layer设置正确,碰撞检测规则正常生效。
  • 玩家TakeDamage方法:需确保该方法已正确实现生命值扣减等逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 15:35:14