Search Unity

Question Is it possible to get the last valid Server transform on a client?

Discussion in 'Netcode for GameObjects' started by UnkelRambo, Dec 14, 2022.

  1. UnkelRambo

    UnkelRambo

    Joined:
    Oct 26, 2012
    Posts:
    80
    Hi!

    I've got a situation where I'm animating some stuff using PositionConstraint as described in the Boss Room pick up action here:

    https://github.com/Unity-Technologi...meplay/Action/ConcreteActions/PickUpAction.cs

    One problem I'm running into with using this is that it's possible for the client and server to become mildly out of sync doing this, and I'm struggling to find a good fix.

    The exact situation is this:

    I've got an async method that runs some ability (pickup, drop, throw, etc.) In this async method, I do client-only animation (no animations run on dedicated servers for perf reasons). During the client animation, I attach an object to a bone, do an animation, then detach the object from the bone in the async ability method. Sometimes, the ability is interrupted by the SERVER and cancellation of the async ability task on the CLIENT is triggered. For instance, if something hits the player while they're picking something up, it forces them to drop it (which can happen when the client is doing the animation and awaiting ability validation from the server.)

    After the client animation plays, the new position of the attached object will be X on the CLIENT. The server interrupted the ability, forces the player to drop the object, which is now at (authoritative) position Y on the SERVER.

    So, my question is this:

    Is there any good way to get the authoritative position Y on the CLIENT so the no-longer-attached object doesn't appear at the now out-of-sync position X?

    I looked for a way to mark the NetworkTransform (ClientNetworkTransform, in my case) as Dirty on the server but I couldn't really see a way to do this directly.

    My somewhat fragile fix for this is to teleport the object to a *slightly* different position on the server after an interrupt. It mostly works... mostly... but I'm expending extra logic finding a valid teleport spot, which I'd like to avoid.

    Thoughts?

    Thanks!
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,882
    To interrupt this animation, I would assume the server sends a YouGotHitSoDropItClientRpc(). The server knows the object the client is about to pick up, so it can just pass the current authoritative position along with the RPC message. The client uses that to reposition the item that was in the process of being picked up.

    Note that NetworkTransform has a "Teleport" method. I cannot remember the name exactly but it definitely has "teleport" in its name. If you call that, even with the exact same position the object is currently at, it will force the NetworkTransform to be synchronized.
     
    UnkelRambo likes this.
  3. UnkelRambo

    UnkelRambo

    Joined:
    Oct 26, 2012
    Posts:
    80
    There's actually no RPC sent, only replicated state. This is important for join in progress for other abilities to function correctly.

    Teleport is exactly what I'm doing, and like I said it *mostly* works except when the teleport position is within the position threshold that gets checked in ApplyTransformToNetworkStateWithInfo().

    My workaround is stupid, but it works. I teleport the object OUT of that threshold, then teleport it back to its original position. Which is a silly workaround to being able to force the transform to be dirty like you can with NetworkVariable.SetDirty().

    Where this fails is when gameplay code acts on a transform change event, which I currently only have one minor thing (deriving Velocity on remote clients for walk animation speed. My networking situation is a bit weird lol)

    Maybe this belongs in a feature request, because what I'm REALLY looking for is a NetworkTransform.SetDirty() method. I'll post something in the GitHub and respond here I guess...
     
  4. RikuTheFuffs-U

    RikuTheFuffs-U

    Unity Technologies

    Joined:
    Feb 20, 2020
    Posts:
    440
    yeah, you shouldn't be doing these hacks, lol. if you can open a feature request, that'd be great!
     
    UnkelRambo likes this.
  5. UnkelRambo

    UnkelRambo

    Joined:
    Oct 26, 2012
    Posts:
    80
    Hacks are my middle name :cool:

    On a previous AAA project I worked we had a render call in a placement new operator to pass Cert.

    This is nothin ;)

    I'll open a feature request now and post back here in a bit...
     
    RikuTheFuffs-U likes this.
  6. UnkelRambo

    UnkelRambo

    Joined:
    Oct 26, 2012
    Posts:
    80
  7. NoelStephens_Unity

    NoelStephens_Unity

    Unity Technologies

    Joined:
    Feb 12, 2022
    Posts:
    257
    Have you tried using NetworkTransform.SetState on the server-side with teleportDisabled = false?
    This will force the owner client to set its transform and will force it to mark itself dirty. That will be updated back to the server, which it then gets propagated out to any other non-authoritative clients currently connected.
     
  8. UnkelRambo

    UnkelRambo

    Joined:
    Oct 26, 2012
    Posts:
    80
    Interesting! I'll give it a shot and see how it works out. I'm ankles deep in join-in-progress ability code today so might not get to it but appreciate the response!