Search Unity

Resolved Synchronising a projectile (spear) in a fair but responsive way.

Discussion in 'Netcode for GameObjects' started by Serinx, Jan 15, 2023.

  1. Serinx

    Serinx

    Joined:
    Mar 31, 2014
    Posts:
    788
    I'm creating a game with client authority for movement/animation.
    I want the player to be able to throw projectiles like spears at their opponents, but because of the slight delay, the location of the spear and hit detection could look different depending on the point of view of the client1 vs host vs client2.

    For example:
    Say client 1 is throwing a spear at client 2, who wants to see the spear coming in order to dodge out of the way.

    1. client 1 instantiates the spear and asks the host to instantiate it and spawn it for clients
    50ms
    2. host receives the RPC, instantiates the spear, and tells client 2 to instantiate
    50ms
    3. client 2 receives the RPC and instantiates the spear

    at this point, the spear is probably halfway to client 2 from client 1's perspective, not giving them enough time to react.

    I want the client who throws the spear to hit if it looks like they hit on their system. I'm ok with the hit being a *little bit* off on the receiving client, but not like they ran around the corner 2 seconds ago and still got hit.

    My ideas are:
    1. Start the throwing animation, but wait for the server response before "finishing" the throw animation.
    This could make the animation inconsistent on the throwing client depending on their ping, but should sync things up

    2. Send the start time of the animation to the host & client so they can advance the throwing animation or speed it up accordingly. This would sync things up and have the spear appear at the same time but the animation would look a bit awkward on the receiving end

    3. Let the host set a ping limit to reduce the impact of this issue.

    I like idea 1 the most, as it prevents people with really high ping from scoring a hit before the receiver is even aware of it. But I'm still not super happy with it.

    Does anyone have any ideas or references for the best way to handle this?
     
  2. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    Hi @Serinx , what you need is Client side prediction + Reconciliation (or a client-driven variant of it). This is not available in Netcode For GameObjects out of the box, but if you google it you'll be able to find sevral relevant articles on how to implement it for you specific use case.

    Hope this helps ^.^
     
  3. Serinx

    Serinx

    Joined:
    Mar 31, 2014
    Posts:
    788
    @RikuTheFuffs-U thanks for the feedback!

    I did some digging after your comment and found this halo networking video about how it handles grenade throws which seems to perfectly fit my spear throw scenario!



    Basically, you have client authority over the animation, but host authority over spawning the grenade. Players typically don't notice that there's a small delay between the peak of the throw animation and the grenade appearing because they're so focused on aiming at their target, and because the animation begins immediately it feels responsive, and the clients should all see the spear appear at the same time.

    I'll add a little video once I've implemented this solution to see how it looks it action!
     
    RikuTheFuffs-U likes this.
  4. Serinx

    Serinx

    Joined:
    Mar 31, 2014
    Posts:
    788
    @RikuTheFuffs-U Here it is! Ignore the bear.



    I have 1 slight issue which you might see in the video. When the spear spawns on the client, it seems to have no physics applied for the first frame and is kinda suspending in mid air before flying.

    I'm using a NetworkRigidbody on the spear and applying force on the server only on networkspawn.
    Is this the correct way to handle this?
    I tried applying force to the object on the server before calling Spawn but it didn't appear to apply force at all.

    I might try getting the client to apply the initial force on spawn and then set the rigidbody to kinematic when receiving the first transform update from the server. Would that work?

    Thanks!
     
  5. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    Hey @Serinx , happy to see that you're making it!

    In theory I think so, but in practice I guess that the the server's OnNetworkSpawn might be called a bit earlier than the client's. Can you check this?

    This shouldn't be needed if you're using NetworkRigidbody (according to the docs), because the simulation is happening on the server. However, depending on how you implemented this system, you might need to apply the same force on the client.

    This is why making Prediction + Reconciliation is hard :(
     
    Serinx likes this.
  6. Serinx

    Serinx

    Joined:
    Mar 31, 2014
    Posts:
    788
    @RikuTheFuffs-U I found some old Unity documentation that mentions forces are not instantly applied to spawned network objects which I think was causing my suspended projectile issue.

    I realised in that Halo video they said "The grenade disappears for a second and nobody notices". I ignored that sentence for some reason but have now realised that would absolutely fix my problem.

    I just make the spear invisible for 0.1 seconds and then show it and it looks perfect now! And they were right - it's hardly noticeable.

    You would only see if suspended now for whatever your latency is - 100ms which is fine by me, I'd hope the players were under 100ms anyway xD
     
    RikuTheFuffs likes this.