Search Unity

  1. Check out the Unite LA keynote for updates on the Visual Effect Editor, the FPS Sample, ECS, Unity for Film and more! Watch it now!
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

[RELEASED] Smooth Sync - Smoothly network rigidbodies and transforms while reducing bandwidth

Discussion in 'Assets and Asset Store' started by Fuestrine, Aug 4, 2017.

  1. foolmoron

    foolmoron

    Joined:
    Jun 22, 2013
    Posts:
    28
    I tried a bunch of things and nothing really got rid of the initial catch up lag. Higher FORCE_TIME_SYNC_DURATION, higher timeCorrectionSpeed, lower snapTimeThreshold, nothing quite did it. I don't really get what's going on in this function I guess.
     
  2. Fuestrine

    Fuestrine

    Joined:
    Feb 13, 2013
    Posts:
    257
    @foolmoron
    I've got the issue narrowed down on my end. It's because that FORCE_SYNC goes off only once on the server when a client joins if the client doesn't move. The issue isn't seen on clients(at least not the way I'm testing). Then by the time the client actually moves, it's done forcing the time change so it just slowly adjusts.

    I've got a fix in now where I keep automatically setting the new time for an amount of received States equal to a ratio of the SendRate, but I'm going to need to look at it again when I wake up to be certain.
     
    Last edited: Nov 5, 2018
  3. Fuestrine

    Fuestrine

    Joined:
    Feb 13, 2013
    Posts:
    257
    Version 3.08 has been submitted to the Asset Store.

    Change log:
    • Fixed issue with slow time correction at beginning on server when client doesn't move initially.
    • Smooth Authority Changes fix for all uses.
    • Fixed 2D rigidbody not working with velocity driven syncing.
     
  4. Richie_V

    Richie_V

    Joined:
    Dec 3, 2014
    Posts:
    3
    Hello, I just would like to say I would be also interested in Mirror support, I am working on a LAN only project using Smooth Sync, and Mirror is the best solution I've found for that, and unlike PUN, or the upcoming Unity Networking solution, Mirror is open source and free to host, so just to add to the suggestion, maybe it is worth it to support the simplest truly free solution out there with your asset :)
     
  5. the_dunderman

    the_dunderman

    Joined:
    May 4, 2017
    Posts:
    4
    Hey Fuestrine,

    We are a small team working on a prototype for a networked version of our developed local multiplayer game using PUN2. We were having jittering issues, and decided to use your asset to smooth things out.

    I have been tweeking settings on the smooth sync script in our test scene for the past 3 days, and I am having some seemingly unsolvable issues. It is easy enough to smooth our players for non-master clients using your script. All our issues are with physics based objects in the scene that can be affect by either player, and thus are server owned. As you can imagine, our master client sees a perfect simulation of the objects being interacted with, as it does all of the physics calculations for the photon server.

    One example of a big issue we're having is with a stack of cubes (with an empty parent) that the players can crash into. When we use the smooth sync script, we can get a pretty smooth and accurate interaction with a non-master client if we check the "Use Velocity Driven Syncing" box under misc. However, this causes the cube to, what we're calling, "melt" on the non-master clients screen. The boxes slowly drift away from each other on the non-master clients scene, but on the master-clients scene, they are perfectly still. If either player hits the cubes, they teleport back to the position they should be, and then accurately simulate the rigidbodies being hit.

    Our player (also with an empty parent) has "Use Velocity Driven Syncing" checked, and the issue with this is sometimes the positions aren't synced on player screens.

    Why is this happening when we check this box? Shouldn't transform positions still be synced while also trying to affect velocities of an object? Why are they not synced, and in completely different places on the screen until they are interacted with (Our Photon Views are set to "Unreliable")? I saw that for UNET parent objects also require your script. I'm not sure if this is true for PUN2, and if it is, how should we be configuring these settings? How should parent and child versions of your script differ if it is required to attached them in both places?

    We also have a lot of "rope" like objects in our game, which are a bunch of fixed joints attached to one another. We are having trouble between non-master client and rope interaction using the settings that work for the cubes, but there is no "melting" for the rope.

    Any tips or answers to my endless amount of questions, or even just one, I think would help. Let me know if you need any more info to help answer any of these as well.

    Thanks,
    Matt
     
    utkarshdwivedi3997 likes this.
  6. Fuestrine

    Fuestrine

    Joined:
    Feb 13, 2013
    Posts:
    257
    @the_dunderman
    Thanks for bringing it to my attention. It looks to be a problem with at rest when using the VelocityDrivenSyncing.

    I'll have to make a cleaner version and take a deeper look at it this weekend, but changing the else if code block that starts on line 868 of SmoothSyncPUN2.cs to this solved the issue for me.
    Code (CSharp):
    1. else if (stateBuffer[0].atPositionalRest && stateBuffer[0].atRotationalRest)
    2. {
    3.                 targetTempState.copyFromState(stateBuffer[0]);
    4.                 extrapolatedLastFrame = false;
    5.                 if (setVelocityInsteadOfPositionOnNonOwners) triedToExtrapolateTooFar = true;
    6.             }
    I didn't need to change MaxPositionDifference (underneath UseVelocityDrivenSyncing) for the fix but it should make it more accurate overall if you lower that.

    You may also be getting extrapolation issues, try turning extrapolation off if the above code doesn't fix it.

    I don't think there are any issues with them being children or not. You just need a SmoothSync on each object you want to sync, child or not, with the way Photon works I believe.

    Let me know how it goes, if you have any questions, or if I missed anything.
     
    Last edited: Nov 10, 2018
    the_dunderman likes this.
  7. Fuestrine

    Fuestrine

    Joined:
    Feb 13, 2013
    Posts:
    257
    @Richie_V
    Fine, you've all convinced me to take a deeper look at it. :)
    I've been seeing it around online a bit lately too.

    I'm not promising anything but I'll take a better look at a conversion and see how it would be for me to put out releases.
     
    Last edited: Nov 10, 2018
    Richie_V likes this.
  8. iStolyarov

    iStolyarov

    Joined:
    Oct 29, 2018
    Posts:
    2
    Hi! I have two problem if i use plugin with Photon (PUN V1) on Unity 2018.2.13f1:
    1. If i add Smooth Sync PUN (Script) to GameObject i have a Error and object not synced.
    Code (CSharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    2. UnityEngine.Networking.NetBuffer.ReadByte () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkBuffer.cs:33)
    3. UnityEngine.Networking.NetworkReader.ReadByte () (at C:/buildslave/unity/build/Extensions/Networking/Runtime/NetworkReader.cs:160)
    4. Smooth.NetworkStatePUN.Deserialize (UnityEngine.Networking.NetworkReader reader, Smooth.SmoothSyncPUN smoothSync) (at Assets/!IMPORTED/Smooth Sync/Other Networking APIs/PUN/Smooth Sync Asset/StatePUN.cs:440)
    5. Smooth.SmoothSyncPUN.OnPhotonSerializeView (PhotonStream stream, PhotonMessageInfo info) (at Assets/!IMPORTED/Smooth Sync/Other Networking APIs/PUN/Smooth Sync Asset/SmoothSyncPUN.cs:2028)
    6. PhotonView.ExecuteComponentOnSerialize (UnityEngine.Component component, PhotonStream stream, PhotonMessageInfo info) (at Assets/!IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/PhotonView.cs:532)
    7. PhotonView.DeserializeComponent (UnityEngine.Component component, PhotonStream stream, PhotonMessageInfo info) (at Assets/!IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/PhotonView.cs:378)
    8. PhotonView.DeserializeView (PhotonStream stream, PhotonMessageInfo info) (at Assets/!IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/PhotonView.cs:363)
    9. NetworkingPeer.OnSerializeRead (System.Object[] data, PhotonPlayer sender, System.Int32 networkTime, System.Int16 correctPrefix) (at Assets/!IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:4399)
    10. NetworkingPeer.OnEvent (ExitGames.Client.Photon.EventData photonEvent) (at Assets/!IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:2631)
    11. ExitGames.Client.Photon.PeerBase.DeserializeMessageAndCallback (System.Byte[] inBuff) (at <f525be5a15db43b28dff4016d8fa9620>:0)
    12. ExitGames.Client.Photon.EnetPeer.DispatchIncomingCommands () (at <f525be5a15db43b28dff4016d8fa9620>:0)
    13. ExitGames.Client.Photon.PhotonPeer.DispatchIncomingCommands () (at <f525be5a15db43b28dff4016d8fa9620>:0)
    14. PhotonHandler.Update () (at Assets/!IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/PhotonHandler.cs:161)
    15.  
    upload_2018-11-12_11-56-31.png
    2. If i use Smooth Sync (Script) my GameObject after load the GameScene throw the error but, if i enabled the gameobj in Editor script work fine.
    Code (CSharp):
    1. The observed monobehaviour (Player - Basic(Clone)) of this PhotonView does not implement OnPhotonSerializeView()!
    2. UnityEngine.Debug:LogError(Object)
    3. PhotonView:ExecuteComponentOnSerialize(Component, PhotonStream, PhotonMessageInfo) (at Assets/!IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/PhotonView.cs:544)
    4. PhotonView:DeserializeComponent(Component, PhotonStream, PhotonMessageInfo) (at Assets/!IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/PhotonView.cs:378)
    5. PhotonView:DeserializeView(PhotonStream, PhotonMessageInfo) (at Assets/!IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/PhotonView.cs:363)
    6. NetworkingPeer:OnSerializeRead(Object[], PhotonPlayer, Int32, Int16) (at Assets/!IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:4399)
    7. NetworkingPeer:OnEvent(EventData) (at Assets/!IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/NetworkingPeer.cs:2631)
    8. ExitGames.Client.Photon.PeerBase:DeserializeMessageAndCallback(Byte[])
    9. ExitGames.Client.Photon.EnetPeer:DispatchIncomingCommands()
    10. ExitGames.Client.Photon.PhotonPeer:DispatchIncomingCommands()
    11. PhotonHandler:Update() (at Assets/!IMPORTED/Photon Unity Networking/Plugins/PhotonNetwork/PhotonHandler.cs:161)
    12.  
     
    Last edited: Nov 12, 2018 at 4:08 PM
  9. mrmirhajian1996

    mrmirhajian1996

    Joined:
    Sep 18, 2018
    Posts:
    1
    great asset. I am using it to create a motorcycle race game,but there is an issue.
    when motorcycle 1 overtake motorcycle 2 in host, the motorcycle 1 overtake motorcycle 2 after one or even two seconds in client. what fields should i change ? what am i doing wrong ?
     
  10. Fuestrine

    Fuestrine

    Joined:
    Feb 13, 2013
    Posts:
    257
    @mrmirhajian1996
    Lower your InterpolationBackTime probably. It puts it this far back in time on purpose.

    Keep in mind that if your InterpolationBackTime is less than your SendRate/100 (sendRateOnSerialize in photon?) then you will be extrapolating a bit between every received message.

    Let me know if this doesn't fix your issue.
     
  11. katasteel

    katasteel

    Joined:
    Nov 21, 2014
    Posts:
    160
    So I just got the newest version of SmoothSync and I see you made the teleport function need Local Authority at some point.

    What about things like projectiles from monsters which have no local authority?

    Teleport needs to be used when using object pooling.
     
  12. Fuestrine

    Fuestrine

    Joined:
    Feb 13, 2013
    Posts:
    257
    @katasteel
    I think that's always been the case. I don't know how you would send a message if you don't have authority and Smooth Sync has never used separate objects to send messages around.

    The monster's (EDIT: projectile) local authority would be the server if it isn't owned by any non-server clients, unless I'm completely misunderstanding something.

    Let me know if I'm misunderstanding or if you have further questions.
     
    Last edited: Nov 13, 2018 at 11:57 PM
  13. Fuestrine

    Fuestrine

    Joined:
    Feb 13, 2013
    Posts:
    257
    @iStolyarov
    I'm seeing the same thing on my end. Sorry about the PUN issue and thanks for bringing it to my attention. It's being very tricky to track down though, I'll have to take another look at it tomorrow and get back to you.
     
    Last edited: Nov 13, 2018 at 6:26 AM
  14. the_dunderman

    the_dunderman

    Joined:
    May 4, 2017
    Posts:
    4
    @Fuestrine

    Thanks so much for the answer. We took a dive into the code and it stopped our "melting" issue. I also set the local rigidbody component's velocity and angular velocity to Vector3.zero in that if statement you suggested to us.

    One thing we found was an if block that didn't run correctly because you had an new if statement for your 2D rigidbody check rather than an "else if", which caused the else statement to run every time for us since we are using 3D rigidbodies. This was in SmoothSyncPUN2 around line 1350-1360, and our new code looked as followed (just changed the second if to an else if)

    Code (CSharp):
    1. if (hasRigidbody && !isTeleporting && whenToUpdateTransform == WhenToUpdateTransform.FixedUpdate)
    2. {
    3.     rb.MovePosition(position);
    4. }
    5. else if (hasRigidbody2D && !isTeleporting && whenToUpdateTransform == WhenToUpdateTransform.FixedUpdate)
    6. {
    7.     rb2D.MovePosition(position);
    8. }
    9. else
    10. {
    11.      realObjectToSync.transform.position = position;
    12.      DebugTransformChange();
    13. }
    We do have a new issue though, and maybe this isn't smooth sync related, but right now our clients "bounce" off of other rigidbodies that the master client has no issue affecting. What I mean by this is our player has a mass of 10, and we have a stack of cubes that are no longer melting at a mass of 1. Our master client will barrel through and knock the cubes over, but our normal client will hit the stack, bounce off, and affect the cubes as if the normal client barely hit the stack.

    Almost none of the options for SmoothSync seem to alleviate the issue here.

    Have you faced this problem before? Do you believe it to be an issue with SmoothSync, or rather our PUN connection in general?

    We took off smooth sync and just used the normal PhotonView for Rigidbody, and this issue isn't present. Any input would be helpful.

    Thanks again,
    Matt
     
  15. katasteel

    katasteel

    Joined:
    Nov 21, 2014
    Posts:
    160
    It's calling teleport on the server from an object that does not have authority and gets a warning and never teleports because of this:

    Code (CSharp):
    1.             if (!hasAuthority)
    2.             {
    3.                 Debug.LogWarning("Trying to teleport from an unowned object. You can only teleport from an owned object. Look up Unity networking object ownership.");
    4.                 return;
    5.             }
     
  16. Fuestrine

    Fuestrine

    Joined:
    Feb 13, 2013
    Posts:
    257
    @katasteel
    You'll need to call it on the owned object. Owned objects have hasAuthority == true. I don't know of any way to send a message from an unowned object. It goes against how UNet works unless I'm misunderstanding something.

    Let me know if I'm missing something or if you have further questions.
     
  17. Fuestrine

    Fuestrine

    Joined:
    Feb 13, 2013
    Posts:
    257
    @iStolyarov
    Alright, I believe this will fix the issue. Sorry again and thanks for letting me know about it.

    I'll be cleaning up the code for release but here's the fix: Replace this with the OnPhotonSerializeView in SmoothSyncPUN.

    Code (CSharp):
    1. bool sentMessage = false;
    2.         public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    3.         {
    4.             // When sending data.
    5.             if (stream.isWriting)
    6.             {
    7.                 // Determine if and what we should send.
    8.                 sendState();
    9.                 if (shouldSendNextPUNUpdate)
    10.                 {
    11.                     sentMessage = true;
    12.                     stream.SendNext(sentMessage);
    13.                     NetworkWriter netWriter = new NetworkWriter();
    14.                     sendingTempState.Serialize(netWriter);
    15.                     // Sending the serialized byte array
    16.                     stream.SendNext(netWriter.AsArray());
    17.                     shouldSendNextPUNUpdate = false;
    18.                 }
    19.                 else
    20.                 {
    21.                     sentMessage = false;
    22.                     stream.SendNext(sentMessage);
    23.                 }
    24.                 // Set variables for use next frame.
    25.                 positionLastFrame = getPosition();
    26.                 rotationLastFrame = getRotation();
    27.                 // Reset flags back to default.
    28.                 resetFlags();
    29.             }
    30.             // When receiving data.
    31.             else
    32.             {
    33.                 bool receivedSmoothMessage = (bool)stream.ReceiveNext();
    34.                 if (receivedSmoothMessage)
    35.                 {
    36.                     NetworkStatePUN networkState = new NetworkStatePUN(this);
    37.                     //if (stream.Count > 0)
    38.                     {
    39.                         // Receiving the byte array
    40.                         object objectTemp = stream.ReceiveNext();
    41.  
    42.                         Byte[] byteArray = objectTemp as Byte[];
    43.                         NetworkReader netReader = new NetworkReader(byteArray);
    44.                         networkState.Deserialize(netReader, this);
    45.  
    46.                         if (networkState != null && !photonView.IsMine)
    47.                         {
    48.                             networkState.smoothSync.addState(networkState.state);
    49.                         }
    50.                     }
    51.                 }
    52.             }
    53.         }
    Let me know how it goes.
     
  18. Fuestrine

    Fuestrine

    Joined:
    Feb 13, 2013
    Posts:
    257
    @the_dunderman
    Nice catch on the elseif issue. Thanks! I'll put it in the next update.

    For the physics interaction between separate owners questions, it's expected behavior. Games that have important physics (like rocket league) will have the physics objects all be owned by the server. The reason PhotonRigidbodyView works for this is because it doesn't work in many other ways, like hitting an unowned object so that it becomes nowhere near where it should be.

    I think you can get SmoothSync to act more like PhotonRigidbodyView though, but it's not a real solution as the hits will be more random than if objects owned by the same machine were to collide. Try turning your InterpolationBackTime down. You may want to turn your SendRate(PhotonNetwork.serilizationRate?) up so you aren't extrapolating too much, but also extrapolation will probably help you collide more. You will get extraplation if you lower your InterpolationBackTime to be less than your SendRate/100.

    My understanding of why separate owner physics isn't good:
    Say you collide a moving sphere (owned by a client) with a stationary cube (owned by the server). The cube is being told to sit still by the server since the the server determines the cube's position. So from the client's view, the sphere is rolling into a brick wall. The sphere never goes into a position that would have it collide with the cube, it just goes to a position that is exactly contacting it, which is nothing like fully rolling into a cube.

    Maybe something to try, but it's probably bad:
    If you take out the AtRest 0 velocity fix I sent earlier, I think it may react more, but that was completely unintentional as the owner is the only one that should be determining the object's position. Maybe try a low MaxPositionDifference and take out the AtRest 0 fix.

    Let me know if that helps or if I was confusing in any of that.
     
    Last edited: Nov 15, 2018 at 10:07 AM
  19. Fuestrine

    Fuestrine

    Joined:
    Feb 13, 2013
    Posts:
    257
    @katasteel
    Oh yeah. I wanted to say what you should do to get a message to the owner of an object.

    So if you have an object on the server that is owned by a client but you want to use the server to tell it to teleport, you'd send a message over on an object that the server owns. Typically a Game Controller or something similar would be server owned and may be useful for something like this. Then, the client receives this message and will tell it's owned object to teleport.
     
    Last edited: Nov 14, 2018 at 8:02 AM
  20. iStolyarov

    iStolyarov

    Joined:
    Oct 29, 2018
    Posts:
    2
    @Fuestrine Hi again, i fix ussue by dettaching Photon Transform View and RigidBodyView and you script at PUN work without any modification, but unfortunatly if players interactions by using RigidBody2D.AddForce() (this action send and recieved similar as just in time, but character bad sync position) or move fast i have some problem:
    1. Sometime player fall in the collider and return if player who control the character jump or do something
    2. The character lags behind
    May be i incorrect setup script or do something wrong, i wait for you responce. I want to sync physics actions in my game.
    My setup for your script:
    upload_2018-11-14_18-48-18.png
     
  21. Fuestrine

    Fuestrine

    Joined:
    Feb 13, 2013
    Posts:
    257
    @iStolyarov
    Can you word this differently? I'm not understanding what you are saying. Any idea on how to recreate the issue so I can see it on my end? I don't see anything in your Smooth Sync settings that is wrong.

    Lower the InterpolationBackTime if you want the object to be less in the past. Right now it is .12s in the past on purpose because of the InterpolationBackTime. Keep in mind that with the default 10 SendRate of Photon, if you put InterpolationBackTime below .1, you will be extrapolating consistently.
     
    Last edited: Nov 14, 2018 at 5:43 PM
  22. Fuestrine

    Fuestrine

    Joined:
    Feb 13, 2013
    Posts:
    257
    Version 3.09 is on the Asset Store.

    Changes:
    -Fixed issue with disconnecting and reconnecting while in the same scene with networked scene objects not registering handlers.
    -Fixed PUN and PUN2 not syncing when there were multiple network observed components.
    -Fix for VelocityDrivenSyncing staying at rest when supposed to.
    -SetPosition() now does rigidbody.MovePosition() if it has a rigidbody and WhereToUpdate is FixedUpdate.
     
    Last edited: Nov 15, 2018 at 8:03 PM