Search Unity

How would you approach lag-compensation for a "slow" projectile

Discussion in 'Multiplayer' started by PhilSA, Aug 2, 2017.

  1. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    So, I want the following things:
    • Shoot a rocket projectile in a fast-paced online game (imagine Quake 3)
    • fully authoritative server (server must simulate everything. Clients only send their inputs)
    • server does lag compensation for shots
    ____________________

    If I wanted to shoot with an "instant" projectile weapon; this would be fairly simple...
    1. Client sends request to press shoot with timestamp
      1. Client simulates the visual/anim aspect of the shot for responsiveness, but with no damage or important gameplay effect
    2. Server gets shooting request and rewinds all player positions to time of shot request
    3. Server simulates instant shot with a raycast and finds out if a player was hit
    4. Server replicates the visual/anim aspect of the shot on all clients except the one who shot (because they simulated it locally)
    5. If we hit a player, apply damage to the player and handle replication of the damage, vfx, etc...
    _____________________

    But if we are shooting a projectile that isn't infinitely fast, we can't just rewind player positions, do a raycast, and find out if it hit something. Any ideas on how this should be handled?

    My only idea right now would be to do several simulation steps from the shot request's time to the current server time... let's say at 0.02ms intervals, but I fear this might be too performance-intensive. Especially if all players are shooting fast-firerate slow-projectiles weapons all over the place.

    Also, you could make the rocket spawn at its calculated position at current server time based on its start point and its velocity, but then maybe it wouldn't be able to detect hits that were really close.
     
    Last edited: Aug 2, 2017
    akuno likes this.
  2. robochase

    robochase

    Joined:
    Mar 1, 2014
    Posts:
    244
    instead of rewinding & simulating forward, you could save like a second worth of player positions & look at that.
     
  3. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    https://forum.unity3d.com/threads/lag-compensation-simulation-back-in-time.486012/ Might help you a bit.
     
  4. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    But for projectiles. I think its easier to do them client sided. Cause even if u simulate on the client. If you hit x object on your end and expect it to blow up. But then on the server you missed. Thats going to be odd.

    And many games do that. I know for a fact Arma has bullets client sided. And battlefield aswell.
     
  5. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    As soon as you give the client the power to tell the server "i damaged this player", it opens the door for hackers to instantly kill everyone on the server, no?
     
  6. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    Well, I never said that you should just blindly trust what they are saying. But let them do the real simulation. And everyone else just does a own simulation for visual effect. Then you can verify if what they are doing is possible or not.

    Alternativley, Just do your normal lag compensation? Where the server spawns your object in past time and just "speeds up time" to make it the object catch up with current time. Should be no different from raycast lag compensation other than you have to catch up.
     
  7. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    oh, right.... I guess it could go like this:
    1. Client sends request to press shoot with timestamp, and simulates visuals locally, etc...
    2. Server gets shooting request, replicates on all other clients, but doesn't do any lag-compensation for the moment
    3. Later, client detects that the rocket hit someone, sends an "I think I hit someone at this time with this projectile" RPC
    4. Server gets that RPC, goes back to the exact time that the client says it hit the player, and checks if his rocket overlaps with the player
    This has all kinds of advantages:
    • We don't have to do the thing where we resimulate the whole trajectory of the rocket in one frame, so it's much lighter for performance.
    • We only have to rewind one single player for lag-compensation instead of rewinding all of them. Again, much better for performance. (although, now that I think about it, it might still be safer to rewind all players anyway in case the rocket's explosion affects other players too. But that's something that could be checked by the client as well. The worst thing that could happen if the client messes with the game and lies about its hit players is that it would hit less players than it normally would)
    • Server doesn't even have to constantly check if projectiles are hitting players. It only checks when the client asks to. More performance again!
    • The server remains 100% authoritative. Even if a client does a hack that tells the server every frame that they hit all players, he will still only hit the players he would've truly hit with his projectiles spawned on server. The client only helps the server know when to check, for optimization purposes. The only negative effect this sort of hack would entail is more calculations on the server, but we can solve that with sanity checks that would detect that it doesn't really make sense that someone would be hitting all players every frame when they only have 1 or 2 projectiles spawned
    thanks!
     
    Last edited: Aug 2, 2017
    andreyefimov2010 and akuno like this.
  8. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    That's one approach. Then you have Client authority over the rocket. But you verify results on server.

    But if you want normal lag compensation. I don't really see your problem? Just spin back time. Spawn the bullet. Then fast forward time to syncronize where the rocket should be in current time. (You basically do physics iterations as a part of your simultaion).
     
  9. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    that approach would surely work, but I'd be very worried about performance on the server

    Imagine if 16 players are shooting with some kind of Link Gun from UT (rapid-firing slow bullets). In that case, the server would have to simulate several frames almost every frame.....
     
    Last edited: Aug 2, 2017
  10. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    I mean, you could offload to a separate thread? That would be a bit complicated though.
    Or if you want to go down the super difficult path. Do it in a couroutine. Then you can spread the work over multiple frames. But that will be kindoff difficult as you need to make sure you reserve some extra position data for the coroutine so your main loop doesn't clear it. And you also have to resync the corotuine state with the main games every iteration of the corotuine and also when you're done. That's going to have significant overhead.

    But I guess the approach you are taking now is fine.