Learning network and practicing,not sure what's good or bad

Greetings everyone,

It’s the first time I ever post on Unreal Engine Forums so maybe I should have made a question post instead of a discussion one however I thought it fitted better since it’s not really a single question.

I come here today because I struggle to understand how network works in general and more specifically on Unreal Engine. I already use Neukirchen compendium and WizardCell site but it seems already awfully advanced without going into practical examples so I’m not sure if I understand everything correctly. That’s why I’m here.

I’m doing a test project to learn and apply what I learn immediatly. For now I managed to make a custom Online subsystem to create a session (listen server) or to join one as well as a BP lobby system with passwords that you can either create or join thanks to the subsystem.

Once created or joined the players receive a pawn given by the engine through the GameMode.

As you can see both players are the authority on the server player. I don’t know if this normal ? However the second player can control his character without problem. On the client side, his character is autonomous proxy while the server character is in simulated proxy.

I’m trying to make them shoot projectiles. They are not trace projectiles so they are actors spawned. So I use a server RPC to call a SpawnProjectile function. The problem is it moves smoothly on the server side but its movement is a little sketchy on the client side. It’s like it’s “vibrating” or glitching a little and sometimes even rollback. So I thought of spawning a non replicated projectile on the client side and another on the server side. That way each one will see only the one on their computer and there should be no lag or rollback I think.

void ATestCharacterMP::Fire(const FInputActionValue& _value)
{
	const FVector _loc = GetActorLocation() + GetActorForwardVector() * 100;
	const FRotator _rot = GetActorRotation();
	ReliableServerSpawnProjectile(_loc, _rot);
}

void ATestCharacterMP::ReliableClientSpawnProjectile_Implementation(const FVector& _loc, const FRotator& _rot)
{
	SpawnProjectile(bulletToSpawnClient, _loc, _rot);
}

void ATestCharacterMP::ReliableServerSpawnProjectile_Implementation(const FVector& _loc, const FRotator& _rot)
{
	ReliableClientSpawnProjectile(_loc, _rot);
}

void ATestCharacterMP::SpawnProjectile(TSubclassOf<AProjectile> _projectile, const FVector& _loc, const FRotator& _rot)
{
	AActor* _actor = GetWorld()->SpawnActor<AProjectile>(_projectile, _loc, _rot);
}

The problem is, how do I ensure that the server only spawn one and that each client spawn their own ? I thought of making a Fire function on the character that call a server RPCthat receive the location and rotation of the firing pawn among the list of players then call a Client RPC (not multicast) that will receive the coordinates that will spawn the projectile on every client in theory. The problem is that there will be lag between the fire command and the spawn of the bullet for the client. The thing is, how can I spawn locally the bullet and then make my server spawn it on all other client but this one ? Is there a way to filter client ? I thought of using the netID but then I run into how to use it to apply said filter.

Another question I have is, how do I truly differenciate between client and server in this situation ? As you saw both characters have authority it seems, so I cannot make them act or not through this method (HasAuthority).

As you can see both players are the authority on the server player. I don’t know if this normal ? However the second player can control his character without problem. On the client side, his character is autonomous proxy while the server character is in simulated proxy.

This is correct and normal.

A common convention for fairly fast projectiles is for them to not replicate location or movement.

Client controlled character is an Autonomous Proxy only on the owning client. All other characters on his/her screen are Simulated Proxies. The servers copies of all players are Authoritative Proxies.


For projectiles, have each Proxy spawn their own. Don’t replicate projectiles.

  • Client fires a local only w/hit fx (squibs, decals, impact sounds).
  • Client passes relevant data to server (aim vector, aim velocity, etc).
  • Server fires its own shot based on its own calculations of where the shot should go. Pure Authority.
  • Server multicasts its aim velocity vector to SIMS.
  • Sims fire a local using servers data.

On server hit, it multicast the hit location and normal to Sims for other client impact fx.
Damage is sent to the hit client by the auth proxy of that client. (RPC Owning client).

The data sent to the server from the firing client can be used for anti-cheat. If you aren’t going to use it, don’t send it.

Do to floating point precision errors the servers and clients shots will never match up. Even if the server uses the clients projectile velocity ( Aim Vector * muzzle velocity[float] ). There will be discrepancies in hit location.

This even the case with line traces. They’ll be close, but exact values.