Chapter 7-5. AI : Navigation AI

Date:     Updated:

카테고리:

태그:

인프런에 있는 케이디님의 [유니티 3D] 실전! 생존게임 만들기 - Advanced 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click

Chapter 7. 동물들의 공격형 AI, 도망형 AI 구현

🚖 Nav Mesh Agent 컴포넌트

장애물, 혹은 갈수 없는 곳을 스스로 인식하고 피해가게 한다.

이전까지 직접 스크립트에 의하여 돼지를 움직이게 했을 땐, 돼지가 장애물이 있더라도 장애물을 뚫으려고 하고 장애물을 피해가지 않았었다. 장애물을 인식 처리를 못해서 그냥 가야할 방향으로 가려고만 했기 때문이다. 👉 Nav Mesh Agent 를 사용하여 돼지가 장애물을 스스로 인식하도록 만들기.

  • Nav Mesh Agent 을 통하여 스스로
    • 장애물을 인식한다.
    • 못 갈 것 같은 곳이면 가지 않는다. (너무 좁은 곳이라거나 등등)

Pig에게 Nav Mesh Agent 컴포넌트 추가

image

원기둥 같은 이 영역의 크기를 기준으로 돼지가 통과할 수 있는 곳 인지를 연산하게 된다. 이 원기둥이 돼지의 Nav Mesh Agent 이다. Nav Mesh Agent는 돼지에게 붙어 다니며 이 Nav Mesh Agent 크기를 바탕으로 갈 수 있는 곳인지 없는 곳인지를 체크한다.

image

image

돼지 오브젝트 크기에 맞게 설정해주었다.

  • Base Offset
    • Nav Mesh Agent이 Y 축 방향 위치.
  • Radius
    • Nav Mesh Agent 반지름
  • Height
    • Nav Mesh Agent 높이


🚖 Navigation : 돼지가 갈 수 있는 곳 설정

Window - AI - Navigation - Bake

Bake 구워서 현재 Terrain 에서 Nav Mesh Agent가 갈 수 있는 곳 연산.

image

구우니 이런 결과가 나왔다. 파란색 영역들은 돼지. 즉 Nav Mesh Agent 가 갈 수 있는 지역이다. 너무 가파르거나 도달할 수 없는 지역은 파란색이 적용되지 않았다. 파란색이 적용되지 않은 부분은 장애물로 판단한다. Step Height로 장애물로 판단할 경사를 수정할 수 있다.

Nav Mesh Agent가 붙어 있는 오브젝트는 Bake 된 파란 지형들만 갈 수 있다.


장애물로 판단할 오브젝트 설정

image

돼지가 나무와 돌 오브젝트를 장애물로 판단하고 피해갈 수 있도록 할 것이다.

  • 나무와 돌 오브젝트를 static 에서 Navigation static으로 변경해준다.
    • 자식들까지 전부 적용
  • Navigation - Bake 에서 다시 구워준다.

image

나무와 돌을 장애물로 인식하게 되었기 때문에, 나무와 돌 주변은 더 이상 파란색이 아니다. 이 부분은 이제 Nav Mesh Agent가 가지 못한다. Bake 구울 때 Agent Radius 값을 크게 하면 이 나무와 돌 주변에 파랗지 않은 영역이 더 넓어진다.


🚖 SetDestination : Nav Mesh Agent 에 의한 이동으로 바꾸기

📜Animal.cs

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

public class Animal : MonoBehaviour
{
    protected Vector3 destination;  // 목적지

    // 필요한 컴포넌트
    protected NavMeshAgent nav;

    protected void Start()
    {
        currentTime = waitTime;   // 대기 시작
        isAction = true;   // 대기도 행동
        theAudio = GetComponent<AudioSource>();
        nav = GetComponent<NavMeshAgent>();
    }

    protected void Update()
    {
        if (!isDead)
        {
            Move();
            ElapseTime();
        }
    }

    protected void Move()
    {
        if (isWalking || isRunning)
            nav.SetDestination(transform.position + destination * 5f);
            
            //rigid.MovePosition(transform.position + transform.forward * applySpeed * Time.deltaTime);
    }

    protected virtual void ReSet()  // 다음 행동 준비
    {
        isAction = true;

        nav.ResetPath();

        isWalking = false;
        anim.SetBool("Walking", isWalking);
        isRunning = false;
        anim.SetBool("Running", isRunning);
        nav.speed = walkSpeed;

        destination.Set(Random.Range(-0.2f, 0.2f), 0f, Random.Range(0.5f, 1f));
    }

    protected void TryWalk()  // 걷기
    {
        currentTime = walkTime;
        isWalking = true;
        anim.SetBool("Walking", isWalking);
        nav.speed = walkSpeed;
        Debug.Log("걷기");
    }
}

Rigidbody 보다 Nav Mesh Agent 가 우선시 되기 때문에, Nav Mesh Agent 컴포넌트가 붙게 되면 더 이상 rigid.MovePosition, rigid.MoveRotation 함수로 이동, 회전 할 수 없게 된다. ⭐이 Rigidbody 함수들이 freeze 되어 먹히지 않는다.⭐ 따라서 돼지를 Nav Mesh Agent 전용 이동 함수를 사용하여 이동시켜야 한다. 👉 SetDestination(Vector3)

  • nav.SetDestination(Vector3)
    • 인수로 들어간 Vector3 를 목적지로 하여 그 위치로 Nav Mesh Agent(돼지)가 이동하게 한다.
      • 해당 목적지로 이동하기 위해 새로운 Path 경로를 최단경로로 찾아 설정한다.
    • 이 함수를 사용하면 회전도 자동으로 이루어진다. 목적지를 바라보도록 자연스럽게 회전도 같이 이루어짐.
      • 따라서 Rotation() 함수는 이제 지워주었다.
    • 해당 목적지로 갈 수 있는 최단 경로로 이동한다.
      • Bake 한 지형들을 바탕으로 해당 목적지까지의 최단 경로를 계산 함.
    • 이동 속도 값은 Nav Mesh Agent 컴포넌트에 속성으로 있는 최대 이동 속도 Speed, 회전 속도 Angular Speed 값을 속도로 하여 목적지로 알아서 이동한다.
  • nav.ResetPath()
    • SetDestination(Vector3) 함수로 인하여 현재 설정되어 있던 경로를 지운다.
      • 이에 따라, 현재 이동중이었다면 이동을 멈추게 된다.
    • 해당 Nav Mesh Agent는 새로운 SetDestination(Vector3) 호출이 있을 때까지 경로를 찾지 않는다. 이동도 하지 않는다.

Nav Mesh Agent는 Bake 된 지형을 기반으로, 이동시 최단 거리를 찾아 이동하게 한다. 목적지만 SetDestination 함수에게 알려주면, 알아서 그 목적지로 회전하고 이동한다. 그것도 최단 경로로! 이동 회전 ‘속도’값은 컴포넌트에서 설정할 수 있다.

  • Start
    • nac 에 Nav Mesh Agent 컴포넌트 로딩
  • Update
    • Rotate 함수는 삭제하였다. 더 이상 사용하지 않음.
      • Nav Mesh Agent의 SetDestination 함수로 해당 목적지로 이동시킬 때 회전도 자동으로 같이 하기 때문이다.
  • Move
    • 이제 rigid.MovePosition 가 아닌 nav.SetDestination을 사용한다.
    • Nav Mesh Agent가 인수에 해당하는 해당 목적지로 최단 경로로, 컴포넌트에서 설정되있는 속도 값으로, 알아서 회전하고 알아서 이동한다. 목적지를 향하여.
      • 목적지 👉 돼지의 위치에서 destination * 5f 만큼 떨어진 곳
        • destination 값은
          • 그냥 TryWalk 상태일 경우
            • 랜덤한 x, z 위치를 가진 벡터
          • Run 상태일 경우 (플레이어로부터 도망갈 때)
            • (플레이어👉돼지) 방향 벡터로 설정 in 📜WeakAnimal.cs
  • Reset
    • 현재 Nav Mesh Agent가 목적지로 가기 위해 이동중이었을 경우를 대비하여 nav.ResetPath() 더 이상 이동하지 않도록 리셋.
    • TryWalk 상태를 대비하여 이제 랜덤한 방향으로 걸어야 하므로 destination을 새롭게 설정한다.
      • 랜덤한 x, z 위치를 가진 벡터
  • TryWalk()
    • Nav Mesh Agent의 이동 속도를 walkTime 으로
      • nav.speed = walkSpeed


📜WeakAnimal.cs


public class WeakAnimal : Animal
{
    public void Run(Vector3 _targetPos)
    {
        destination = new Vector3(transform.position.x - _targetPos.x, 0f, transform.position.z - _targetPos.z).normalized;

        currentTime = runTime;
        isWalking = false;
        isRunning = true;
        nav.speed = runSpeed;

        anim.SetBool("Running", isRunning);
    }

}
destination = new Vector3(transform.position.x - _targetPos.x, 0f, transform.position.z - _targetPos.z).normalized;

nav.speed = runSpeed;
  • 도망가는건 약한 동물들 뿐
  • 도망갈 떄 목적지
    • (플레이어👉돼지) 플레이어가 돼지를 향하는 방향으로 도망가야 한다.
    • normalized를 1 로 하여 크기를 1 로 하였고 추후 Move 에서 목적지에 5 를 곱하니, 거리 5 로 도망가게 될 것이다.
  • 도망갈 때 이동 속도는
    • nav.speed = runSpeed


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Unity Lesson 3 카테고리 내 다른 글 보러가기

댓글 남기기