Initialize Class within AI Controller

This is a really beginner question but for the life of me can’t figure it out for the life of me.

What I’m trying to do is retrieve the location of my AI within the world and compare that against the players position. I have this logic being done in my AIController which is of type ACharacter (for movement etc).

I have the following code which prints out and shows the difference in location between the AI and the player

	if (m_lineOfSight)
	{
		SetFocus(m_fpsCharacter);
		const FVector playerLoc = m_fpsCharacter->GetActorLocation();

        // Crashes here as m_observer is nullptr
		const FVector seekerPos = m_observer->GetActorLocation();  

		const FVector distanceBetween = m_observer->GetActorLocation() - m_fpsCharacter->GetActorLocation();
		
		UE_LOG(LogTemp, Display, TEXT("Player Position X:%f,Y:%f,Z:%f"), playerLoc.X, playerLoc.Y, playerLoc.Z)
		//UE_LOG(LogTemp, Display, TEXT("Seeker Position X:%f,Y:%f,Z:%f"), seekerPos.X, seekerPos.Y, seekerPos.Z)
		//UE_LOG(LogTemp, Display, TEXT("Distance Between X:%f,Y:%f,Z:%f"), distanceBetween.X, distanceBetween.Y, distanceBetween.Z)
	}

I know that m_observer needs to be initialized so that it doesn’t return a nullptr. But I’m struggling on how to initialize it (sounds daft, I know). In the SeekerAIController.h, the m_observer has been created like AObserver* m_observer = nullptr;. I know this is why it’s returning a nullptr, but obviously needs to have some ‘value’ as it’s a pointer. I have tried using UPROPERTY(EditAnywhere) to assign the Blueprint that way, but when I select BP_Observer, it doesn’t get set, field stays as None.

I have been looking at the idea of spawning the observer in the world which would be it’s initialization. At the moment, it’s just dragged into the world via Blueprint Class (created from the C++ class). But can’t really figure that out either… I feel like I should know how to do this, but I’m drawing a blank. Any advice on what I could do to solve this?

P.S; Observer and Seeker are the same thing. Just haven’t made the name consistent yet.

First off, always null check any pointer before using.

Second, there are a couple of common ways to implement “A uses pointer to B” in game:

  • (1) A and B are always placed in the saved level, then on BeginPlay() A finds and saves pointer to B
  • (2) only A is placed in level, then A spawns B in BeginPlay() and saves the reference

If you need code for either can supply.

Yeah, that makes sense and it’s what I’ve been trying to achieve with no luck.

With the first point, could I place BP_SeekerAIController in my level? Pretty sure I tried that before with no luck (probably means I’ve done something wrong…)

In this case, I’d assume point 2, the SeekerAIController Class would spawn m_observer in SeekerAIController::BeginPlay(). That way, the controller ‘created’ m_observer and therefore it’s initialized and won’t return nullptr?