My bullets aren’t actors or anything, but they are points in space that’re updated, with line-tracing in between the old pos and the new pos each frame. I was thinking that I’d RPC out every impact location, otherwise how can I ensure the FX are synced? I.e. if I leave it up to clients to simulate each bullet and determine the impact, even a tiny bit of lag = impact FX (dust clouds, bullet holes) totally off from where it should be.
Unless you have a really good connection, The game will have a better flow and feel for the player if the hit test is on the client.
That’s why in online games when you shoot someone, there can be the hit sound, the blood splatter etc, then they’re still standing.
because the client ran through what it thought happened, then the server left the player alive as the authority on whether the hit happened, but from a player perspective it’s more fluid to accept that what it saw was true.
Edit:
I think I’m not all here this morning, it seems that’s what you’ve done
Sorry about that. I saw the “Impact effects” being called by the server and missed the ‘local effects’
Though my point about the bloodsplatter etc still stands, there’ll be a lag, which is why games tend to go ‘client hit the person THEY SEE so do everything as if they had, but the server decides whether anyone else sees that’
This is where I get confused - should the other players be simulating the hit impacts, or waiting for the server to tell them the real impact location so it matches up? If they’re already waiting for the server (to hear about the shooting itself), why not a fraction longer to get the real location? Problem is if it’s a long-range shot… could be a while
depends what your ‘bullets’ are like.
is there a ‘smoke line’ from the gun to the bullet?
how complex is your fx? ie, is there a front and back bullet penetration?
Because if it’s just simple blood splatter I’d suggest:
client:I shot to VectorX, spawn fx,
Server:there’s a guy there, you hit him in the neck
Remote:guy got shot at [mesh location (neck)], spawn fx[if not client who shot] and ragdoll,
Everyone who’s not the shooter sees blood and a collapsing person equally, except the guy who shot which sees the blood slightly before that.
The dead reckoning being used for the ‘victem’ Should not continue the motion of the pawn, so they may appear to freeze before they fall, but in normal networking scenarios this should appear seamless
There’s basically nothing between bullet and gun - the bullets aren’t even visible. No tracers, nothing. Just muzzle flash / sound, then hit impact at the other end. What if the flight time is a full second? People getting shot hear/see it a full second + (round-trip time / 2) later.
I’m not going to respond for 5 mins, let everything even out, then continue
But basically muzzle flash/sound all ‘fire’ related things should be sent out asap, but the ‘hit’ effects should be confirmed by the server for everyone. The shooter might end up seeing a blood splatter that no one else did, but that’s only in rough network conditions
Since there are no visible bullets/trails, I suppose as long as everyone hears the sound / sees the muzzle flash at roughly the same time, the flight-time of the bullet is irrelevant - they’ll feel/see the hit a fraction of a second later. And hopefully the different between the real shot and the local shot/muzzle flash, and the real impact and the local impact are the same, so it all appears consistent (i.e. if I’m 50ms behind the real shot with the playing of my FX, my hit impact is also 50ms behind the real impact, so I could time it out and get the true shot distance).
It still feels odd to me - how can someone react properly if a burst of shots has been fired, and by the time they hear the first one, all 3 have already landed?
What you’ve got, in your flow chart is right.
I may have confused things with my examples/ramblings.
On remote hit locations
these should be given to the remotes by the server, reduces unneeded calculations on their side.
When the ‘hit’ reaches the remote doesn’t really matter, only that it’s accurate when it gets there. if they simulate they could me wrong and you’ve had the same calculation done on multiple machines for no reason.
Long flight times
If there’s long flight times, they’ll still have heard/seen the muzzle flash when it was fired. The hit effect can be later, the flight time might be a second, but the lag from the server won’t be, so they’ll get shot/hear someone get shot at the right time.
Here’s a case where your 2nd last post doesn’t work as well - what if the gun firing also fires a tracer round? That would have to appear and fly from the time the remote client is told about the shooting, until the remote client is told about the impact. If it didn’t match up, they’d see the tracer stop/hit one location, and a dust cloud / bullet hole in another. If you didn’t simulate it on remote clients, however, you’d get no tracer at all (or you’d need the server to constantly tell them the position, and that’s just crazy).
Well, that’s why I mentioned before about it depending on how complex everything is.
I can’t give you a ‘definitive’ answer, in my experience no one has one.
The best you can do is when you send the ‘fire’ from the server, to tell the remotes the sound, then they just draw the tracer line from the sound location in the right direction.
In Halo 2&3 the line is drawn that way, on the sound playing. This can create the problem of the trace line missing someone who died from the shot (i’m sure we’ve all seen it) but it’s a balancing act.
You’re programming for the 70% of the time when the delay makes it negligible
Small fix on my end:
Behavior should always be dictated by the server, you have the client setting bIsShooting=true, it should be the server. The client requests the shooting, the server evaluates whether or not the client can shoot, if it can, spawn the appropriate stuff and define client behaviour.
Good point, though I suppose that’s a result of being brief. I more meant with that one flowchart node that the client would try to shoot, play a local effect so they feel it straight away, and then tell the server, which sets bIsShooting to true and replicates it to the remote clients
Another few questions that came to me;
What about the muzzle flash - should it occur at a world position in space, or from the muzzle of the remote player that’s shooting, as far as the client is concerned? I.e. if a player shoots, and another client sees it but the positions are out of sync, does the muzzle flash appear on the model, or where the model should be?
Also;
T=0: I fire, tell server
T=50: Server sees I fired 50ms ago. Does it roll me back and fire at the old position or at the position I am on the server at T=50?
T=100: Remote clients know that I fired. Am I at a different position to where I was on my client at T=0 (the actual firing position), and where I was on the server at T=50?
With the above, it seems like there are multiple positions I’m at when the fire FX / functionality occurs?
Edit: Another problem. If there’s lag after player A starts shooting, and thus the bIsShooting variable is set to true for their character for all players, won’t other players see them shoot for longer (i.e. they’ll fire more rounds) than they really did? The lag means that the bIsShooting variable is set to false later than it really was, so they believe the gun is still firing and thus play extra FX etc.
Sorry, only got back online now. First the Muzzle
Muzzle flash should be part of the gun, spawned from the actor and called by the server. That way it always syncs up.
Second, the firing and the server
As far a the server is concerned, you fired as soon as it got the message, the lag should be negligible here. you will see your muzzle flash at the end of your gun actor, other’s will see it at the end of the replicated gun actor. They might be slightly different, but again this is a tenth of a second difference.
Edit question
There wouldn’t be a lag in the time the gun is fired, the false would be subject to the same lag as the true. So the fx would be fired for the same length of time, just starting and finishing slightly later.
With the second, I’m not talking about the effect, I’m talking about the actual bullet spawn location and resultant trajectory.
T=0: I fire
T=50: Server receives it, server fires. Does it fire from where I was or where I am now? If it’s where I am now, my bullets won’t land where I was aiming, potentially, since what if I was moving at the same time? It’s now 50ms behind where I wanted to shoot from, so I can never truly hit my target. I know that the game Counterstrike rolls back in time to where you were when you fired, to make sure that if YOU saw that you were aiming correctly, you’ll hit them, even if the server disagrees by the time it gets the message and the newest positions. (Obviously server is still the authority, hence it winding back and making its own decision).
And with the third;
I mean if the ping changes halfway through, i.e.
T=0: I fire, bIsShooting is true locally.
T=50: Server receives, sets bIsShooting to true, and passes along
T=100: remote client recieves bIsShooting = true, and start firing its view of my gun at the gun’s fire rate.
T=150: I stop shooting. bIsShooting = false locally
T=200: Server receives, sets, and passes along.
remote client’s ping increases dramatically, i.e. from 50ms to 200ms -
T=400: Remote client recieves bIsShooting = false, and stops firing its view of my gun.
I held my fire button for 150ms, but remote client saw me shoot for 300ms. At a high rate of fire, that may be an extra bullet or two that don’t ever exist and don’t ever have a hit location / hit FX.
I’ll answer these in reverse order,
If the ping changes halfway, then yes this will happen. You could get a ‘bullet count’ and compare later etc, but it’s really just something that happens as a result of the implementation.
They all have downsides and upsides. If you for example had the client not fire until a ‘wantsToFire’ flag comes back from the server, then you would get round this leaving the potential for lag on fire.
That can be fixed by the animation/sound all playing for the shooter, while they’ve not actually fired until the server says so.
It’s all a balancing act with feeling fluid, realistic gameplay, lag.
The first problem is down to how much lag you expect.
You could say, Store the player’s position when they fire and the server would use the value the shooterClient gave them(which might differ from what the server said)
You could take the midpoint of “where they said they were” and “Where server says they are”(which is a wrong place, but if lag is reasonable, it’s not far)
The problem with rolling back time is that you need to know how far back to roll, do you use ping/2? how are you testing ping? how often?
And how do you ‘roll back’? apply the reverse of their vector (which would be wrong if they’ve turned recently) do you store their last ~500ms of locations and pick the right one?
I mean, what you’re suggesting is what we’re already talking about - the local client isn’t actually shooting, but just plays the FX and tells the server. Obviously the local client will have to simulate its own bullet so it sees the impact at a reasonable time, rather than waiting for the server to come back with the right location, no?
And re. your second point - I ended up creating a time sync setup taking lag into account that can pretty closely synchronize a time value across the network. I’d time-stamp the shooting message and have the server roll-back to that time. I’d store all player positions/rotation states for the last ~500ms, in x ms segments. If we ignore the time problem, would that be a sensible way to do it?
From your answers, I’m worried I’m over-blowing the issues of lag-related desync, but it sounds logical that it could be a problem.
First point, you have to look at what you want to happen in your ‘worst case’
if you simulate everything on the client side, then you’ll have bullet marks others don’t see/see them differently, and blood splatters from people you didn’t hit.
if you simulate All gun things client side, and wait for server to tell you the hits, you’ll have bullet marks that seem to appear from no-where, people standing about before they fall down.
I would always opt for everything client side, as it’s all visuals, all the stuff that effects the other players with the server.
it means the server and the client need to do the bullet calculation, but if there’s no physical bullets it’s just a raycast and the client will be fine.
I think that’d be a sensible way to do it.
personally, I’d not try lag compensation until lag became a problem. As you’ll not have thousands of people connecting to your app from around the world from day one.