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

Unity 2D敌人巡逻异常问题:需实现两点巡逻及玩家检测攻击功能

问题修复与功能实现方案

一、先解决巡逻逻辑错误

你的代码存在两个核心问题,导致敌人单向跑动无法折返:

  1. 错误的位置赋值:Vector2 point = currentPoint.position = transform.position;这行代码把目标点的位置直接改成了敌人当前位置,导致目标点永远跟着敌人,完全无法触发切换逻辑。应改为获取目标点位置,而非赋值。
  2. 过大的距离阈值:50f的距离判断远超常规2D游戏的单位尺度,敌人还没接近目标点就会切换方向,甚至直接跑出地图。改成0.5f这类小数值更合理。

修复后同时新增玩家检测与攻击功能的完整代码:

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

public class EnemyPatrol : MonoBehaviour
{
    public GameObject pointA;
    public GameObject pointB;
    private Rigidbody2D rb;
    private Animator anim;
    private Transform currentPoint;
    public float speed;
    // 玩家检测与攻击相关变量
    public Transform player;
    public float detectRange;
    public float attackRange;
    private bool isChasing;
    private float attackCooldown = 1f;
    private float lastAttackTime;

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        anim = GetComponent<Animator>();
        currentPoint = pointB.transform;
        anim.SetBool("IsRunning", true);
        isChasing = false;
        lastAttackTime = -attackCooldown;
    }

    void Update()
    {
        // 优先执行玩家检测逻辑
        CheckPlayerStatus();

        if (!isChasing)
        {
            PatrolBetweenPoints();
        }
        else
        {
            ChaseAndAttackPlayer();
        }
    }

    // 两点间巡逻逻辑
    void PatrolBetweenPoints()
    {
        Vector2 targetPos = currentPoint.position;
        
        // 朝目标点移动并翻转朝向
        if (currentPoint == pointB.transform)
        {
            rb.velocity = new Vector2(speed, rb.velocity.y);
            transform.localScale = new Vector3(1, 1, 1);
        }
        else
        {
            rb.velocity = new Vector2(-speed, rb.velocity.y);
            transform.localScale = new Vector3(-1, 1, 1);
        }

        // 到达目标点后切换巡逻方向
        if (Vector2.Distance(transform.position, targetPos) < 0.5f)
        {
            currentPoint = currentPoint == pointB.transform ? pointA.transform : pointB.transform;
        }
    }

    // 玩家状态检测
    void CheckPlayerStatus()
    {
        if (player == null) return;

        float distanceToPlayer = Vector2.Distance(transform.position, player.position);
        
        // 进入检测范围开始追击
        if (distanceToPlayer <= detectRange && distanceToPlayer > attackRange)
        {
            isChasing = true;
            anim.SetBool("IsRunning", true);
        }
        // 超出检测范围回到巡逻状态
        else if (distanceToPlayer > detectRange)
        {
            isChasing = false;
            anim.SetBool("IsRunning", true);
        }
    }

    // 追击与攻击逻辑
    void ChaseAndAttackPlayer()
    {
        if (player == null) return;

        float distanceToPlayer = Vector2.Distance(transform.position, player.position);
        
        // 朝向玩家移动
        if (player.position.x > transform.position.x)
        {
            transform.localScale = new Vector3(1, 1, 1);
            rb.velocity = new Vector2(speed, rb.velocity.y);
        }
        else
        {
            transform.localScale = new Vector3(-1, 1, 1);
            rb.velocity = new Vector2(-speed, rb.velocity.y);
        }

        // 进入攻击范围且冷却完成时触发攻击
        if (distanceToPlayer <= attackRange && Time.time >= lastAttackTime + attackCooldown)
        {
            rb.velocity = Vector2.zero;
            anim.SetBool("IsRunning", false);
            anim.SetTrigger("Attack");
            lastAttackTime = Time.time;
        }
    }

    // 调试用:绘制检测范围
    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireSphere(transform.position, detectRange);
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, attackRange);
    }
}

二、使用步骤

  1. 巡逻点设置:在场景中创建两个空物体作为pointA和pointB,拖入脚本对应字段,调整位置为巡逻路径的两端。
  2. 玩家赋值:将玩家对象拖入脚本的player字段。
  3. 参数调整:根据游戏需求修改speed(移动速度)、detectRange(玩家检测范围)、attackRange(攻击触发范围)、attackCooldown(攻击冷却时间)的数值。
  4. 动画适配:确保Animator控制器中有IsRunning布尔参数和Attack触发参数,对应跑动和攻击动画。

三、优化建议

  • 视野限制:添加角度判断,只有玩家在敌人正面视野范围内才触发追击,提升逻辑合理性。
  • 障碍物规避:若巡逻路径有障碍物,可使用射线检测或NavMesh2D实现绕路功能。
  • 状态重置:玩家死亡或脱离范围后,敌人延迟几秒再回到巡逻状态,避免切换过于突兀。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 04:21:03