Client side vs Server side shooting authority?

Hi all,
I am making a multiplayer shooter game and have some questions. It will be really helpful if someone experienced can clear my doubts.

Note: I know hacking can not be completely prevented but all I mean here is minimizing the loop holes in the game. Also, all I want is better user experience.

While shooting I am spawning the bullet on client as well, so that it doesn’t seems to be laggy that the player will wait for the server to spawn the bullet. Now the bullet has some random spread, so the bullet hit location at client and server will be different since it is randomly calculated. I don’t want that the client hits the enemy but won’t kill him because of the different spread at the server which might not hit the enemy. So as to provide better client experience I am just calculating the hit location at the client and sending the bullet hit location to server so that server and client bullet hit the same point. But this is prone to hacking (easy aimbot if someone could change its client code). Is my approach right? Sacrificing hack proof code for better client experience? Or there is some other way to prevent hacking even by having same bullet hit location on both client and server?

Now the second thing, with above approach, I have to send a reliable RPC every time a bullet is spawned. This means that a reliable RPC will be sent every 0.04s-0.8s according to gun’s fire rate. Is this ok because I have read that reliable RPCs should not be sent on every tick. The above rate is close to that of tick (though it will only be sent when the player is firing). Can this cause reliable RPCs to overflow?? Or this is fine since though it is sending reliable RPC’s at a fast rate but it is not on every tick as the player will not be firing all the time. Is this right? Can it cause problems?

Now if I go with sending hit location to server which is prone to hacking but provides better user experience. Then shall I go with client-side hit detection(applying damage on client and sending to server) instead of server-side hit detection(applying damage on server and replicating)? I am saying this because since it is already prone to hacking if I am sending hit location to server, so why not just add client - side hit detection too for more better user experience and also if I do this, then I could just send unreliable RPC to server in step 2 and that will solve the 2nd problem too? Should I do client-side hit detection also now since this will make better client experience? And then I will look for some other hack minimizing techniques which will not sacrifice the user experience.

It would be really helpful if someone could clear all these doubts as I haven’t found a proper explanation of this anywhere.

bump, i too would like another opinion on this, but so far , this is my approach as well to improve the client epxerience

1 Like

Don’t use reliable for something that frequent, if at all.

If your packet/shot RPC gets dropped, it gets dropped.

Think of a scenario where a player experiences not just one packet, but multiple seconds of packets being lost for whatever reason. Does it even make sense that all of their shots reliably get processed full seconds after they should’ve occurred? How does that even look to other players?

so what I’ve done for now is this(and I’m not done nor nowhere near server validation but this works until I get there)

player wants to fire, he fires locally his bullet…
he also tells server to multicast shots (but they only do visual/audio fx) and they skip the original player (they dont get called again for him)
the original player’s shots can do damage and ONLY upon hitting another player do they call a reliable RPC, this reduces the need to replicate every bullet reliably, only the actual HITS are sent reliably…

if its an automatic weapon only START FIRING and STOP FIRING are reliable RPC’s multicast to other clients with a timer set to firing rate that spawns the bullets locally… so 1 RPC to start firing, 1 to end… here you completely eliminate the need to call a reliable RPC for EVERY BULLET

I just made this today, so next step is server validation, but this is basically what I’ve been seeing in the games I’ve been playing(client sided bullet damage authority)…

How would you deal with bullet impact/whizby sound since other players would need to see that ?
I’ve tried a similar approach to you, the difference is everyone spawns a bullet except the dedicated server.

In most competitive FPS, the server will always have the final authority upon hit. What you’re trying to do on the client is to make the best possible prediction on what the hit will look like.

So, if we take your example:

  • Client fires the shot
  • Bullet is spawned on the client and is multicast to the other players
  • The server will be the final authority on whether the bullet has been a hit and will map the location of the hit.
  • In the meantime, the client will predict and correct as needed the location of the bullet as it receives the information from the server.

If there’s latency on an FPS, you might think you hit a player, but you actually didn’t, because the server has the current position of the player, while you are still set on their previous location.

A lot of time has been spent trying to find the best way to solve that problem on modern FPS. And so far the best solution has been to make client-side predictions and latency compensation because, at the end of the day, you need to rely on the server to validate the hit if you want your game to be competitive.

Valve made an excellent article on the topic. You should check it out: Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization - Valve Developer Community

If you want to reduce latency for your players, just not manage its effects on the player experience, there’s a new type of server provider that is focused on that. Edgegap, for example, will spawn a game server where your players are, instantly and on-demand.

thats exactly what I’m doing. Everyone spawns a bullet, except the firing client’s bullet is not only visual, it deals damage. The other clients bullets are just visual/audio/impact fx/etc.

1 Like

how would this example work with bullets that have tracers for example. you can’t just move a firing client’s bullet without a noticeable effect, or am I missing something. Also from what I read in the article you shared it seems to imply that if you think you hit a player, you hit him, it mentions the example that is all too well known for competitive gamers of being hit behind cover and that can ONLY happen if the client is allowed to tell the server where he hit, sure the server can validate it and say NO you were way too far away to fire that shot and then do something about that, but thats the validation part…

No, it’s not the client telling the server where they hit. Read the valve article about lag compensation, specifically the header Game Design Implications of Lag Compensation.

The server is rewinding time to approximate where the target player was in relation to the 1/2 rtt of the shooter (clamped to a threshold) or some fixed value you can configure like x ms. This can mean that the target player who gets hit may perceive themselves behind cover/a wall and still gets hit anyway, but this is the trade off for more accurate hit registration when dealing with latency. Otherwise players need to lead their shots.

The shooter Player does not tell the server where they hit though, you can opt to send that info for debugging or additional validation, but never trust it.

1 Like

I agree with what is saying. You should never trust the client to register the hit if you’re making a competitive game.

On the other hand, , you bring a good point with “tracers”. You would probably have to stray away from perfect realism and bend the bullet tracers when you receive the information from the server. That’s probably why we’re never going to see a Superhot multiplayer mode.

1 Like

You can synchronize the spread randomness using seeds.

Note that I’m gonna assume you are doing hit-scan weapons (ie. instant line traces), not projectiles. Projectiles are a whole different can of worms!

Regarding hit detection, I would suggest using client side hit detection (and I mean detection, aka. line trace → hit actor, NOT the part where you apply damage). Replicate hits to server, verify the hit on the server to mitigate major cheats, and apply damage on server. To avoid annoying user experience where hits do not register, don’t be too strict on the server hit verification. You want to implement something like an array of player positions during the past X milliseconds, so you can rewind the enemy position back to where it was when player fired Ping ms ago. And then test against a rough, slightly enlarged hit box to mitigate minor inaccuracies.

Client sending hit locations to server is not more or less unsafe than “standard” behavior where the client only updates its rotation and server calculates hit location. If one can write a cheat to modify the sent hit location, one can even more easily write a cheat to modify camera rotation to point to enemy (=aimbot). So you’re not really sacrificing anything imho.

2 Likes

we ended up switching our logic, we now have the clients only spawn visual fx, but the server spawned bullet is the one that causes damage… this way you still have instantaneous fx and you can use tracers which you might even see hit someone, but if the server doesn’t think so, tough luck… it happens a lot in most games where you swear “I lit him up” but he lost like -1 hp … it just feels safer this way… will look into the hit detection next, that sounds like the way to go…

1 Like

Nice! What about your Ammo design? What type of setup did you go with?