Perception Component

  • 주로 AI의 타겟 인지 및 해제를 관리하는 목적의 컴포넌트
  • 자극(stimulus)을 인지하면서 호출하는 대표적인 delegate는 아래와 같다
    • OnPerceptionUpdated
      • 자극을 처리하는 과정에서 자극을 제공한 모든 액터를 어레이로 받는다
    • OnTargetPerceptionInfoUpdated / OnTargetPerceptionUpdated
      • 위의 delegate는 모두 자극을 제공한 단일 대상에 대해 업데이트가 필요할 때 호출된다
      • 다만 OnTargetPerceptionInfoUpdated는 자극 제공 대상이 valid하지 않은 경우에도 호출된다
      • 반대로 OnTargetPerceptionUpdated는 자극 제공 대상이 valid한 경우에만 호출한다

AIPerceptionStimuliSourceComponent

  • Perception System을 통해 인지할 자극(stimulus)을 제공하는 컴포넌트
  • 이 컴포넌트가 없는 Actor를 인지 못하는 것은 아니다
    • AIPerceptionSystem은 게임을 시작하면서 모든 Pawn에 대한 자극 대상을 각 Sensor에 등록한다
void UAIPerceptionSystem::StartPlay()
{
  for (UAISense* Sense : Senses)
  {
    if (Sense != nullptr && Sense->ShouldAutoRegisterAllPawnsAsSources())
    {
      FAISenseID SenseID = Sense->GetSenseID();
      RegisterAllPawnsAsSourcesForSense(SenseID);
    }
  }

  //...
}

void UAIPerceptionSystem::RegisterAllPawnsAsSourcesForSense(FAISenseID SenseID)
{
  UWorld* World = GetWorld();
  for (TActorIterator<APawn> PawnIt(World); PawnIt; ++PawnIt)
  {
    RegisterSource(SenseID, **PawnIt);
  }
}
  • 하지만 몇몇 함수로 Perception System에서 특정 액터를 아주 제외하거나 다시 등록할 수 있다
UFUNCTION(BlueprintCallable, Category = "AI|Perception")
AIMODULE_API void RegisterWithPerceptionSystem();

UFUNCTION(BlueprintCallable, Category = "AI|Perception")
AIMODULE_API void UnregisterFromPerceptionSystem();
  • 이 Component를 사용한다면, 아마 위의 함수를 사용할 목적으로 class를 override해서 사용하지 않을까 싶다
  • 플레이어 사망 및 부활, 그리고 테스트 단계에서 적이 플레이어 캐릭터를 인지하지 못하게 하는 치트 구현 등에 사용할 수 있다
// 현재 활성화된 AICharacter 불러와서 잡고 있는 타겟이 PlayerCharacter인지 확인하고 강제로 해제
const UActorManagerSubsystem* ActorManager = GetWorld()->GetSubsystem<UActorManagerSubsystem>();
const TArray<ACharacter*>& AICharacters = ActorManager->GetAllAICharacters();
for (auto& AICharacter : AICharacters)
{
  AAIController* AIController = Cast<AAIController>(AICharacter->GetController());
  check(AIController);
  UCustomAIPerceptionComponent* PerceptionComponent = Cast<UCustomAIPerceptionComponent>(AIController->GetAIPerceptionComponent());
  check(PerceptionComponent);
  if (PerceptionComponent->GetTargetActor() == GetOwner())
  {
    PerceptionComponent->ForceReleaseTarget();
  }
}

// Stimuli 리스트에서 제외
UnregisterFromPerceptionSystem();
// 현재 인지 중인 타겟 강제 해재 함수
void UCustomAIPerceptionComponent::ForceReleaseTarget()
{
  if (TargetActor.IsValid())
  {
    LostTarget(TargetActor.Get());
  }
}
  • 다만, 이미 인지하고 있는 AI들은 UnregisterFromPerceptionSystem를 호출한다고 하더라도 Target을 유지한다
    • 그래서 현재 인지중인 Target을 명시적으로 해제해줘야 한다

출처