3D 콘텐츠 제작

좀짓막(좀비 집짓고 막기) [#4] - 길찾기 알고리즘 이동에 적용

송현호 2023. 9. 27. 12:06

내가 참고한 사이트에서는 경로탐색을 PathRequestManager에 맡겨서 큐에 넣은 다음 순차적으로 처리하는 방법을 사용했다. 다른 사이트도 참고해봤는데 다들 큐로 사용하는 방식을 사용했다.

 

https://github.com/olokobayusuf/3D-A-Star-Pathfinding/blob/master/Pathfinding/PathRequestManager.cs

 

왜 큐를 사용하는지 궁금해서 챗gpt님에게 물어봤다

 

그래서 일단 같은 방법으로 PathRequestManager를 작성해보았다.

 

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

public class PathRequestManager : MonoBehaviour
{
    Queue<PathRequest> pathRequestQueue = new Queue<PathRequest>();
    PathRequest currentPathRequest;

    PathFinding pathfinder;
    bool isProcessingPath;

    static PathRequestManager instance;

    void Awake()
    {
        instance = this;
        pathfinder = GetComponent<PathFinding>();
    }

    struct PathRequest
    {
        public Vector3 pathStart;
        public Vector3 pathEnd;
        public Action<Vector3[], bool> callback;

        public PathRequest(Vector3 _pathStart, Vector3 _pathEnd, Action<Vector3[], bool> _callback)
        {
            pathStart = _pathStart;
            pathEnd = _pathEnd;
            callback = _callback;
        }
    }

    public static void RequestPath(Vector3 pathStart, Vector3 pathEnd, Action<Vector3[], bool> callback)
    {
        PathRequest newRequest = new PathRequest(pathStart, pathEnd, callback);
        instance.pathRequestQueue.Enqueue(newRequest);
        instance.TryProcessNext();
    }

    void TryProcessNext()
    {
        if (!isProcessingPath && pathRequestQueue.Count > 0)
        {
            currentPathRequest = pathRequestQueue.Dequeue();
            isProcessingPath = true;
            pathfinder.StartFindPath(currentPathRequest.pathStart, currentPathRequest.pathEnd);
        }
    }

    public void FinishedProcessingPath(Vector3[] path, bool success)
    {
        currentPathRequest.callback(path, success);
        isProcessingPath = false;
        TryProcessNext();
    }
}

음.. path를 만드는 부분까진 이해가 잘 됐는데 path를 받아서 처리하는 부분이 좀 복잡하다고 느껴졌다.

실행을 해보았는데 인스펙터상엔 문제가 없었는데 Nullreference가 뜨면서 작동하지않았다. 그래서 Debug를 찍으면서 문제점이 뭔지 다시 찾아 보니까 FindPath에 startNode와 targetNode에 값을 넣어주는 과정에서 문제가 발생하는 것 같았다.

좀 더 찾아보았더니 GetNodeFromWorldPoint에서 값을 전달하지 못하는 문제가 발생하는 것 같았다.

x,y값은 제대로 int값으로 나왔는데 grid[11,11]을 직접 찍어보았더니 디버그가 뜨지 않았다. 그럼 grid가 아직 생성되지 않았다는 뜻인데 설마 호출순서의 문제가인가 싶어서 AGrid 스크립트에서 CreateGrid()의 위치를 awake로 바꿔줬더니 정상적으로 잘 동작했다.

 

이런 종류의 문제는 처음 겪어봐서 당황했는데 스크립트를 작성할때 호출되는 순서를 신경쓰면서 작성해야 할 것 같다.

 

이제 스크립트를 수정해서 targetPos을 마우스 클릭위치로 받도록 수정할 생각이다.

근데 이번엔 에러가 난 건 아니지만 마우스로 찍은 위치보다 덜 움직이거나 움직이지 않는 현상이 나타났다. 이번에도 Debug를 찍어보면서 찾아봤는데 정말 사소한 실수였다. FollowPath() 메서드에서 targetIndex를 1씩 늘려가면서 패스를 이동하는데 targetIndex를 필드에 정의해놓았기 때문에 targetIndex가 초기화되지 않아서 발생한 문제였다... 

 

이젠 진짜 잘 움직임

그리고 마우스휠을 이용해서 카메라를 줌인 줌아웃하는 기능도 추가 했다.