Listen Server BeginOverlap - How to reach only the client that overlapped?

Hi forum,

I’m having some issues with overlaps in Listen Server Multiplayer.

On Overlap I want to set the visibility of a widget in the “OtherActor” to true.
But only for the client that actually overlaps with it…

In BeginPlay I set the Overlap functions:

if(HasAuthority()){
		SphereComponent->OnComponentBeginOverlap.AddDynamic(this, &AMasterCharacter::TriggerBeginOverlap);
		SphereComponent->OnComponentEndOverlap.AddDynamic(this, &AMasterCharacter::TriggerEndOverlap);
	}

Only the server should check for overlaps right? Hence the HasAuthority().

In TriggerBeginOverlap:

bool ImplementsInterface = UKismetSystemLibrary::DoesImplementInterface(OtherActor, UInteractableActorInterface::StaticClass());
		
		if (ImplementsInterface){
			APickup* pickup = Cast<APickup>(OtherActor);
			if(pickup){
				pickup->SetItemNameVisibility(true);
			}
		}

I need to know who the client is that needs to have the visibility set to true + how to actually do that.

Replication isn’t the answer here, cause then all clients would see the widget.

The Actor’s that the player overlaps with are just dragged in the Level using the editor.
They don’t really belong to the player or something.

Can someone help me please?

Kind regards,

Nick

Hi,

There is a Only Relevant to Owner replication option that may be usable to do this within the replication system.

I don’t know how that works and if it suits this use case, but I believe your problem can be solved simply with a Run on Owning Client function anyway:

	// this character's player controller
	APlayerController Controller = GetController<APlayerController>();

	// Call your "Executes on Owning Client" function here
	Controller->SpecialCallJustForThisPlayer();

Oh, do you mean a Client RPC function?

I’ll give it a go when I get home!

Thanks!

Yeah, asking the server to do something is probably the typical RPC use, but it can totally be done (and is) the other way too.

Semantics for it in C++ are strange, see the doco:

In Blueprint tutorials for this, they always use IsLocallyControlled, which is only available in C++ for a character/Pawn, but not for actors.

If I’m not mistaking, it is the servers task to check for overlap and then send it to the correct client (which is why I’m here :wink: )

Making Every client check overlap themselves would be easier, but that isn’t really safe I supposed. Since the Actor that is overlapping with the player is a Pickup Actor.

Another way I could be doing this is to check overlaps from the Pickup Actor itself.
In tick of the Pickup, constantly retrieve GetOverLappingActors of type “PlayerCharacter” and go from there.

I tried staying away from RPC’s as long as possible since they are quite costly. There Will be lots of Pickup Actors in the game with up to 4 players. So every time a player get’s close it’ll trigger it.
Since it important that they player can actually pick the item up, I’ll have to put it on Reliable as well.

I’ll play with it this evening and try and test what works best!

Definitely look into the Only Relevant to Owner replication thing, assuming that sphere component is on a character it sounds like it might be what you looking for.

Good luck!

Hi,

I’ve tried it, but didn’t succeed sadly.

I can’t find any examples of client RPC’s using C++.

My code atm:

MasterCharacter.cpp

void AMasterCharacter::BeginPlay()
{
	Super::BeginPlay();
	
         //Input mapping logic...

            // Does this need a HasAuthority check?
		SphereComponent->OnComponentBeginOverlap.AddDynamic(this, &AMasterCharacter::TriggerBeginOverlap);
		SphereComponent->OnComponentEndOverlap.AddDynamic(this, &AMasterCharacter::TriggerEndOverlap);

}
void AMasterCharacter::TriggerBeginOverlap(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult)
{
    if(HasAuthority()){  // Needed because calling a client RPC
		bool ImplementsInterface = UKismetSystemLibrary::DoesImplementInterface(OtherActor, UInteractableActorInterface::StaticClass());
		 
		if (ImplementsInterface){
			APickup* pickup = Cast<APickup>(OtherActor);
			if(pickup){

				pickup->ClientRPCShowPickupText();
			}
		}
	}

Pïckup.cpp

void APickup::ClientRPCShowPickupText_Implementation(){ 
	SetItemNameVisibility(true);
}

Result: Only the host (listen server) has the text appear. Even when a client overlaps with the pickup.

Following this table my guess is that the pickup actor is a Server-Owned actor or an Unowned actor.

Since I drag the pickup’s in the editor, I have no idea what to do.

Yes, you’re calling the client RPC on a server owned actor, which indeed won’t work.
The RPC needs to be on the character or player controller (something the client owns), you can just pass the pointer to the pickup actor across, and the change will then obviously only be on that client.

1 Like

It works now! :tada:

I put the ClientRPC in the player character itself.
And then pass through the OtherActor from the overlap event.

In the ClientRPC_Implementation I then call the “SetItemNameVisibility” of the pickup and it finally works!! (After almost 2 weeks rip).

I do have one question though about ‘performance’.

In Beginplay of the PlayerCharacter I set:

if(HasAuthority()){  
		SphereComponent->OnComponentBeginOverlap.AddDynamic(this, &AMasterCharacter::TriggerBeginOverlap);
		SphereComponent->OnComponentEndOverlap.AddDynamic(this, &AMasterCharacter::TriggerEndOverlap);
	}

Is it ok that only the server listens for overlaps? Or should this also be in the clients?
I’ve watched a video’s where they let the client perform a linetrace when pressing the interact key.
When the linetrace has a hit with a “pickup” actor, they call a Server RPC to let the server know the client had an overlap.
BUT … Then they actually perform the linetrace again on the server to validate if the client is actually hitting an object that exists on the server… Which is logic, but double the work no?

I was wondering if enabling the OnComponent overlaps only on the server would be too much for the server. But since they are also validating it on the server by performing it again, I don’t know if it would be better?

I might make a new topic with this question to get (hopefyully) more opinions on this.
There must be a “best” way to do something right? haha

Thank you very much already for fixing it for me!

1 Like

It’s a trade off of course, best for performance is just let the client do it and that can be fine (if you can trust the client, or if it doesn’t really matter), indeed for what you seem to be doing I would think it is fine (cosmetic change). So maybe we didn’t need all this :stuck_out_tongue:

I believe the ‘doubling of work’ is done to allow the client to respond to input quickly and just let the server know what’s happening, if all goes well everything is smooth, if not there are some corrections.

While it is nice to be able to pre-emptively optimise, it is not that wise I think. Get things working, test often and if something is slow deal with it then. And no, there is of course no generic best way; It depends :slight_smile:

Glad you got it working! (but maybe just do it all on the client?)

Hi,

I still have no idea how to do it on the client haha.

Everything about ‘Only Relevant to Owner’ replication is searched, came out as an RPC…

I’ve tried a lot in my BeginOverlap and either it shows for all clients or only for the server.
Never alone for the client that actually overlaps…

I’m probably still missing something, but after a few weeks of searching for it I don’t know where to look further.

I think I found what you were referring to!

Was it a

 DOREPLIFETIME_CONDITION?

In this case:

void AActor::GetLifetimeReplicatedProps( TArray< FLifetimeProperty > & OutLifetimeProps ) const
{
    DOREPLIFETIME_CONDITION( APickup, bShowPickupName, COND_OwnerOnly);
}

I’m going to test it now

What I was trying to get at in my last post (which maybe got buried a bit) is that the message visibility seems like something the server doesn’t need to know about.

If so, just do everything client side and leave the server out of it entirely, do your overlap tests for local controllers, flip message vis locally, and do zero network stuff.

Server RPC for the actual pickup of course, which needs authority.

I finally find a way to do it client only!

Thanks for the help!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.