AI Navigation System

정혜창·2025년 4월 23일

내일배움캠프

목록 보기
46/64
post-thumbnail

내일배움캠프 ch.5로 AI를 배우게 되었다.
여태 프로젝트를 진행하면서 GameMode(Gameflow logic), Character, Animation 을 담당했었고 AI는 다루지 않아서 꼭 배우고 싶었는데 마침 수강할 수 있게 되어 기쁘다.

🎮 AI

1️⃣ 필수요소

언리얼에서 AI를 구동하기 위해서는 삼총사가 필요하다.

  • AI Controller :

    • AI를 제어하는 클래스, AAIcontroller를 상속받아 사용
    • Behavior Tree 실행 여기에서 시작
  • Behavior Tree

    • AI의 행동 플로우를 시각적으로 보여주는 곳
  • Blackboard

    • AIController와 Behavior Tree 사이에서 AI의 의사결정에 필요한 정보를 주고 받도록 도와주는 데이터 저장소이다.


2️⃣ Navmesh Bound Volume

NavMeshBoundVolume은 AI의 이동 가능 영역을 정의 해주는 볼륨. 네브메시의 시각화 및 비시각화 옵션을 활용해서 정상 동작을 직접 검증/평가 할 수 있다.

📌 생성

  • 생성 후 'P' 를 누르면 이동가능한 영역은 초록색으로 보여지는 것을 볼 수 있다.

🔥 NavMesh는 Scale이 아니라 Brush크기를 활용해 레벨 내 적용되는 지오메트리를 결정한다.
따라서 Location을 변경한다던지, Rotation이나 Scale값을 변경해서 AI가 갈 수 있는 곳과 갈 수 없는 곳을 엔진 아키텍쳐상 동적으로 설정할 수 없다. 그러나 Project Setting 에서 Navmesh의 Runtime Generation을 Dynamic을 설정함으로써 타의 오브젝트를 통해 AI의 이동영역을 통제할 순 있다.


📌 Dynamic

  • 동적으로 변형이 되게 하기 위해서는 프로젝트 세팅에서 바꿔야 되는 설정이 있다.
    • 프로젝트 세팅 → Engine → Runtime → Static에서 Dynamic으로 변경
  • 다음과 같이 시뮬레이션을 했을 때 동적으로 변형 및 생성이 되는 것을 볼 수 있다.

🔥 Dynamic 설정을 이용해서 Navmesh안에 Engine에 있는 오브젝트가 들어갔을 때 Navmesh의 영역이 새로 확장되는 것을 볼 수 있다.

  • Static으로 설정되었을 때는 Navmesh가 오브젝트에 전혀 상관이 없는 것을 볼 수 있다.

📌 Dynamic Modifiers Only

  • Dynamic Modifiers Only 설정을 적용하기 위해서는 Obstacle 역할을 하는 오브젝트 안에 NavModifier Component를 추가해야한다.
  • 추가하고 해당 Component의 Detail Pannel의 Navigation 카테고리에서 NavArea 설정을 해줄 수 있다.
  • NavArea_Null로 설정하고 Project설정에서 DynamicModifiers Only로 설정한뒤 살펴보면 다음과 같이 동적으로 설정된다. 🔥 Dynamic 설정과는 다르게 Navmesh가 액터의 이동에 따라 없어지기만 할 뿐 따로 재생성되는 구역이 없다. DynamicModifiers Only는 빼기의 성격이 강함.


3️⃣ Navigation Invoker

Invoker = 명사 : 호출자, 초대자

Dynamic 설정을 통해 일부분 못지나가거나 새로 이동 가능한 구역을 타의 오브젝트위로 설정을 할 순 있지만 Mesh 자체의 이동과 사이즈가 동적으로 변경이 불가능하기 하다. 그래서 맵 전체를 Navmesh Bound Volume로 덮어야 하는가? 하는 의문이 생기게 된다. 이것은 플레이어가 가지않는 부분도 Navmesh 영역으로 설정될 수 있기 때문에 매우 비효율적이고 최적화의 관점에서도 좋지 않다. 이런 부분을 회피할 수 있는 기능이 Navigation Invoker이다.

Navigation Invoker는 Navigation Invoker라는 컴포넌트를 가진 액터의 주변 영역만 연산해서 리소스를 아끼고, 게임 플레이는 문제없이 가능하게 하는 기능이다.

📌 컴포넌트 및 모듈 추가

캐릭터 클래스에 Navigation Invoker Component를 추가하여야한다.

📋 AI_TestCharacter.h
// 헤더 추가
#include "NavigationInvokerComponent.h"
.
.
.

class AAI_TestCharacter : public ACharacter
{
	GENERATED_BODY()
    .
    .
    
	/** Navigation Invoker component */
	UPROPERTY(BlueprintReadWrite, Category = "Navigation", meta = (AllowPrivateAccess = "true"))
	UNavigationInvokerComponent* NavInvoker;
    .
    .
    
public:
	AAI_TestCharacter();

	float NavGenerationRadius;

	float NavRemovalRadius;

	/** Returns NavInvoker subobject **/
	FORCEINLINE class UNavigationInvokerComponent* GetNavInvoker() const { return NavInvoker; }
}
  • NavigationInvokerComponent.h 헤더파일 추가
  • 기본적으로 접근지정자를 명시하지 않으면 class의 경우 private가 디폴트이다. 따라서 블루프린트에서 private멤버에 접근하기 위해 메타데이터를 명시 meta = (AllowPrivateAccess = "true")
  • Invoker 크기를 설정해주기 위해 NavGenerationRadius(생성 반경), NavRemovalRadius(제거 반경) 선언
  • FORCEINLINE은 강제로 인라인 처리를 하도록 컴파일러에 지시하는 매크로
📋 AI_TestCharacter.cpp
생성자에 추가

// 활성화될 범위 설정. 테스트를 위해 매우 작은 값 부여. 
NavGenerationRadius = 10.0f;
NavRemovalRadius = 15.0f;

// Navigation Invoker 컴포넌트 생성 및 초기값 셋업.
NavInvoker = CreateDefaultSubobject<UNavigationInvokerComponent>(TEXT("NavInvoker"));
// SetGenerationRadii 함수를 사용하여 생성 반경과 제거 반경 설정. Protected 멤버변수이므로 함수를 통해 수정 필요.
NavInvoker->SetGenerationRadii(NavGenerationRadius, NavRemovalRadius); 
📋 AI_Test.Build.cs
using UnrealBuildTool;

public class AI_Test : ModuleRules
{
	public AI_Test(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

		PublicDependencyModuleNames.AddRange(new string[] {
        "Core",
        "CoreUObject",
        "Engine",
        "InputCore",
        "EnhancedInput",
        "NavigationSystem"
        });
	}
}
  • Navigation System을 사용하기 위해서는 아래와 같이 빌드파일에 Navigation System 모듈을 추가해야한다.

해당 C++ 클래스를 상속받는 블루프린트 Character의 컴포넌트에 Nav Invorker가 추가된것을 확인할 수 있다.


📌 Project Setting

🔥 주의

  • Navigation Invorker를 사용하기 위해선 Project Setting에서 이전에 Navmesh Runtime 설정을 바꾼 것 처럼 Dynamic으로 설정해주어야 한다.
  • 또한 Project Setting에서 Nevigation System 탭에서 Nevigation Enforcing 카테고리에 Generated Navigation Only Around Navigation Invorker를 True로 설정한다.

📌 확인

Navigation Invorker는 우선 Navmesh 안에서 Invorker 주변에 AI 이동영역을 계산하여 활성화하는 형식이다.
따라서 NevmeshBoundVolume 의 크기를 늘리고 Invorker Component를 가지고있는 캐릭터를 이동하면 이동영역이 활성화 되는 곳이 바뀌는 것을 확인할 수 있다.

👉 Navmesh가 레벨 전체를 감싸고 있더라도 실제로 연산되는 구역은 Invorker를 가지고 있는 주변으로만 제한되기 때문에 훨씬 효율적이라고 볼 수 있다.

  • play 이후 시뮬레이션에서 ai가 알아서 움직이게 하기 위해서 블루프린트 로직을 추가해보았다.

    이동 할때마다 navigation brush 영역이 바뀌면서 알아서 순찰이 잘 되는 모습이다.

profile
Unreal 1기

0개의 댓글