Unable to get my AI controler from OwnerComp.GetAIOwner() in a service - UE 4.18

Hello, I have an issues as the title says. The code is:

BehaviorTree = OwnerComp.GetCurrentTree();
AZSFSEnemy1ConBase* AICharacter1Con = Cast<AZSFSEnemy1ConBase>(OwnerComp.GetAIOwner());
if (AICharacter1Con) {
AZSFSEnemy1Base* AICharacter1 = Cast<AZSFSEnemy1Base>(AICharacter1Con->GetPawn());
}
else {
GLog->Log(“No AICharacter1Con”);
}

I get “No AICharacter1Con”. Have I missed something?

Likely your cast is failing for some reason. Have you placed a breakpoint and seen what GetAIOwner is returning?

Thank you for your post, but I am unable to debug with Visual Studio 2017. It doesn’t work somehow.

What do you mean it doesn’t work? If debugging was broken in VS2017, MS wouldn’t release it and Epic certainly wouldn’t allow you to use it. :slight_smile:

How are you editing your code, I assume it’s in VS2017. Are you just using hot reload to view your changes? If so, simply run your game via your VS2017 instead (using your MyGame.sln) and you should be able to debug as expected.

It doesn’t works as should, but I was able to use the Watch window and I see that AICharacter1Con (my ai controller) is undefined (identifier AICharacter1Con is undefined). Why? I included AZSFSEnemy1ConBase and the service class should see it.
the same problem with OwnerComp.GetAIOwner() - also OwnerComp is udnefined.
I see that my Behavior Tree and Blackboard don’t run. I referenced the Behavior Tree in the ai character and the AICharacter1Con that is my ai controller class.

The full code:


// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "AIController.h"
#include "ZSFSEnemy1ConBase.generated.h"

/**
 *
 */
UCLASS()
class ZSFS_I_API AZSFSEnemy1ConBase : public AAIController
{
    GENERATED_BODY()

private:
    /*Behavior Tree component reference*/
    //UPROPERTY(transient)
    class UBehaviorTreeComponent* BehaviorComp;

    /*Blackboard comp ref*/
    //UPROPERTY(transient)
    class UBlackboardComponent* BlackboardComp;

public:

    /*Constructor*/
    AZSFSEnemy1ConBase();

    virtual void BeginPlay() override;

    /*Blackboard key*/
    UPROPERTY(EditDefaultsOnly, Category = "AI")
    FName ZSFSMainHeroKey;

    UPROPERTY(EditDefaultsOnly, Category = "AI")
    FName CombatStatusKey;

    /*Executes right when the controller possess a Pawn*/
    virtual void Possess(APawn* InPawn) override;

    //virtual void UnPossess() override;

    /*Sets the sensed target in the blackboard*/

    void SetSeenTarget(APawn* InPawn);

    uint8 CombatStatusKeyID;
    uint8 HeroKeyID;

};


// Fill out your copyright notice in the Description page of Project Settings.

#include "ZSFS_I.h"
#include "BehaviorTree/BehaviorTree.h"
#include "BehaviorTree/BehaviorTreeComponent.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "BehaviorTree/Blackboard/BlackboardKeyAllTypes.h"
#include "ZSFSEnemy1Base.h"
#include "MainHero.h"
#include "ZSFSEnemy1ConBase.h"

AZSFSEnemy1ConBase::AZSFSEnemy1ConBase(){
    //Initialize the behavior tree and blackboard components
    BehaviorComp = CreateDefaultSubobject<UBehaviorTreeComponent>(TEXT("BehaviorComp"));

    BlackboardComp = CreateDefaultSubobject<UBlackboardComponent>(TEXT("BlackboardComp"));

    ZSFSMainHeroKey = "ZSFSMainHero";
    CombatStatusKey = "CombatStatus";
}

void AZSFSEnemy1ConBase::Possess(APawn* InPawn){
    Super::Possess(InPawn);

    //Get the possessed Pawn. If it's the AI Character we created
    //initialize it's blackboard and start it's corresponding behavior tree
    AZSFSEnemy1Base* AICharacter = Cast<AZSFSEnemy1Base>(InPawn);
    if (AICharacter){
        if (AICharacter && AICharacter->BehaviorTree){
            BlackboardComp->InitializeBlackboard(*(AICharacter->BehaviorTree->BlackboardAsset));

            //CombatStatusKeyID = BlackboardComp->GetKeyID("CombatStatus");
            //HeroKeyID = BlackboardComp->GetKeyID("ZSFSMainHero");
            BehaviorComp->StartTree(*AICharacter->BehaviorTree);
        }
    }
}

//void AZSFSEnemy1ConBase::UnPossess(){
//    Super::UnPossess();
//
//    /* Stop any behavior running as we no longer have a pawn to control */
//    BehaviorComp->StopTree();
//}

void AZSFSEnemy1ConBase::BeginPlay() {
    //BlackboardComp->SetValueAsObject(ZSFSMainHeroKey, nullptr);
    //BlackboardComp->SetValueAsEnum(CombatStatusKey, (uint8)CombatStatus::CS_Patrol);
}

void AZSFSEnemy1ConBase::SetSeenTarget(APawn* InPawn){
    //Registers the Pawn that the AI has seen in the blackboard
    //GLog->Log("Oh hello there");
    AMainHero* MH = Cast<AMainHero>(InPawn);
    if(MH){
    if (BlackboardComp){
        BlackboardComp->SetValueAsObject(ZSFSMainHeroKey, MH);
        BlackboardComp->SetValueAsEnum(CombatStatusKey, (uint8)CombatStatus::CS_Combat);
    }

    }

}


// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "ZSFS_I.h"
#include "BehaviorTree/BTService.h"
#include "BTService_ChangeCombatStatus.generated.h"

/**
 *
 */
UCLASS()
class ZSFS_I_API UBTService_ChangeCombatStatus : public UBTService
{
    GENERATED_BODY()

public:
    UBTService_ChangeCombatStatus();

    virtual void TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;

    UPROPERTY(EditDefaultsOnly, Category = "AI")
    FName CS;
    //CombatStatus CS;

    UBehaviorTree* BehaviorTree;

};


// Fill out your copyright notice in the Description page of Project Settings.

#include "ZSFS_I.h"
#include "ZSFSEnemy1ConBase.h"
#include "ZSFSEnemy1Base.h"
#include "MainHero.h"
#include "BTService_ChangeCombatStatus.h"

UBTService_ChangeCombatStatus::UBTService_ChangeCombatStatus() {
    /*
    bNotifyTick = true;
    bNotifyOnSearch = true;
    bTickIntervals = true;
    bCallTickOnSearchStart = false;
    bRestartTimerOnEachActivation = false;

    Interval = 0.5f;
    RandomDeviation = 0.1f;

    bCreateNodeInstance = true; */
    CS = "CombatStatus";

}

void UBTService_ChangeCombatStatus::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) {

    ScheduleNextTick(NodeMemory);

    BehaviorTree = OwnerComp.GetCurrentTree();
    if (BehaviorTree) {
        GLog->Log("BehaviorTree");
    }
    AZSFSEnemy1ConBase* AICharacter1Con = Cast<AZSFSEnemy1ConBase>(OwnerComp.GetAIOwner());
    if (AICharacter1Con) {
        AZSFSEnemy1Base* AICharacter1 = Cast<AZSFSEnemy1Base>(AICharacter1Con->GetPawn());
    }
    else {
        GLog->Log("No AICharacter1");
    }

    if (AICharacter1Con) {
        AMainHero* MH = Cast<AMainHero>(GetWorld()->GetFirstPlayerController()->GetPawn());
        GLog->Log("Service");
        if (MH) {

            //OwnerComp.GetBlackboardComponent()->SetValue<UBlackboardKeyType_Object>("ZSFSMainHero", MH);
            //CS = AICharacter1->CS;
            //GEngine->AddOnScreenDebugMessage(0, 0.5f, FColor::Yellow, FString::Printf(TEXT("CombatStatus %d"), (uint8)CS));
            //UE_LOG(LogTemp, Warning, TEXT("CombatStatus %d"), (uint8)CS);
            //OwnerComp.GetBlackboardComponent()->SetValueAsEnum<UBlackboardKeyType_Object>(AICharacter1Con->CombatStatusKeyID,(uint8)CombatStatus::CS_Patrol);
                //
            OwnerComp.GetBlackboardComponent()->SetValueAsObject("ZSFSMainHero", MH);
            OwnerComp.GetBlackboardComponent()->SetValueAsEnum(CS, (uint8)CombatStatus::CS_Combat);

        }
    }

}

“It doesn’t work as it should” isn’t a good response. You need to fix that if you want to get anywhere, otherwise you’re just working blind.

In the meantime you can print out the name of the controller class.



    AZSFSEnemy1ConBase* AICharacter1Con = Cast<AZSFSEnemy1ConBase>(OwnerComp.GetAIOwner());
    if (AICharacter1Con) {
        AZSFSEnemy1Base* AICharacter1 = Cast<AZSFSEnemy1Base>(AICharacter1Con->GetPawn());
    }
    else {
        GLog->Log("No AICharacter1, controller class was %s", OwnerComp.GetAIOwner() ? *(OwnerComp.GetAIOwner()->GetClass()->GetName()) : TEXT("NULL"));
    }


But, again, I HIGHLY suggest you figure out what’s going on with your debugging situation. It’s definitely not normal.

Ok, thank you. Tomorrow :).
For now, I know Behaviour Tree and Blackboard don’t work. Maybe UE 4.18 is too fresh.

No messaging and no debugging! Because the service doesn’t run and because the behavior tree doesn’t run. All stuff referenced in my ai enemy and all initialized in the code. How to force the behavior tree to run? How to debug it?

All things in my AI Controller class works. In the ai controller class, I have tested: AI character, behavior tree (referenced in ai enemy blueprint), BlackboardAsset, Behaviour Tree Component, Blackboard Component. All available, initialized and works. However, the real assets in the Content Browser (Behavior Tree and Blackboard) don’t work when I at runtime. I don’t understand. Earlier it worked, then stopped working, worked and don’t work now again. I just tried to create blueprint for my ai controller class and assigned it to the ai character blueprint - the behavior tree stopped working, so I referenced the C++ class of ai controller again (removing ai controlling blueprint), but it didn’t help.
My behavior tree doesn’t’ work. WTF?

Oh yeah, I can replicate that!