유니티로 적들 길찾기 AI 만들고 있는데
적들이 너무 장애물에 잘낍니다.
AI는 별 문제 없다고 칭찬해주던데
진짜 왜 이런지 1도 모르겠습니다.
만약에 유니티에서 주로 끼는 이유를 아는 분은 제발 알려주세요.
일단 혹시 모르니까 A*에 기반한 이동 방식을 표현한 코드도 남겨두겠습니다.
더 필요하시면 아래에 나오는 gridManager랑 FindPath도 코드 올리겠습니다.

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

public class enemyMovement : MonoBehaviour
{
    public LayerMask obstacleLayer;
    public Vector2Int PathFindDis;
    public GameObject Target;
    public float moveSpeed = 1f;          // 이동 속도
    private int targetIndex;              // 현재 목표 지점 인덱스
    private Rigidbody2D rb;
    public float updateInterval = 0.5f; // 0.5초마다 실행
    private float nextUpdateTime = 0f;
    private List<Node> path;
    private bool isMoving = false;
    private Vector3 nextNodeWorldPos;
    private Vector2 lastPosition;
    private float stuckTimer;

    void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    void Update(){
        IsStuck();
    }

    void FixedUpdate()
    {
    // 1. 이동 중이면 계속 이동 처리
    if (isMoving)
    {
        float step = moveSpeed * Time.fixedDeltaTime;
        Vector2 direction = ((Vector2)nextNodeWorldPos - rb.position).normalized;
        //Vector2 newPosition = rb.position + direction * step;
        rb.linearVelocity = direction * step;

        if (Vector2.Distance(rb.position, nextNodeWorldPos) < 0.01f)
        {
            rb.position = nextNodeWorldPos;
            targetIndex++;
            if (targetIndex < path.Count)
            {
                StartMovingToNextNode();
            }
            else
            {
                isMoving = false;
            }
        }

    if (path == null || targetIndex >= path.Count)
    {
    // 목표가 없으면 현재 위치로 이동 시도 (충돌 정상화)
    rb.linearVelocity = Vector2.zero;
    return;
    }

        return; // 이동 중이면 여기서 종료
    }

    // 2. 이동 중이 아니고 시간이 되면 경로 갱신
    if (Time.time >= nextUpdateTime)
    {
        nextUpdateTime = Time.time + updateInterval;
        Vector2Int objPos = new Vector2Int(Mathf.FloorToInt(rb.position.x), Mathf.FloorToInt(rb.position.y));
        Vector2Int TargetVec = new Vector2Int(Mathf.FloorToInt(Target.transform.position.x), Mathf.FloorToInt(Target.transform.position.y));

        GridManager gridManager = new GridManager(objPos, PathFindDis, obstacleLayer);
        Pathfinding pathfinding = new Pathfinding(gridManager);
        path = pathfinding.FindPath(objPos, TargetVec);
        targetIndex = 0;

        if (path != null && path.Count > 0)
        {
            StartMovingToNextNode(); // 여기서 isMoving = true가 됨
        }

       
    }
    }

        void StartMovingToNextNode()
    {
        Vector2Int gridPos = path[targetIndex].position;
        nextNodeWorldPos = new Vector3(gridPos.x + 0.5f, gridPos.y + 0.5f, transform.position.z);
        isMoving = true;
    }

   void IsStuck()
{
    if (Vector2.Distance(lastPosition, rb.position) < 0.01f)
{
    stuckTimer += Time.deltaTime;
    if (stuckTimer > 1f)
    {
        rb.linearVelocity = Vector2.zero;
        TryEscapeStuck();
        stuckTimer = 0;
    }
}
else
{
    stuckTimer = 0;
}
lastPosition = rb.position;
}

bool TryEscapeStuck(float probeDistance = 0.3f, int maxAttempts = 8)
{
    Vector2[] directions = {
        Vector2.up, Vector2.down, Vector2.left, Vector2.right,
        new Vector2(1,1).normalized, new Vector2(-1,1).normalized,
        new Vector2(1,-1).normalized, new Vector2(-1,-1).normalized
    };

    foreach (Vector2 dir in directions)
    {
        Vector2 checkPos = rb.position + dir * probeDistance;
        Collider2D hit = Physics2D.OverlapBox(checkPos, Vector2.one * 0.6f, 0, obstacleLayer);
        if (hit == null)
        {
            rb.position = checkPos;
            return true;
        }
    }

    return false;
}
}