본문 바로가기
게임 프로그래밍/유니티 활용

[유니티 활용] 비주얼 스크립팅 - 적 인공지능 (Enemy AI)

by 레오란다 2023. 5. 9.
반응형

안녕하세요. 오늘은 유니티의 비주얼 스크립팅을 이용해 적의 인공지능을 만드는 방법에 대해 알아보도록 하겠습니다.

 

우선 적은 다음과 같은 행동 패턴을 갖도록 정의하겠습니다.

 

1. 플레이어를 발견하지 않은 상태에서는 생성된 지점에서 특정 반경안을 주기적으로 돌아다님

2. 플레이어를 발견하면 따라감

3. 플레이어와 특정 거리 이상 벌어지면 다시 생성된 지점으로 돌아가 1 번 상태가 됨

 

사용 컴포넌트

적 객체의 이동과 충돌체크를 위해 다음과 같은 컴포넌트를 사용합니다.

  • Nav Mesh Agent (적 캐릭터의 이동에 사용)
  • Rigidbody & SphereCollider (플레이어 캐릭터 감지에 사용)
  • State Machine (비주얼 스크립팅 작성에 사용)

 

Navigation 설정

Navigation 은 유니티에서 제공하는 길 찾기 기능입니다. 제 블로그의 다른 글에서 다룬 적이 있으니 여기서는 간단히 다루도록 하겠습니다. 

 

 

[유니티 활용] NavMeshAgent 사용법 (Simple Monster AI)

NavMeshAgent 는 유니티에서 제공하는 네비게이션 시스템입니다. 이 기능을 이용해 몬스터 객체가 플레이어 캐릭터를 자동으로 따라다니 게 하는 방법에 대해 알아보도록 하겠습니다. 플레이어 캐

ugames.tistory.com

 

Plane 객체를 바닥으로 사용할 것입니다. Plane 객체를 생성하고 아래와 같이 값을 설정합니다. 반드시 Static 에 체크를 해 주셔야 합니다.

 

Plane
바닥으로 사용할 Plane 객체 설정

 

이제 메뉴의 [Window > AI > Navigation] 을 선택하면 다음과 같이 Navigation 창이 나타나고 아래와 같이 Bake 버튼을 눌러 Baking 을 해줍니다. 이렇게 하면 적 객체가 Plane 위에서 길 찾기를 할 수 있게 됩니다.

 

Navigation Baking
Navigation Baking

 

적 객체 만들기

적 객체는 간단하게 Capsule 로 생성하고 이름을 Enemy 로 변경한 다음 다음과 같이 필요한 컴포넌트를 추가합니다.

Enemy 객체 생성 및 컴포넌트 추가
Enemy 객체 생성 및 컴포넌트 추가

  • State Machine: [Add Component > Visual Scripting > State Machine]
  • Nav Mesh Agent: [Add Component > Navigation > Nav Mesh Agent]
  • Rigidbody: [Add Component > Physics > Rigidbody]

이제 다음과 같이 자식 객체로 Sensor 를 달아줍니다. 이 Sensor 는 플레이어 감지에 사용됩니다.

Sensor 객체 생성
Sensor 객체 생성

 

 비주얼 스크립트 작성

State Machine 컴포넌트에 있는 New 버튼을 클릭해서 새로운 State Graph 에셋을 생성한 다음 [Edit Graph] 버튼을 클릭합니다. 

전체 State 모습
전체 State 모습

먼저 위의 그림에서 빨간 테두리와 같이 Object 변수를 생성합니다.

  • initPos: 적 객체의 시작 위치를 저장합니다.
  • target: 적 객체가 따라갈 대상 객체가 지정됩니다.

 

Start State

Start 는 비주얼 스크립트가 처음 시작할 때 수행되는 상태입니다. 다음과 같이 설정하면 객체의 초기 위치를 Object 변수인 initPos 에 저장합니다.

Start State의 비주얼 스크립트
Start State의 비주얼 스크립트

 

 Start > Idle Transition

Start 에서 Idle 로 가는 transition의 세부 설정은 다음과 같이 합니다. 적 객체는 Nav Mesh Agent 를 사용하고 있고 Destination 을 설정하지 않은 상태이기 때문에 On Reached Destination Event 가 발생하게 됩니다.

 

Start > Idle transition 설정
Start > Idle transition 설정

Idle State

Idle 상태에서는 Random 함수에 있는 InsideUnitCircle 을 이용해 적 객체가 생성된 위치 (initPos) 를 기준으로 2 Unit 반경의 임의의 위치로 이동합니다.

위의 관계식이 복잡해 보이지만 C# 수식으로 표현하면 다음과 같습니다.

var rndPos = Random.InsideUnitCircle;
var newPos = new Vector3(rndPos.x + initPos.x, initPos.y, rndPos.y + initPos.z) * 2f;

 

 Idle Self Transition

Self transition 은 State Box 를 선택하고 마우스 우클릭 > Make Self Transition 으로 생성할 수 있습니다.

Idle Self Transition
Idle Self Transition

Idle 상태에서 이동한 목적지에 도달하면 On Destination Reached 이벤트가 발생하고 이 transition 으로 들어오게 됩니다. 여기서 Wait For Seconds 를 이용해 0.5 초간 대기한 다음 다시 Idle 상태로 들어갑니다.

 

여기서 중요한 것은 Wait For Seconds 를 사용하기 위해  On Destination Reached 를 Coroutine 으로 만들어 주어여 하는 것입니다.  아래의 그림과 같이 On Destination Reached 박스를 클릭하고 Coroutine 항목을 체크해 주면 됩니다. 

 

Coroutine 설정
Coroutine 설정

 

Idle > Chase Transition

Idle 상태일 때 적 객체의 Sensor 에 Player 가 감지되면 On Trigger Enter 이벤트가 발생되어 이 transition 으로 들어오게 됩니다. collider 를 통해 감지된 객체의 이름이 Player 면 Object 변수인 target 에 Player의 transform 을 저장합니다.

Idle > Chase Transition
Idle > Chase Transition

 

Chase State

Chase 상태는 적이 플레이어를 발견하면 수행되는 상태입니다. 플레이어와의 거리가 6 이하면 계속해서 따라가고 6 이상이면 "LostPlayer" 이벤트를 발생시켜 다시 Idle 상태로 돌아갑니다.

Chase State
Chase State

 

 Chase > Idle Transition

Chase 상태에서 발생한 커스텀 이벤트인 "LostPlayer" 이벤트를 수신하게 되면 이 transition 으로 들어오게 되고 Idle 상태로 이동됩니다.

Chase > Idle Transition
Chase > Idle Transition

 

이상으로 비주얼 스크립팅을 이용한 적 AI 를 만드는 방법에 대해 알아보았습니다. Player 객체는 Capsule 객체를 만들고 Rigidbody 를 달아 준 다음 이름을 Player 로 하시면 됩니다. 유니티 에디터에서 게임을 실행한 다음 Scene 창에서 Player 객체를 직접 움직여서 로밍하고 있는 적 객체 근처로 가져가면 Player 객체를 따라오고 거리를 6 이상으로 벌리면 적 객체가 다시 멀어지게 됩니다.

 

실행 결과
실행 결과

 

반응형

댓글