Advertisement
Guest User

UE4 AIController

a guest
Mar 13th, 2021
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.20 KB | None | 0 0
  1. // Copyright 2021 Anatoli Kucharau https://vk.com/ulvprog. All Rights Reserved.
  2. /**
  3.  * Контроллер врага.
  4.  */
  5.  
  6. #pragma once
  7.  
  8. #include "EnemyAIController.h"
  9. #include "Kismet/GameplayStatics.h"
  10.  
  11. #include "MagicTrigger\Enemy\EnemyCharacterMagicTrigger.h"
  12. #include "MagicTrigger\Data\DebugMessage.h"
  13. #include "MagicTrigger\Data\CollisionChannelsMagicTrigger.h"
  14.  
  15. #include "UObject/ConstructorHelpers.h"
  16. #include "Perception/AIPerceptionComponent.h"
  17. #include "Perception\AISenseConfig_Sight.h"
  18. #include "Perception\AISenseConfig_Hearing.h"
  19.  
  20. #include "BehaviorTree\BehaviorTree.h"
  21. #include "BehaviorTree\BlackboardData.h"
  22. #include "BehaviorTree/BehaviorTreeComponent.h"
  23. #include "BehaviorTree/BlackboardComponent.h"
  24.  
  25. #include "NavMesh\RecastNavMesh.h"
  26. #include "NavAreas\NavArea_Obstacle.h"
  27. #include "Components\SphereComponent.h"
  28.  
  29. class UAISense_Sight;
  30.  
  31. AEnemyAIController::AEnemyAIController()
  32. {
  33.     AIPerceptionComponent = CreateDefaultSubobject<UAIPerceptionComponent>(TEXT("AIPerceptionComponent"));
  34.     AISightConfig = CreateDefaultSubobject<UAISenseConfig_Sight>(TEXT("AISightConfig"));
  35.     AIHearingConfig = CreateDefaultSubobject<UAISenseConfig_Hearing>(TEXT("AIHearingConfig"));
  36.  
  37.     BlackboardComponent = CreateDefaultSubobject<UBlackboardComponent>(TEXT("BlackboardComponent"));
  38.     BehaviorTreeComponent = CreateDefaultSubobject<UBehaviorTreeComponent>(TEXT("BehaviorTreeComponent"));
  39.  
  40.     static ConstructorHelpers::FObjectFinder<UBehaviorTree> BTObject(TEXT("/Game/MagicTrigger/AI/Enemy/BT_Enemy"));
  41.     if (BTObject.Succeeded())
  42.     {
  43.         BehaviorTreeAsset = BTObject.Object;
  44.     }
  45.     else
  46.     {
  47.         DEBUGMESSAGE("!BTObject.Succeeded()")
  48.     }
  49.     static ConstructorHelpers::FObjectFinder<UBlackboardData> BBObject(TEXT("/Game/MagicTrigger/AI/Enemy/BB_Enemy"));
  50.     if (BBObject.Succeeded())
  51.     {
  52.         BlackboardAsset = BBObject.Object;
  53.     }
  54.     else
  55.     {
  56.         DEBUGMESSAGE("!BBObject.Succeeded()")
  57.     }
  58.     BBKeys = FBlackboardKeyNamesStruct();
  59.     DeltaAttackRadius = 20;
  60.     BeginPlayTimerTime = 0.2;
  61.     OnPossessTimerTime = 0.2;
  62.  
  63.     ConfigureAIPerception();
  64. }
  65.  
  66. void AEnemyAIController::BeginPlay()
  67. {
  68.     Super::BeginPlay();
  69.  
  70.     StartBeginPlayTimer_IF_Implementation();
  71. }
  72.  
  73. void AEnemyAIController::OnRunAI()
  74. {
  75.  
  76.     //DEBUGMESSAGE("OnRunAI");
  77.     this->AIPerceptionComponent->Activate();
  78.     this->BehaviorTreeComponent->StartLogic();
  79. }
  80.  
  81. void AEnemyAIController::OnStopAI()
  82. {
  83.     //DEBUGMESSAGE("OnStopAI");
  84.     this->AIPerceptionComponent->Deactivate();
  85.     FString Reason;
  86.     this->BehaviorTreeComponent->StopLogic(Reason);
  87. }
  88.  
  89. void AEnemyAIController::OnPossess(APawn* InPawn)
  90. {
  91.     Super::OnPossess(InPawn);
  92.  
  93.     if (!GetWorld())
  94.     {
  95.         DEBUGMESSAGE("!GetWorld()");
  96.         return;
  97.     }
  98.     GetWorld()->GetTimerManager().SetTimer(this->OnPossessTimer, this, &AEnemyAIController::CheckReferencesOnPossess, this->OnPossessTimerTime, true);
  99.  
  100. }
  101.  
  102. void AEnemyAIController::CheckReferencesOnPossess()
  103. {
  104.     ACharacter* PlayerCharacterTmp;
  105.     AEnemyCharacterMagicTrigger* EnemyTmp;
  106.  
  107.     PlayerCharacterTmp = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);
  108.     EnemyTmp = GetPawn<AEnemyCharacterMagicTrigger>();
  109.     if (!PlayerCharacterTmp)
  110.     {
  111.         DEBUGMESSAGE("!PlayerCharacter");
  112.         return;
  113.     }
  114.     if (!EnemyTmp)
  115.     {
  116.         DEBUGMESSAGE("!Enemy");
  117.         return;
  118.     }
  119.  
  120.     this->Enemy = EnemyTmp;
  121.     this->PlayerCharacter = PlayerCharacterTmp;
  122.     GetWorld()->GetTimerManager().ClearTimer(this->OnPossessTimer);
  123.     DoOnPossess();
  124. }
  125.  
  126. void AEnemyAIController::DoOnPossess()
  127. {
  128.     UAIPerceptionSystem::RegisterPerceptionStimuliSource(GetWorld(), this->AISightConfig->GetSenseImplementation(), this->PlayerCharacter);
  129.     UAIPerceptionSystem::RegisterPerceptionStimuliSource(GetWorld(), this->AIHearingConfig->GetSenseImplementation(), this->PlayerCharacter);
  130.  
  131.     this->AISightConfig->SightRadius = this->Enemy->EnemyToBehaviorTreeStruct.SightRadius;
  132.     this->AISightConfig->LoseSightRadius = this->Enemy->EnemyToBehaviorTreeStruct.LoseSightRadius;
  133.     this->AIHearingConfig->HearingRange = this->Enemy->EnemyToBehaviorTreeStruct.HearingRange;
  134.  
  135.     bool bInitializeBB = this->BlackboardComponent->InitializeBlackboard(*this->BlackboardAsset);
  136.     if (!bInitializeBB)
  137.     {
  138.         DEBUGMESSAGE("!bInitializeBB");
  139.         return;
  140.     }
  141.  
  142.     this->AIPerceptionComponent->OnTargetPerceptionUpdated.AddDynamic(this, &AEnemyAIController::TargetPerceptionUpdate);
  143.     this->BehaviorTreeComponent->StartTree(*this->BehaviorTreeAsset);
  144.  
  145.     this->AIPerceptionComponent->ProcessStimuli();
  146.  
  147.     /////////////////////////////////////////////////////////
  148.     /**
  149.      * Поиск перса и останока логики, если перс не найден.
  150.      */
  151.     TSubclassOf<ACharacter> ClassFilter;
  152.     TArray<AActor*> OverlappingActors;
  153.     bool bPlayerCharacterFound = false;
  154.  
  155.  
  156.     this->Enemy->RunAISphere->GetOverlappingActors(OverlappingActors, ClassFilter);
  157.     if (!OverlappingActors.Num())
  158.     {
  159.         //DEBUGMESSAGE("!OverlappingActors.Num()")
  160.         OnStopAI();
  161.     }
  162.     else
  163.     {
  164.         for (const auto& OverlappingActor : OverlappingActors)
  165.         {
  166.             ACharacter* OverlappingCharacter = Cast<ACharacter>(OverlappingActor);
  167.             if (OverlappingCharacter == this->PlayerCharacter)
  168.             {
  169.                 bPlayerCharacterFound = true;
  170.                 break;
  171.             }
  172.         }
  173.         if (!bPlayerCharacterFound)
  174.         {
  175.             //DEBUGMESSAGE("!bPlayerCharacterFound")
  176.                 OnStopAI();
  177.         }
  178.     }
  179.     /////////////////////////////////////////////////////////
  180.  
  181. }
  182.  
  183. void AEnemyAIController::FindPlayer()
  184. {
  185.     this->Enemy = GetEnemy();
  186.     if (!this->Enemy)
  187.     {
  188.         DEBUGMESSAGE("!this->Enemy");
  189.         return;
  190.     }
  191.     if (!this->BlackboardComponent)
  192.     {
  193.         DEBUGMESSAGE("!this->BlackboardComponent");
  194.         return;
  195.     }
  196.  
  197.     //DEBUGMESSAGE("FindPlayer");
  198.     this->BlackboardComponent->SetValueAsObject(this->BBKeys.TargetPlayer, this->PlayerCharacter);
  199.     StopMovement();
  200.     this->BlackboardComponent->SetValueAsBool(this->BBKeys.bRoaring, true);
  201.  
  202. }
  203.  
  204. void AEnemyAIController::LosePlayer()
  205. {
  206.     if (!this->Enemy)
  207.     {
  208.         DEBUGMESSAGE("!this->Enemy");
  209.         return;
  210.     }
  211.     if (!this->BlackboardComponent)
  212.     {
  213.         DEBUGMESSAGE("!this->BlackboardComponent");
  214.         return;
  215.     }
  216.     if (!this->PlayerCharacter)
  217.     {
  218.         DEBUGMESSAGE("!this->PlayerCharacter");
  219.         return;
  220.     }
  221.     //DEBUGMESSAGE("LosePlayer");
  222.     this->Enemy->StopAttack();
  223.     StopMovement();
  224.     this->BlackboardComponent->ClearValue(this->BBKeys.bCanMoveToPlayer);
  225.     this->BlackboardComponent->ClearValue(this->BBKeys.TargetPlayer);
  226.     this->BlackboardComponent->ClearValue(this->BBKeys.bRoaring);
  227.     this->BlackboardComponent->ClearValue(this->BBKeys.bCanAttack);
  228.  
  229. }
  230.  
  231.  
  232. void AEnemyAIController::TargetPerceptionUpdate(AActor* Actor, FAIStimulus Stimulus)
  233. {
  234.     if (!this->PlayerCharacter)
  235.     {
  236.         //DEBUGMESSAGE("Actor != this->PlayerCharacter");
  237.         return;
  238.     }
  239.  
  240.     if (Actor != this->PlayerCharacter)
  241.     {
  242.         //DEBUGMESSAGE("Actor != this->PlayerCharacter");
  243.         return;
  244.     }
  245.  
  246.     UObject* TargetPlayer = this->BlackboardComponent->GetValueAsObject(this->BBKeys.TargetPlayer);
  247.  
  248.     if (TargetPlayer)
  249.     {
  250.         //DEBUGMESSAGE("TargetPlayer");
  251.         return;
  252.     }
  253.  
  254.     bool bFindPlayer = Stimulus.WasSuccessfullySensed();
  255.     //DEBUGMESSAGE("TargetPerceptionUpdate");
  256.     if (bFindPlayer)
  257.     {
  258.         //DEBUGMESSAGE("bFindPlayer");
  259.         FindPlayer();
  260.     }
  261.  
  262. }
  263.  
  264.  
  265. void AEnemyAIController::ConfigureAIPerception()
  266. {
  267.     this->AISightConfig->DetectionByAffiliation.bDetectEnemies = true;
  268.     this->AISightConfig->DetectionByAffiliation.bDetectFriendlies = true;
  269.     this->AISightConfig->DetectionByAffiliation.bDetectNeutrals = true;
  270.     this->AIHearingConfig->DetectionByAffiliation.bDetectEnemies = true;
  271.     this->AIHearingConfig->DetectionByAffiliation.bDetectFriendlies = true;
  272.     this->AIHearingConfig->DetectionByAffiliation.bDetectNeutrals = true;
  273.  
  274.     this->AIPerceptionComponent->ConfigureSense(*this->AISightConfig);
  275.     this->AIPerceptionComponent->ConfigureSense(*this->AIHearingConfig);
  276.  
  277.     this->AIPerceptionComponent->SetDominantSense(this->AISightConfig->GetSenseImplementation());
  278. }
  279.  
  280.  
  281. ACharacter* AEnemyAIController::GetPlayerCharacter() const
  282. {
  283.     if (!this->PlayerCharacter)
  284.     {
  285.         DEBUGMESSAGE("!this->PlayerCharacter");
  286.     }
  287.     return this->PlayerCharacter;
  288. }
  289.  
  290. AEnemyCharacterMagicTrigger* AEnemyAIController::GetEnemy()
  291. {
  292.     if (!this->Enemy)
  293.     {
  294.         DEBUGMESSAGE("!this->Enemy");
  295.     }
  296.  
  297.     return this->Enemy;
  298. }
  299.  
  300. void AEnemyAIController::LosePlayer_IF_Implementation()
  301. {
  302.     LosePlayer();
  303. }
  304.  
  305. /**
  306.  * BeginPlayInterface
  307.  */
  308.  ///////////////////////////////////////////////////////////////////////////////////////
  309. bool AEnemyAIController::CheckReferences_IF_Implementation()
  310. {
  311.     UGameplayStatics::GetAllActorsOfClass(GetWorld(), ARecastNavMesh::StaticClass(), this->NavMeshArray);
  312.     if (
  313.         !this->NavMeshArray.Num()
  314.         || !this->NavMeshArray[0]
  315.         || !Cast<ARecastNavMesh>(this->NavMeshArray[0])
  316.         )
  317.     {
  318.         return false;
  319.     }
  320.  
  321.     return true;
  322. }
  323.  
  324. void AEnemyAIController::DoBeginPlay_IF_Implementation()
  325. {
  326.     this->NavMesh = Cast<ARecastNavMesh>(this->NavMeshArray[0]);
  327. }
  328.  
  329. void AEnemyAIController::StartBeginPlayTimer_IF_Implementation()
  330. {
  331.     if (!GetWorld())
  332.     {
  333.         DEBUGMESSAGE("!GetWorld()");
  334.         return;
  335.     }
  336.  
  337.     GetWorld()->GetTimerManager().SetTimer(this->BeginPlayTimer, this, &AEnemyAIController::BeforeBeginPlay_IF_Implementation, this->BeginPlayTimerTime, true);
  338. }
  339.  
  340. void AEnemyAIController::BeforeBeginPlay_IF_Implementation()
  341. {
  342.     if (CheckReferences_IF_Implementation())
  343.     {
  344.         GetWorld()->GetTimerManager().ClearTimer(this->BeginPlayTimer);
  345.         DoBeginPlay_IF_Implementation();
  346.     }
  347. }
  348.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement