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

Unity 2D敌人AI射线检测追踪玩家失效问题求助

2D平台游戏敌人AI问题排查与修复建议

问题概述

  • 敌人唤醒Trigger功能正常,但玩家进入Raycast检测范围后,敌人未执行追逐逻辑
  • Raycast前方存在“Action”层物体时,无法保持isAgro为true的状态
  • 怀疑问题出在isAgro变量的逻辑处理上

敌人子物体层级结构:
敌人子物体层级结构

问题代码

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

public class Presentsaswehear : MonoBehaviour
{
    // Start is called before the first frame update
    // trigger code ignore
    private Animator Enemtestone;
    public GameObject FirstTrig;
    public static bool Izintyloip;
    private bool Thecheckert;
    // trigger code ignore


    //Enemy part tracking blablablaaaaa
    [SerializeField]
    Transform Player;

    [SerializeField]
    float agroRange;

    [SerializeField]
    Transform castPoint;

    [SerializeField]
    float moveSpeed;

    Rigidbody2D rb2det;

    bool isFacingLeft;

    //true
    private bool isAgro = true;
   
    
    private bool isSearching;

    void Start()
    {
        
        Enemtestone = GetComponent<Animator>();
        //FirstTrig.SetActive(true);
        Izintyloip = false;
        rb2det = GetComponent<Rigidbody2D>();
        Thecheckert = false;
    }

    // Update is called once per frame
    void Update()
    {
        // trigger code ignore
        if (Izintyloip == true) { 
            Enemtestone.SetInteger("Wakeup", 1);
            Thecheckert = true;
        }
        // trigger code ignore
        
        if (CanSeePlayer(agroRange))
        {
            isAgro = true;
            //ChasePlayer(); uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

        }
        else
        {
            if (isAgro)
            {
                //isSearching = true;
                
                if(!isSearching)
                {
                    isSearching = true;
                    Invoke("StopChasingPlayer", 5);

                }
            }
            
            
        }
        
        if (isAgro)
        {

            ChasePlayer();

        }
    }

    bool CanSeePlayer(float distance)
    {
        bool val = false;
        float castDist = distance;

        if (isFacingLeft)
        {

            castDist = -distance;


        }


        Vector2 endPos = castPoint.position + Vector3.right * castDist;
        
        RaycastHit2D hit = Physics2D.Linecast(castPoint.position, endPos, 1 << LayerMask.NameToLayer("Action"));
        if(hit.collider != null)
        {
            //(hit.collider.gameObject.CompareTag("Player"))
            if (hit.collider.gameObject.CompareTag("Player"))
            {
                val = true;

            }
            else
            {
                val = false;
            }


            Debug.DrawLine(castPoint.position, hit.point, Color.yellow);
        }
        else
        {

            Debug.DrawLine(castPoint.position, endPos, Color.blue);

            

        }
        return val;
    }

    void ChasePlayer()
    {

        if(transform.position.x < Player.position.x)
        {

            rb2det.velocity = new Vector2(moveSpeed, 0);
            transform.eulerAngles = new Vector3(0, 180, 0);
            isFacingLeft = false;
        }
        else
        {

            rb2det.velocity = new Vector2(-moveSpeed, 0);

            transform.eulerAngles = new Vector3(0, 0, 0);
            isFacingLeft = true;
            // if(transform.position.x > player.postion.x)
        }

        Enemtestone.SetBool("GFW", true);
    }
    void StopChasingPlayer()
    {
        isAgro = false;
        rb2det.velocity = new Vector2(0, 0);
        isSearching = false;
        Enemtestone.SetBool("GFW", false);
    }
}

问题分析

  1. isAgro初始值错误:默认设为true,但唤醒逻辑未关联agro状态,导致敌人初始就处于追逐状态,不符合“唤醒后才响应视线”的设计逻辑。
  2. LayerMask检测范围不足:CanSeePlayer函数仅检测“Action”层,玩家不在该层时无法被检测到;同时遇到“Action”层物体时直接返回false,导致isAgro被重置。
  3. isFacingLeft未初始化:初始值未显式设置,可能导致Raycast方向与敌人实际朝向不符。
  4. 搜索状态未及时重置:重新检测到玩家时,未取消之前触发的StopChasingPlayer调用,导致isAgro被错误设为false。

修复方案

1. 修正isAgro初始值与唤醒逻辑绑定

将isAgro初始值改为false,确保敌人唤醒后才具备响应视线的能力:

// 初始化改为
private bool isAgro = false;

// Update中的唤醒逻辑保持原有唤醒动画逻辑即可

2. 修复CanSeePlayer函数的检测逻辑

扩展LayerMask范围,同时处理“Action”层物体的检测逻辑,保持当前isAgro状态:

bool CanSeePlayer(float distance)
{
    bool val = false;
    float castDist = distance;

    if (isFacingLeft)
    {
        castDist = -distance;
    }

    Vector2 endPos = castPoint.position + Vector3.right * castDist;
    // 同时检测Player层和Action层
    int layerMask = (1 << LayerMask.NameToLayer("Player")) | (1 << LayerMask.NameToLayer("Action"));
    RaycastHit2D hit = Physics2D.Linecast(castPoint.position, endPos, layerMask);
    
    if(hit.collider != null)
    {
        Debug.DrawLine(castPoint.position, hit.point, Color.yellow);
        if (hit.collider.gameObject.CompareTag("Player"))
        {
            val = true;
        }
        else if (hit.collider.gameObject.layer == LayerMask.NameToLayer("Action"))
        {
            // 检测到Action层物体,保持当前agro状态
            val = isAgro;
        }
        else
        {
            val = false;
        }
    }
    else
    {
        Debug.DrawLine(castPoint.position, endPos, Color.blue);
        val = false;
    }
    return val;
}

3. 初始化isFacingLeft

在Start函数中添加初始朝向设置,确保Raycast方向正确:

void Start()
{
    Enemtestone = GetComponent<Animator>();
    Izintyloip = false;
    rb2det = GetComponent<Rigidbody2D>();
    Thecheckert = false;
    // 根据敌人初始朝向设置,示例为朝右
    isFacingLeft = false;
}

4. 重置搜索状态

当重新检测到玩家时,取消之前的StopChasingPlayer调用:

if (CanSeePlayer(agroRange))
{
    isAgro = true;
    // 取消正在进行的停止追逐调用
    if(isSearching)
    {
        CancelInvoke("StopChasingPlayer");
        isSearching = false;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 11:09:16