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

Unity 2D Raycast检测距离失效 敌人AI超距识别玩家问题

Unity 2D敌人射线检测距离失效排查方案

问题根因

  • 追击标记永久锁死:代码中SeenPlayer变量一旦被赋值为true,没有任何逻辑将其重置为false。只要射线第一次碰撞到任意物体,敌人就会永久进入追击状态,无论玩家后续跑多远都会持续追踪,表现为距离限制完全失效。
  • 射线未做碰撞过滤:当前玩家检测射线命中任意碰撞体(地面、墙体、场景道具、其他单位)都会触发追击判定,没有校验命中对象是否为玩家,容易出现隔墙误判、超远距离误触发的问题。
  • 射线方向固定不跟随朝向:检测射线写死朝世界坐标左侧发射,敌人转向朝右巡逻时射线方向不会同步切换到右侧,不仅会漏检正面的玩家,转向过程中还容易误扫到其他物体提前进入追击。
  • 参数默认值触发无限检测:seeDistance是public字段,如果在Inspector面板未正确赋值、或意外清空输入框,字段默认值为0。根据Unity 2D射线的API规则,当传入的射线长度参数为0时,会沿指定方向做无限距离检测,完全忽略距离限制。
  • 移动逻辑与朝向不匹配:巡逻时固定朝世界坐标右侧移动,转向后移动方向不会同步反转,会导致敌人转向后原地卡顿、移动方向错乱,间接干扰检测逻辑的表现。

修复方案

  1. 给公开参数加默认值,避免Inspector漏赋值导致的异常:将seeDistance初始值设为2,同时新增玩家层、地面层的掩码参数,过滤无关碰撞体。
  2. 射线命中后增加校验逻辑,只有命中对象标签为Player时才触发追击标记。
  3. 增加丢失玩家判定:进入追击状态后持续计算和玩家的距离,超出阈值后重置SeenPlayer标记,回到巡逻状态。
  4. 射线方向、巡逻移动方向随敌人朝向动态切换,不要写死固定方向。
  5. 调试阶段开启射线可视化,直观确认射线的长度、方向、命中对象是否符合预期。

修正后完整代码

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

public class enemyMove : MonoBehaviour
{
    public int speed = 2;
    private bool movingRight = true;
    public bool SeenPlayer = false;
    public Transform target;
    public float seeDistance = 2f;
    public int health = 3;
    public Rigidbody2D rb;
    public Transform groundDetection; 
    // 层掩码参数,在Inspector面板分别指定玩家、地面对应的层
    public LayerMask playerLayer;
    public LayerMask groundLayer;
    // 丢失玩家的距离阈值,比检测距离稍大,避免状态反复切换
    public float losePlayerDistance = 3f;

    void Start()
    {
        target = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        if (!SeenPlayer)
        {
            // 按当前朝向移动
            transform.Translate((movingRight ? Vector2.right : Vector2.left) * speed * Time.deltaTime);
        }
        else
        {
            transform.position = Vector2.MoveTowards(transform.position, target.position, speed * Time.deltaTime);
            transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);

            // 超出丢失距离则回到巡逻状态
            if (Vector2.Distance(transform.position, target.position) > losePlayerDistance)
            {
                SeenPlayer = false;
                transform.localScale = Vector3.one;
            }
        }

        // 地面检测只碰撞地面层
        RaycastHit2D groundInfo = Physics2D.Raycast(groundDetection.position, Vector2.down, 2f, groundLayer);
        // 玩家检测方向跟随朝向,只碰撞玩家层
        Vector2 detectDir = movingRight ? Vector2.right : Vector2.left;
        RaycastHit2D playerHit = Physics2D.Raycast(groundDetection.position, detectDir, seeDistance, playerLayer);
        
        // 边缘转向逻辑
        if (groundInfo.collider == null)
        {
            if (movingRight)
            {
                transform.eulerAngles = new Vector3(0, -180, 0);
                movingRight = false;
            }
            else
            {
                transform.eulerAngles = new Vector3(0, 0, 0);
                movingRight = true;
            }
        }

        // 确认命中玩家才触发追击
        if (playerHit.collider != null && playerHit.collider.CompareTag("Player"))
        {
            SeenPlayer = true;
        }

        // 调试用:Scene视图中绘制射线,方便排查问题
        Debug.DrawRay(groundDetection.position, detectDir * seeDistance, Color.red);
        Debug.DrawRay(groundDetection.position, Vector2.down * 2f, Color.green);
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        BulletScript bullet = collision.GetComponent<BulletScript>();
        if (bullet != null)
        {
            health -= 1;
            Destroy(bullet.gameObject);
            if (health == 0)
            {
                Destroy(gameObject);
            }
            else
            {
                // 受击力方向根据当前朝向调整
                rb.AddForce(new Vector2(movingRight ? -4 : 4, 2), ForceMode2D.Impulse);
            }
        }
    }
}

注意:使用层掩码前,需要在Unity的Layer设置中新建Player、Ground层,分别把玩家对象、地面平台对象挂载到对应层,再把脚本上的playerLayer、groundLayer参数指定为对应层即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 00:57:28