[UE5] 적 AI 만들기 (2)

재석 블로그·2025년 3월 9일

AI Perception 컴포넌트

AI Perception 컴포넌트는 이름 그대로 AI에게 인지능력을 주는 컴포넌트이다. 이 프로젝트에선 시각, 청각, 대미지를 인지할 수 있도록 하였다.


  • 각 감각별로 인지 거리, 유효 시간, 디버그 컬러 등을 설정할 수 있다.
  • 게임에서 ' 키를 누르면 AI Debugger가 실행되고, Num pad 4를 누르면(넘패드에서 눌러야 함) 위에서 설정한 AI Perception 컴포넌트를 시각적으로 확인할 수 있다.
  • 적의 시야에 플레이어와 다른 적 캐릭터가 들어와 위치에 디버그 스피어가 표시되고 있다.

  • Report Noise Event/Report Damage Event - AI Perception 컴포넌트에게 각각 소음과 대미지 이벤트를 알리는 노드. 실질적으로 소음과 대미지가 발생하는 것은 아니다. 소음과 대미지의 실질 적용은 Make NoiseApply Damage로 한다.

이벤트 바인딩하기

  • AI Perception 컴포넌트를 이용해 컨트롤러는 자극을 감지할 수 있다. 이벤트그래프에서 자극을 감지하면 어떻게 반응할 지 설정해야 한다.


On Perception Updated(AIPerception)

  • AI Perception 컴포넌트에서 자극을 감지했을 때 발생하는 이벤트.
  • 이벤트를 감지하면 자극의 종류에 따라 설정된 함수를 호출한다.

Can Sense Actor


  • 적이 액터(플레이어)를 인식할 때 어떤 자극에 의해 감지하는지를 결정하는 함수
  • 어떤 감각으로 플레이어를 인지했는지, 플레이어를 인지하는 것에 성공했는 지를 반환한다.
  • Get Actor Perception 노드로 액터의 정보를 받아오고, 받아온 정보와 Enum으로 정의해둔 감각 리스트(AI Sense Hearing, AI Sense Damage, AI Sense Sight)와 동일하다면 해당 감각과 인지 여부를 반환한다.

  • 이후 각각의 감각을 느꼈다면 감각을 느꼈을 때의 핸들을 호출하게 된다.

Handle Sensed Sight/Sound/Damage

  • 핸들 함수는 상황에 따른 상태에 접근하는 역할을 한다. 공통적으로 현재 적의 상태를 확인한 후(Get Current State(인터페이스 함수)), 현재 상태에 따라 상태를 변화 시킨다.


HandleSensedSight - 발견한 액터가 플레이어라면, Passive/Stunned/Investiagting 상태일 때 적 캐릭터를 공격 상태로 전환하며 공격 목표로 플레이어를 지정한다.

HandleSensedSound - Passive/Investigating 상태일 때 청각 자극이 주어지면 적 캐릭터를 탐색 상태로 만들며, 자극이 발생한 장소를 Location으로 전달한다.




Environment Query System(EQS)

  • EQS는 플레이어와의 거리, 주변 환경, 시야 등을 종합해 적이 움직일 장소를 고르는 것에 사용된다.
  • 해당 프로젝트에선 3가지에 EQS를 사용했다.
  1. 근접 적이 플레이어를 공격 후 다음 공격 쿨타임까지 옆걸음
  2. 원거리 적이 플레이어를 공격 후 플레이어와 가장 멀면서 시야는 보이는 곳으로 이동
  3. 원거리 적의 체력이 일정 비율 이하일 때, 플레이어에게 안보이는 가장 가까운 곳으로 도망
  • 위 사진의 초록색 구체들을 보면 숫자가 쓰여있는 것을 볼 수 있는데, 이것이 사용자가 입력한 조건에 따라 EQS가 평가한 점수이다. AI는 이 점수가 가장 높은 곳으로 이동하게 된다. (조건에 따라 가장 높은 곳, 상위 25% 점수 내에서 무작위 등등 가능하다.)

Strafe EQS 만들기


  • 근접 적의 패턴. 컨텍스트(플레이어) 주위 원형으로 포인트가 생성되고, 적은 이 포인트를 따라 횡이동 한다.

OnCircle : ...

  • 위 사진처럼 컨텍스트 주변 원형으로 포인트가 생성된다.
  • 원의 반지름과 포인트의 개수를 지정 가능
  • 기본값은 Querier 주변으로 포인트가 생성되는 건데, 우리가 원하는 것은 플레이어 주변으로 생성되는 것이기 때문에 컨텍스트를 AttackTarget, 즉 플레이어로 지정하도록 컨텍스트를 새로 만들어야 한다.

PathExist: from Querier

  • 길찾기 조건을 추가하는 것. Querier가 도달할 수 있는 곳으로만 이동하게 한다. 도달할 수 없는 곳은 버려진다.

Distance: to Querier

  • 거리 조건을 추가하는 것. 적 캐릭터 기준 150 ~ 500 거리에 포함되는 곳으로만 이동하게 한다. (제자리에서 가만히 있는 것을 방지함)

Context 조건 새로 만들기


  • 새 블루프린트 클래스 만들기로 EnvQueryContext_BlueprintBase를 선택하여 만들어준다.
  • Return 노드에서 반환하게 되는 Resulting Actor가 컨텍스트가 된다. 우리가 원하는 것은 플레이어가 컨텍스트가 되는 것이니 AI Controller에서 이미 사용하고 있는 AttackTarget을 불러와 지정해준다.
  • 위 연결되어 있지 않은 노드는 테스트용 노드. 플레이어가 아닌 EQS TestPawn이라는 클래스(별도로 존재함)를 컨텍스트로 만드는 용도. EQS를 시각화하여 테스트해볼 수 있다.

FindCover EQS 만들기


  • 원거리 적의 도망 패턴. 일정 체력 이하라면 컨텍스트에서 안보이는 곳이며 최단 거리(최대효율) 도망간다.
  • 처음 스크린 샷처럼 넓은 범위를 커버한다. around Querier 이므로 그리드는 적 주변에 펼쳐지게 될 것이다.

PathExist: from Querier

  • 앞의 Strafe 와 동일한 조건. 갈 수 없는 곳은 선택하지 않는다.

Trace: to Context on Visibility

  • 시야 조건. 플레이어가 시야에서 보이지 않아야 한다.
  • 컨텍스트에게 라인 트레이스를 해서 안맞는 거리를 설정한다. 아래 Filter에서 Bool Match 옵션을 체크 해제하면 반대로 컨텍스트에게 라인트레이스가 가능한 거리만 선택하게 된다.

Distance : to Querier

  • 플레이어와의 거리 조건. 가까울 수록 좋게 설정되어 있다. 최단 거리를 이동하는 이유는 최대한 벽에 딱 붙으며, 효율적 동선을 갖도록 하기 위함이다.
  • 테스트 결과를 점수로만 결정하도록 하고, 옵션을 Inverse Linear로 바꾸면 멀 수록 낮은 점수를 갖게 된다. (Constant는 거리 상관없이 같은 점수, Linear는 멀 수록 높은 점수)


FindIdealRangedLocation EQS 만들기

  • 원거리 적의 공격 후 패턴, 공격 후 가만히 있지 않고 플레이어가 시야에 보이면서 가장 먼 곳으로 이동한다. EQS Strafe와 비슷한 역할

SimpleGrid: generate around Context

  • 컨텍스트 주변으로 서로 200 간격인 포인트를 생성

PathExist: from Querier

  • 위와 동일함. Querier(적)가 갈 수 없는 곳은 버린다.

Trace: to Context on Visibility

  • FindCover와 같다. 컨텍스트(플레이어)로 라인 트레이스를 하여 적중하는 곳을 기준으로 한다. 차이점이라면 플레이어가 보이는 곳이어야 하기 때문에 Bool Match 옵션을 체크 해제.

Distance: to Context / to Querier

  • 첫 번째는 플레이어로부터 멀 수록 높은 점수(Linear)가 배정된다.
  • 두 번째는 본인의 현재 위치에서 최소 250 이상 떨어진 곳을 선택하는 것이다. 이 최소값 조건을 통해 한 자리에 가만히 있지 않고 계속 이동하도록 할 수 있다.

Behavior Tree에서 적용하기

이렇게 만든 EQS는 위처럼 Run EQS Query 노드를 통해 사용할 수 있다.

  1. Query Template 에 사용할 EQS를 설정
  2. EQS의 결과를 저장할 블랙보드 키(미리 만들어놨어야 함)를 지정 (EQS 자체가 이동 장소를 잡기 위한 시스템이기 때문에 벡터 타입의 키로 생성한다.)
  3. 위 사진에서는 PointOfInterest에 EQS의 결과가 되는 위치 벡터를 저장해놓았고, 바로 다음 MoveTo 노드에서 해당 블랙보드 키를 이용해 이동하게 하였다.
profile
게임 개발자 재석의 블로그입니다.

0개의 댓글