SimpleMoveToActor & Multiplayer

Currently I’m trying to get an AI Guard that walks around using an array of targetpoints (set in editor) to function with multiplayer. As it stands currently, it runs just fine without any warnings when I only have 1 player and do not have “Run as dedicated server” option selected. However when I have 2 players or “Run as dedicated server” the messages

LogNavigation: Warning: UNavigationSystemV1::SimpleMoveToActor called for NavSys : None Controller : None controlling Pawn : NULL with goal actor TargetPoint3(if any of these is None then there’s your problem

Show up in the output log, with a new line showing up for each time the AI Guard reaches the targetpoint it was moving towards. The guard still walks around despite the warnings, and using UAIBlueprintHelperLibrary::SimpleMoveToLocation gives no issues regardless of multiplayer or not.

When I have commented out the line
UAIBlueprintHelperLibrary::SimpleMovetoActor(GetController(), CurrentTargetPoint);
Everything runs fine without any warnings, apart from the guard no longer moving as one might expect. CurrentTargetPoint is an actor reference to a targetpoint from an array of them

.h file

UPROPERTY(EditAnywhere, Category = "AI")
TArray<ATargetPoint*> PatrolPoints;


.cpp file

if (CurrentTargetIndex < TotalTargetPoints)
{
	CurrentTargetPoint = PatrolPoints[CurrentTargetIndex];
}
else
{
	CurrentTargetIndex = 0;
	CurrentTargetPoint = PatrolPoints[CurrentTargetIndex];
}
	CurrentTargetIndex++;
	UAIBlueprintHelperLibrary::SimpleMoveToActor(GetController(), CurrentTargetPoint);

CurrentTargetIndex++;
UAIBlueprintHelperLibrary::SimpleMoveToActor(GetController(), CurrentTargetPoint);

I’m assuming my problem lies somewhere in replication? But unsure, as this is my first steps into anything other than local co-op multiplayer. If I need to provide any other information I will do my best to provide it when I’m able to.

I think you are running the code on server and client,
but you only have a controller on the server side.

add a check if you are on the server at the begging of your code

on actors:

if (!HasAuthority())
     return;

on actor components:

if (!GetOwner()->HasAuthority())
   return;

I will try this at my next opportunity

So all I had to do was add your first part in front of the code that selects the next point to move towards

	if (!HasAuthority())
	{
		return;
	}

	if (GuardPatrolType == EAIPatrolType::TargetPoints)
	{
		if (CurrentTargetIndex < TotalTargetPoints)
		{
			CurrentTargetPoint = PatrolPoints[CurrentTargetIndex];
		}
		else
		{
			CurrentTargetIndex = 0;
			CurrentTargetPoint = PatrolPoints[CurrentTargetIndex];
		}
		CurrentTargetIndex++;
 		UAIBlueprintHelperLibrary::SimpleMoveToActor(GetController(), CurrentTargetPoint);

I would like to ask, is this the correct way to handle this? I’m not entirely clear on what the difference between actor vs actor components when working in c++

ah sorry, the first part was the part to solve your current problem.

The second one was if you run into a similar problem while writing an actorcomponent :stuck_out_tongue:

An actor is an object that you can place in a level, all of the objects that make up a level inherit from AActor. Like APawn, ACharacter, PlayerStartActor

An actor component can be a part of an actor, they are used to share code between different actor. For example what you could do is create a HealthComponent by inheriting from AActorComponent, and then use that HealthComponent on all your actors that can get damage and die.

That will save you the work of writing the health, damage and reaction code multiple times.

An already pretty big example is the ACharacter, which already has a SkeletalMeshComponent, a CharacterMovementComponent and a CapsuleComponent on it.

The second part

 if (!GetOwner()->HasAuthority())
    return;

is needed if you want to run the same check in a component and not on an actor.

and yes that’s the correct way to handle this,

ofc it would be even better when you only run this code on the server (by not calling it locally) but checking if you are on the server is the next best thing

Ok that explanation makes a lot of sense, I know when I was learning blueprints I would just copy paste the health nodes over between different actors, but in c++ it seems easier to just write a specific health component.

As for being able to only run the code on the server, I wouldn’t personally know how to go about that. This is mostly because initially this was written as a simple single player level and then I wanted to add simple multiplayer so I could learn a bit about it. So I would presume the first player would act as the server and the person connecting would be a client, so I’m not sure if anything but just checking if I am on the server would work in my current setup. Though I suspect this is also the reason I am getting the warning message “No game present to join for session”. But thank you so much for you help despite me taking a few days to get back to you :slight_smile:

Components are great, one of the biggest advantages is that if you need to make changes later on (and you will), you have one place to change and it will be applied everywhere.

In the health example, what if you decide you want to add shields, then you need to find all actors with your copy before and change it again.

Another great advantage is that they also add same functionality to the actors you put them on.

For example you want to create a healing pickup you would need to either create an interface on every actor that has a health value, then implement it over and over again.

With a component you do

auto* HealthComponent = TargetActor->FindComponentByClass<UHealthComponent>();
if (HealthComponent)
   HealthComponent->AddHealth(ADDED_HEALTH_VALUE);

So no need to add any additional interfaces or casts or something like that, actors that have a HealthComponent just get health :stuck_out_tongue:

could you also be so nice and accept the answer, my OCD is a little triggered by not closed answers :stuck_out_tongue: