Unity Engine

Behavior Tree - AI 이동 디테일

Aostols 2022. 7. 10. 15:23
반응형

AI 이동을 좀 더 쓸만하도록 수정하겠습니다.

AI 가 이동할떄 한번에 끝까지 이동하며 도중에 다른 판단을 하지 않게되면 매우 어색하기 때문에 중간중간 갈 위치를 정해두고 매번 다시 평가하는 구조로 만들었습니다.

 

NodeCanvas의 MoveToward의 경우 A포인트에서 B포인트까지 한번에 일정속도로 이동하게 되는데 이떄 시간이 3초 걸린다면 3초동안 다른 평가를 하지 않기 때문에 이상하게 됩니다.

이럴경우 0.5초 로 이동할 수 있는 거리만큼 거리를 계산하고 그만큼만 이동하고 다시 평가를 진행합니다.

 

우선 기존에 진행 하였던 것들에 이어서 진행하지만 많은 변경점이 있어서 전체적으로 다시 적었습니다.

 

CubeController.cs

public class CubeController : MonoBehaviour
{
    private GameObject currentTarget;
    private Vector3 currentDestination;
    private float speed = 3f;
    private float stepTime = 0.5f;
    public bool HasTarget;

    public GameObject CurrentTarget { get => currentTarget; set => currentTarget = value; }
    public Vector3 CurrentDestination { get => currentDestination; set => currentDestination = value; }
    public float Speed { get => speed; set => speed = value; }
    public float StepTime { get => stepTime; set => stepTime = value; }

    public void SetTarget(GameObject target)
    {
        CurrentTarget = target;
        HasTarget = (target != null);
    }

}

CubeController 는 get / set 으로 모두 감싸놨습니다.

Unity 의 고질적인 문제인 public 일 경우 변수가 Inspector에 뜨면서 값이 안바뀌는 문제가 있어서 그냥 속편하게 get/set 처리 했습니다.

speed 는 속도로 1초에 갈수 있는 유닛(유니티의 단위)으로 생각하였습니다

stepTime은 다시 계산하는 시간 단위입니다. 0.5라면 0.5초마다 다시 계싼하는 것 입니다.

SetTarget()이라는 메소드를 추가하여 타겟이 있는지 판안 여부 까지 추가 되었습니다.

 

 

 

CheckObject.cs

private CubeController cubeController;
protected override string OnInit(){
    cubeController = agent.GetComponent<CubeController>();
    return null;
}

protected override void OnExecute(){
    int max = 1;
    Collider[] results = new Collider[max];
    int resultNum = Physics.OverlapSphereNonAlloc(agent.transform.position, 10.0f, results, LayerMask.GetMask("Target"));

    for(int i=0; i< resultNum; ++i)
    {
        cubeController.SetTarget(results[i].gameObject);
    }
    EndAction(true);
}

NodeCanvas Action으로 기존에서 거의 변경되지 않았지만 CubeController 의 CurrentTarget 할당하는 부분을 바로 할당하지 않고 SetTarget을 호출하도록 변경 되었습니다.

 

 

 

MoveDestination.cs

private CubeController cubeController;
private float stepDistance;

protected override string OnInit(){
    cubeController = agent.GetComponent<CubeController>();
    return null;
}

protected override void OnExecute(){
    if(cubeController.HasTarget)
    {
        float distance = Vector3.Distance(agent.transform.position, cubeController.CurrentTarget.transform.position);
        stepDistance = cubeController.StepTime * cubeController.Speed;
        if(distance > stepDistance)
        {
            cubeController.CurrentDestination = agent.transform.position + ((cubeController.CurrentTarget.transform.position - agent.transform.position).normalized * stepDistance);
        }
        else
        {
            EndAction(true);
        }
    }
    else
    {
        EndAction(true);
    }

}

protected override void OnUpdate()
{
    float tempA = (agent.transform.position - cubeController.CurrentDestination).magnitude;

    if (tempA <= 0.1f)
    {
        Debug.Log("Finish Move");
        EndAction();
    }
    else
    {
        agent.transform.position = Vector3.MoveTowards(agent.transform.position, cubeController.CurrentDestination, cubeController.Speed * Time.deltaTime);
    }

}

새로 추가된 NodeCanvas Action입니다.

cubeController 얻는 법은 기존과 동일 합니다.

한틱에 실행이 끝나는 부분이 아니기 떄문에 OnExecute() 에서 EndAction()을 매번 호출하지 않고 OnUpdate()에서 EndAction()을 호출 해 주는 경우가 있습니다.

OnExecute()에서 stepDistance를 구하는데 1번의 계산으로 갈 수 있는 거리 입니다.

Speed는 1초동안 갈수 있는 거리고 StepTime은 계산하는 시간 단위 이기 때문에 이것으로 1계산으로 갈수 있는 거리를 얻을 수 있습니다.

실제 거리가 stepDistance가 보다 긴 경우는 계산으로 이동해도 되는 경우이고 stepDistance가 더 긴경우는 1번의 계산으로 이동하면 넘어가 버리는 경우라서 이동을 하지 않았습니다.

이 경우 추가적인 작업을 하지 않았지만 계산 시간을 줄이거나 하는 방법으로 보완을 해도 좋을 것 같습니다.

OnExecute() 에서 CurrentDestination을 구했다면 OnUpdate()에서 실질적인 이동을 처리하고 있습니다.

그리고 거리가 0.1f이하라면 EndAction()을 호출 해 줍니다.

 

Behaviour Tree 와 Blackboard

 

실행을 해 본다면 잘 동작하는 것을 볼 수 있습니다.

물론 시간이 100%일치하지는 않을것 이지만 대충 이러한 느낌으로 발전하면 좀 더 자연스러운 AI를 만들 수 있을 것 입니다.

반응형

'Unity Engine' 카테고리의 다른 글

[Unity]CollisionFlag - CharacterController  (0) 2022.11.06
[Unity]Physics 와 Layer  (0) 2022.11.01
Behavior Tree - Custom Action  (0) 2022.07.07
Behavior Tree - Node Canvas (2)  (0) 2022.07.02
Behavior Tree - Node Canvas (1)  (0) 2022.06.29