몬스터 AI를 만들다 보니 단순히 플레이어를 보고 달려가서 공격하는 구조만으론 너무 기계적으로 보였다. 공격 모션 자체는 들어가지만, 전투가 뻣뻣하고 리듬감이 전혀 없다. 우리가 흔히 알고 있는 RPG게임의 전투는 이렇지 않다. 공격을 피했다가, 옆으로 게걸음 치듯 돌고, 다시 타이밍을 잡아 공격하는… 그런 살아있는 움직임.
그래서 EQS(Environment Query System)를 쓰기로 했다. EQS는 주변에 여러 후보 지점을 생성하고, 조건에 맞는 최적의 위치를 선택하게 한다. 즉, “이 상황에서 어디로 움직여야 전투가 자연스러워질까”를 AI 스스로 판단할 수 있는 구조.
사용방법
1. AI → Env Query 생성
그러면 아래와 같은 기능을 확인 할 수있다.
- Circle, Grid, Cone 등등
나는 플레이어 주변을 원형으로 돌도록 만들고 싶어서 Circle을 선택했다.
2. Add Test → 조건 설정
- 예: Distance(거리)를 조건으로 추가
3. EQS Test Pawn 생성
- 시각적으로 어떻게 동작하는지 확인하기 위함
그런 다음에 해당 BP에 아까 만들어 놓은 EQS를 세팅한다.
4. EnvQueryContext_BlueprintBase 생성
Query의 기준점을 정의하기 위해 필요
BP에서 GetActorOfClass 노드 사용 → Player Start 액터를 리턴하도록 세팅
Query에 대상을 Player Start 액터로 지정한다는 의미이다. (스샷에는 없지만 실행 링크까지 연결 해야함)
5. Circle Center에 Env Query 세팅
이렇게 하면 플레이어를 기준으로 Circle 포인트가 생성된다.
결과 확인
원형 구 위의 숫자는 점수다.
이 점수를 기준으로 액터가 어떤 위치로 이동할지 결정할 수 있다.
Behavior Tree에서Run EQS Query를 실행하고, Run Mode를 조정해서 이 점수를 활용한다.
말 그대로, 게임 엔진 전체를 관리하는 핵심 엔진 객체에 접근하기 위한 글로벌 핸들 느낌이라고 생각하면 될듯?
UEngine은 추상적인 엔진의 베이스 클래스이고, 실제 실행 중에는 UGameEngine같은 하위 클래스가 생성되어 GEngine에 할당된다.
언제 쓰는지
디버깅, 로그, 시스템 레벨 기능을 직접 호출할때 쓴다.
=> 주로 디버그, 프로토타입, 툴 제작할 때 활용
대표적 예시
AddOnScreenDebugMessage()
화면 위에 직접 텍스트를 띄워줌.
보통 플레이 중 디버깅을 할 때 "눈에 바로 보여야" 할 때 사용.
특징:
UI/HUD 위에 표시
에디터 PIE(Play In Editor) 환경에서 바로 확인 가능
key : -1 (새로운 라인에추가), 0(기존 라인에 덮어씌움)
출력되는 위치는 바꿀 수 없다.
=>
디버그/테스트만 GEgine쓰고, 실제 전역 컨텍스트는 UGameInstance, UWorld, GetGameInstance()->GetSubsystem<T>(), UEngineSubsystem/UGameInstanceSubsystem/UWorldSubsystem을 쓴다.
런타임에 쓰는 UObject나 Actor와 뭐가 다를까?
GEngine은 전역적으로 엔진 전체 관리 객체이고, Actor나 UObject처럼 게임 월드에 배치되는 개별 오브젝트가 아님,
특정 레벨에 속하지 않아서, 어디서든 접근이 가능한 점
Unity와 비교하면?
유니티에서 1:1로 대체할 전역 엔진 객체는 없는것 같다. 언리얼은 "큰 한 덩어리"를 전역 핸들로 접근하는 문화?가 있고, 유니티는 주요 시스템을 정적 클래스/네임스페이스로 분산한 느낌이다.