인공지능 - 행동트리 모델의 구현

Unreal 이론|2024. 11. 11. 15:52

[이득우의 언리얼 프로그래밍 Part2 수업의 정리]

 

패트롤 기능 구현

  • Blackboard에서 Vector Key인 PatrolPos 추가
  • 새롭게 스폰한 NPC가 새로운 섹션에서 랜덤으로 정찰할 포지션을 지정하기 위해 네비게이션 메쉬 볼륨 추가
  • Place Actor->Volume->NavMeshBoundsVolume 추가

NavMesh 구축 후 뷰포트에서 P키를 누르면 초록색으로 길찾기를 수행가능한 영역이 표시된다
동적으로 맵이 추가되기 때문에 NavMesh의 설정 중 Runtime Generation 옵션을 Dynamic으로 변경

  • Dynamic으로 설정을 변경하면 스폰 액터를 통해 생성된 섹션도 NavMesh를 사용가능
  • 행동 트리 설계를 위해 Build.cs에 NavigationSystem, AIModule, GameplayTasks 세개의 모듈 추가
// BTTask_FindPatrolPos.cpp

EBTNodeResult::Type UBTTask_FindPatrolPos::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
	EBTNodeResult::Type Result = Super::ExecuteTask(OwnerComp, NodeMemory);

	APawn* ControllingPawn = OwnerComp.GetAIOwner()->GetPawn();
	if (nullptr == ControllingPawn) {
		return EBTNodeResult::Failed;
	}

	UNavigationSystemV1* NavSystem = UNavigationSystemV1::GetNavigationSystem(ControllingPawn->GetWorld());
	if (nullptr == NavSystem) {
		return EBTNodeResult::Failed;
	}

	FVector Origin = OwnerComp.GetBlackboardComponent()->GetValueAsVector(BBKEY_HOMEPOS);
	FNavLocation NextPatrolPos;

	if (NavSystem->GetRandomPointInNavigableRadius(Origin, 500.0f, NextPatrolPos)) {
		OwnerComp.GetBlackboardComponent()->SetValueAsVector(BBKEY_PATROLPOS, NextPatrolPos.Location);
		return EBTNodeResult::Succeeded;
	}

	return EBTNodeResult::Failed;
}
  • 다음 정찰 위치를 찾는 태스크 추가

위와 같이 하드코딩을 통해 구현한 내용을 빌드 후 확인해보면 NPC가 제대로 움직인다.

이제 해야할건 인터페이스에 NPC가 가져야 할 내용을 구현한 후 뿌려주는것.

  • NPC 헤더를 직접 참조하지 않고 인터페이스를 통해 간접적으로 필요한 값을 얻어오도록 구조 수정
  • AIInterface 클래스에 필요한 값을 가져오는 가상함수를 추가 후 NonPlayer클래스에서 그 함수를 구현, PatrolPos 클래스에서 인터페이스를 캐스팅 해 그 함수를 가져와 간접적으로 값을 얻는 구조

  • BTService 클래스를 상속받은 유저감지 Detect 노드 추가
  • 서비스를 부착한 컴포짓 노드가 활성화 되면 TickNode가 지정한 Interval로 계속해서 호출된다.
  • 내용물을 구현하려면 TickNode에 구현해서 Interval마다 구현한 작업을 수행하도록 구성

구현한 Detect 서비스를 Sequence 노드에 부착

  • BlackBoard에 Target 변수 생성, 타입 Pawn으로 지정
  • 여기까지 한 후 실행을 눌러보면, NPC의 감지 반경과 감지 성공시 플레이어와의 거리가 뷰포트에 출력되는걸 확인 가능

  • 플레이어를 쫓아가서 공격하도록 Selector 추가
  • 언리얼 엔진이 기본으로 제공하는 Blackboard 데코레이터 부여, Key값을 Target으로 지정해 타겟이 설정되있을때만 셀렉터 컴포짓이 수행되도록 설정
  • 이후 Attack, AttackInRange 함수 구현.
  • 델리게이트로 NonPlayer에서 공격하는 로직이 호출되도록 구성
  • NPC도 플레이어처럼 PressCombo 함수를 호출해주고, 콤보가 끝나는 타이밍을 계산하기 위한 함수 CharacterBase에 추가
  • 과정이 꽤 길고 다양한 클래스들을 수정해 코드를 넣진 못했지만, CharacterBase에 공격이 끝난것을 알려주는 가상 함수를 선언하고 ComboActionEnd 함수 마지막에 호출되도록 추가 -> 가상함수는 NonPlayer 클래스에서 받아서 구현한 후 Attack 클래스에서 델리게이트를 묶어줘서 흐름이 굴러가게끔 설계
  • 빌드 후 실행해보면 캐릭터를 잘 쫓아와서 공격하지만, 캐릭터가 쓰러진 후에도 계속해서 공격 -> 셀렉터에 Detect 서비스 추가하면 캐릭터가 쓰러진 후 타겟이 없어지므로 해결

  • 캐릭터가 NPC 공격 중 회피를 했지만 NPC가 몸을 돌리지 않고 처음 공격 방향으로만 공격하는 현상 발생
  • BTTask 노드 추가 - TurnToTarget 클래스 생성해 이를 해결

  • Simple Parallel 컴포짓으로 Selector를 대체하고, Turn to Target 노드 추가
  • 이후 실행해보면 공격하며 동시에 타겟으로 회전하는 NPC를 확인할 수 있다.

'Unreal 이론' 카테고리의 다른 글

게임 플로우 다듬기  (1) 2024.11.21
헤드업디스플레이의 구현  (0) 2024.11.14
인공지능 - 행동트리 모델의 이해  (2) 2024.11.10
게임데이터 관리  (0) 2024.11.06
무한 맵의 제작  (0) 2024.10.31

댓글()