최종 프로젝트 - AI Spline이동

정혜창·2025년 5월 12일

내일배움캠프

목록 보기
54/64
  • 현재 상태 분석
    • Monster 클래스에 SplineComponent가 있음

    • Monster 클래스에 TargetLocation, PatrolIndex를 갱신하고 있음

      // 가져온 PatrolIndex를 바탕으로 SplinePoint의 GetLocation을 통해 TargetLocation 반환
      FVector AMonster::GetPatrolLocation(int32 Index) const
      {
      	if (!PatrolSpline || PatrolSpline->GetNumberOfSplinePoints() == 0) return GetActorLocation();
      
      	// Get SplinePoint to World Location
      	FVector Location = PatrolSpline->GetLocationAtSplinePoint(Index, ESplineCoordinateSpace::World);
      	return Location;
      }
      
      // PatrolIndex를 호출할 때마다 1씩 증가시키고 계속 순환하는 방식 PatrolIndex를 갱신하여 반환한다.
      int32 AMonster::GetNextPatrolIndex(int32 CurrentIndex) const
      {
      	CurrentIndex = (CurrentIndex + 1) % PatrolSpline->GetNumberOfSplinePoints();// Cycle
      	LOG(TEXT("PatrolIndex increment : %d", CurrentIndex));
      
      	return CurrentIndex;
      }
    • 도착하면 TriggerMovementFinished()가 호출되도록 BlueprintCallable 함수를 만듦.

      • TargetLocation, ActorLocation 의 Dist를 구해서 Dist < 100 이면 도착했다고 판정함 (BP 내부에 구현되어 있음)
    • TriggerMovementFinished()가 호출되면 델리게이트가 호출

      image.png

    • BTTask_CustomMove의 ExecuteTask에서 델리게이트 바인딩

    • ExecuteTask에서 EBTNode::Result 를 InProgress로 반환

    • Destination에 도착하면 바인딩 했던 함수 (HandleMoveFinished) 호출 되면서 FinishLetentTask 호출

    • 그러면서 OnTaskFinished 가 자동 호출되면서 바인딩이 해제

      
      #include "Monster/BT/BTTask_CustomMove.h"
      #include "AIController.h"
      #include "Monster/FlyingAIPathfindingBase.h"
      #include "BehaviorTree/BlackboardComponent.h"
      #include "AbyssDiverUnderWorld.h"
      
      UBTTask_CustomMove::UBTTask_CustomMove()
      {
      	NodeName = "Custom Move To Location";
      	bNotifyTick = false;
      	bNotifyTaskFinished = true; // Ensuring OnTaskFinished execution
      }
      
      EBTNodeResult::Type UBTTask_CustomMove::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
      {
      	CashedOwnerComp = &OwnerComp;
      
      	AAIController* AIController = OwnerComp.GetAIOwner();
      	if (!AIController) return EBTNodeResult::Failed;
      
      	APawn* AIPawn = AIController->GetPawn();
      	if (!AIPawn) return EBTNodeResult::Failed;
      
      	CashedPathComp = AIPawn->FindComponentByClass<UFlyingAIPathfindingBase>();
      	if (!CashedPathComp) return EBTNodeResult::Failed;
      
      	UBlackboardComponent* BlackboardComp = OwnerComp.GetBlackboardComponent();
      	if (!BlackboardComp) return EBTNodeResult::Failed;
      
      	FVector TargetLocation = BlackboardComp->GetValueAsVector("TargetLocation");
      
      	// Arrived Event Binding
      	CashedPathComp->OnFinishedMoving.AddDynamic(this, &UBTTask_CustomMove::HandleMoveFinishied);
      	if (AIPawn->HasAuthority())
      	{
      		CashedPathComp->S_MoveTo(TargetLocation);
      	}
      	else
      	{
      		LOG(TEXT("Tried to call Server_MoveTo on client"));
      	}
      
      	return EBTNodeResult::InProgress;
      }
      void UBTTask_CustomMove::OnTaskFinished(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, EBTNodeResult::Type TaskResult)
      {
      	if (CashedPathComp)
      	{
      		CashedPathComp->OnFinishedMoving.RemoveDynamic(this, &UBTTask_CustomMove::HandleMoveFinishied);
      	}
      }
      void UBTTask_CustomMove::HandleMoveFinishied()
      {
      	if (CashedOwnerComp)
      	{
      		FinishLatentTask(*CashedOwnerComp, EBTNodeResult::Succeeded);
      	}
      }

      해결과정

    • BTTask_FindNextPatrolLocation 에서 SetValueAsVector(TargetLocation)에 들어가는 TargetLocation 값 확인

      	BlackboardComp->SetValueAsVector(TargetLocationKey.SelectedKeyName, TargetLocation);
      	BlackboardComp->SetValueAsInt(PatrolIndexKey.SelectedKeyName, Monster->GetNextPatrolIndex(Index));
      	LOG(TEXT("TargetLocation : %s"), *TargetLocation.ToString())
    • 에디터를 켜서 확인한 결과 정확하게 값은 들고옴.

    • Blackboard key 값도 정확하게 들고와서 Set 하고있음

    • 아오 뭐가 문제지 ㅅㅂ..???

    • 와 그냥 중력적용되어있어서 이동이 안되었던 거임….

    • Character Component의 gravityScale을 0으로하니깐 말끔하게 해결

profile
Unreal 1기

0개의 댓글