Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Physics.SyncTransforms() questions

Discussion in 'Physics Previews' started by PhilSA, Aug 9, 2017.

  1. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    So I have a few questions regarding this feature:
    1. When autoSync is turned on, does the system actually force everything to sync positions/rotations every time, or does it have some kind of optimized way of only moving the rigidbodies that are "dirty"? If so, how expensive is the "dirty" check (in other words; how great are the potential performance gains of doing it manually if we weren't moving rigidbodies by using transforms anyway?)
    2. A sync is only needed when a transform with an attached Rigidbody/Collider was moved directly; not when a Rigidbody was moved directly with .position, .MovePosition, .velocity, or through physics forces/impacts. Correct?
    3. Right now, a MovePosition() is only really applied after the FixedUpdate phase. Does calling SyncTransforms apply it instantly or affects it in any way?
    4. If moving a Rigidbody with rigidbody.position or MovePosition, and autoSync is turned off, does it automatically do all the sync work for child Rigidbodies/Colliders, or do we have to call SyncTransforms manually to sync children?
    5. Will turning off autoSync cause any sort of unexpected behaviour with rigidbody interpolation? (does interpolation rely on changing the transform's position internally and not the rigidbody's?)
    Basically, with all this, I am trying to figure out if I really need more than one single sync per fixedUpdate. I already make sure all of my rigidbodies are moved through rigidbody methods, and none of my vanilla colliders are moved at all (if they are moved, I'll make them kinematic rigidbodies). So from what I understand, one sync would be enough (?)

    thanks!
     
    Last edited: Aug 10, 2017
  2. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    596
    Hey Phil

    I wrote up the attached doc for the alpha groups, not sure it actually made it's way down to betas.

    The basic idea of a sync is to take the changed transforms that physics is interested in and apply the changes to the physics engine, one by one at no particular order (happens partially in jobs running on other threads). Priorly, we used to have a TransformChanged(changeType) message that was sent to the physics components as explained in the attached pdf. One way to think about the new deferred updates is to imagine all the TransformChanged messages are now deferred and squashed (=two TransformChanged to a given transform turn in to only one update).

    1. As pointed out above, only the changed transforms are getting written to the physics engine. There is no "dirty" check per se, once you write a transform, there is a bit set in the hierarchy if the transform had the physics engine interest expressed. It's a core feature, and it's also used in AI, Particles, 2D Physics, etc. I believe the main cost of it as of right now is during the collection of the changed transforms from the hierarchy. This is jobified and runs pretty fast, but I'm guessing there would be projects where that is a bottleneck of some kind. We'll see. So far, I've only seen syncing transforms taking up 0.1-0.5ms in large setups. Will keep tracking what devs have to say about this. There is some potential in speeding this all up if required.

    2. Yes, the Sync is required only when something physics-related was altered with the means of a Transform class. Please note that we always sync prior to simulating the physics frame. "autoSync" only affects the optional sync points that happen before physics queries and alike.

    3. It's a good question really. Transforms are always synced before running the simulation, and MovePosition is processed afterwards. That means, MovePosition has a potential to overwrite the sync'ed pose. However, MovePosition isn't really relative to the current pose so unless you set different poses in Transform and MovePosition, there is no way to notice the difference other than wasted cycles doing competitive updates.

    4. It's important to remember that Physics.SyncTransforms is only to flush the Transform changes to physics, not vice versa. That said, it won't help with Rigidbody.position / Rigidbody.MovePosition. Also, I don't think all the body types respected the sub-space logics all the time (and there were probably cases that are no longer supported anymore after the deferred sync landed). Basically, a dynamic body will never simulate in parent's space. After you start the scene, the parent-child connection is much more logical than actually physical. However, a kinematic body does inherit the parent's transform and will be moved after any of the parents moved. This doesn't need sync.

    5. I don't think so, believe interpolation should work as before -- please let me know otherwise.

    Yes, sounds like you will do with the sync that happens internally right after FixedUpdate goes to scripts.

    Hope that helps.

    Anthony

    EDIT: Here is a link to the pdf doc from the alpha groups: https://oc.unity3d.com/index.php/s/snrKobHiS1ZQjGj
     
  3. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    Just for clarification.
    The compatibility mode that is ran by default. Is that when autoSync is false?. So if you have autoSync to false, it syncs the transforms before a raycast. But if you have it to true, it flushes everytime you move something?

    To me, it sounds like there is 3 modes in the document.
    Compat: Flush before FixedUpdate & before Raycast.
    Off: Flush before FixedUpdate
    On: Flush When Something moves.
     
  4. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    596
    Sorry if I wasn't clear before. There are only two modes.

    1. autoSync = true (default): transform changes are applied before sim and at the "automatic" sync points (read the linked pdf -- physics query, camera flares sim, particles with collision module, etc)

    2. autoSync = false: transform changes are applied only before sim (once per the physics frame).
     
    TwoTen likes this.
  5. TwoTen

    TwoTen

    Joined:
    May 25, 2016
    Posts:
    1,168
    Thanks!
    This is a super useful feature for Multiplayer Lag Compensation where we have to roll back time to do Raycasts etc and then roll it back agian all within a frame.

    Great job. And thanks for the clarification
     
  6. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Not sure if I've hit a bug or just don't understand the feature. I couldn't find any information really on does this relate to objects moved via forces.

    2017.3 latest patch update, I have a physics object that is only affected by AddForceAtPosition, and it behaves completely different with auto sync disabled. The code is actually the open source buoyancy script, I disabled auto sync and the first thing that went wrong is all my ships sunk about 500 units then shot up in the sky. Isolated it into a fresh scene with just a cube, rigidbody,and script same result. So obviously forces come into play somehow.

    After that, I added Physics.SyncTransforms() calls to before/after every position read, and before/after the force calls. No effect.
     
  7. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    596
    Hey Snacktime,

    Yes, that's true. AddForceAtPosition depends on the current position of a body, thus behaves differently on whether SyncTransforms was called or not. There was also a bug I fixed recently where an automatic sync point wasn't set in the relative AddForce functions.

    Anthony
     
  8. Atrixx

    Atrixx

    Joined:
    Feb 8, 2012
    Posts:
    24
    Heads up! I found a potential issue when autoSync is turned off - setting transform.localScale while using Rigidbody2D.MovePosition in the same frame causes the object to freeze. This suggests that its not only transform.position / transform.rotation which need manual syncing, but editing the transform component at all overrides physics changes.

    Setting transform.localScale in Update, and then using MovePosition in FixedUpdate works - however breaks interpolation and smooth movement.

    Is this consistent with your findings?
     
  9. herb_nice

    herb_nice

    Joined:
    May 4, 2017
    Posts:
    170
    I've just done some testing on my project, which does do some updating of transforms that have colliders on them (due to 2d hinge joints not behaving wonderfully- when i push on a collider on a hinged rigidbody it behaves like a spring and can be separated from it's anchor and pushed across the world, which is nonsense, none of the hinges in my home do that)

    anyway, here are the results on my project, maybe they will help someone:


    with the fancy new manual sync transforms implemented like this:

    Physics2D.autoSyncTransforms = false;
    Physics2D.autoSimulation = false;
    ...
    //update physics once per-render-frame via Update:
    Physics2D.SyncTransforms();
    Physics2D.Simulate(physicsDeltaTime);

    PC: 2017.3.1f1, .net 3.5, mono, 2 minute soak, 122fps average.
    PC: 2017.3.1f1 .net 4.6, mono, 2 minute soak, 118fps average
    PC: 2017.3.1f1, .net 4.6, mono, 2 minute soak, 131fps average

    Android 2017.3.1f1, .net 3.5, il2cpp, 28 minute soak, 14fps average
    Android 2017.3.1f1 .net 4.6, il2cpp, 28 minute soak, 15fps average


    old way:

    Physics2D.autoSimulation = false;
    ...
    //update once per-render-frame via Update:
    Physics2D.Simulate(physicsDeltaTime);

    PC: 2017.1.1f1, .net 3.5, mono, 2 minute soak, 172 fps average
    PC: 2017.1.1f1, .net 4.6, mono, 2 minute soak, 120 fps average
    PC: 2017.1.1f1, .net 4.6, mono, 2 minute soak, 115 fps average

    Android 2017.1.1f1, .net 3.5, il2cpp, 28 minute soak, 20fps average
    Android 2017.1.1f1, .net 4.6, il2cpp, 28 minute soak, 19fps average


    Android took a significant performance hit with 2017.3.1f1. back to 2017.1.1f1 for us.
     
    Last edited: Mar 8, 2018
  10. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Why duplicate tests?
    and:
    Typo?

    Also I don't see why changing net, IL2CPP etc has any bearing on the unity engine code which is completely separate. This is a seriously flawed set of tests.
     
  11. herb_nice

    herb_nice

    Joined:
    May 4, 2017
    Posts:
    170
    * our SyncTransforms
    because those ones were quick, to get an idea of the variance of data. tests were run in multiple configurations to benchmark those differences as well. not labcoat, but back of envelope.

    to be fair, unity's profiler indicates that we may be spending almost 50% less time syncing transforms in some nasty situations with the new method on android. but whateverthehellallelse is new in 3.1f1 makes our android project go much slower.
     
  12. paradizIsCool

    paradizIsCool

    Joined:
    Jul 10, 2014
    Posts:
    178
    @hippocoder @yant
    Just to be really clear,
    "When set to false, synchronization only occurs prior to the physics simulation step during the Fixed Update."
    If autosimulation is set to false, do we need to call Physics2D.SyncTransforms(); like @herb_nice did in his post or not?

    autoSyncTransforms just change the sync method but did not disable sync, but it's done during FixedUpdate, and autosimulation change the way the physics works, FixedUpdate still called but not for Physics.
     
    afshin_a_1 likes this.
  13. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,363
    I'm seeing character controller being pushed by kinematic rigid colliders on navagents through the terrain collider with autosync off
    Why is this and how to remedy?
     
  14. JiawenYu

    JiawenYu

    Joined:
    Dec 25, 2019
    Posts:
    3
    where can i get the pdf doc? the previous link isn't working any more.
    thanks
     
  15. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    596
    A lot has changed since then, and I'm afraid the doc is no longer available indeed. Do you have any particular questions?
     
  16. JiawenYu

    JiawenYu

    Joined:
    Dec 25, 2019
    Posts:
    3
    thanks for your reply. No, just want to learn more about this subject. If there is any summary about this, it will help a lot.
     
    Last edited: Aug 19, 2021
    RaoulWB and iileychen like this.
  17. iileychen

    iileychen

    Joined:
    Oct 13, 2015
    Posts:
    110
    For my understanding, SyncTransforms is needed only when moving rigidbody without the method of rigidbody, for example move the Transform directly. But I'm not sure, hope there will be a summary about this too, help a lot.
     
  18. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    481
    Does setting Rigidbody.position/rotation immediately updates the physics engine state? Or we are obligated to call SyncTransforms?

    In my case, I want to test with Physics.OverlapBox that moved objects do not overlap. If they overlap then revert position change. And I'm trying to do this in one frame, without spreading logic across several FixedUpdates
     
  19. Wilhelm_LAS

    Wilhelm_LAS

    Joined:
    Aug 18, 2020
    Posts:
    55
    For future whose missed that part
     
  20. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    596
    Rigidbody.position / Rigidbody.rotation writes directly to the physics engine.
     
    Wilhelm_LAS likes this.
  21. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    481
    Thanks for clarifying this!

    Does this mean that every Physics.XXX() methods like Raycast, BoxCast, SphereOverlap etc will use new values right after Rigidbody.position/Rigidbody.rotation are set by a script?

    What about changing Collider parameters? For example, changing center and radius of a SphereCollider
     
    Wilhelm_LAS likes this.
  22. yant

    yant

    Unity Technologies

    Joined:
    Jul 24, 2013
    Posts:
    596
    Generally speaking, we only have that delayed application logic with transform values.

    As been said before, many years ago, code used to have a callback OnTransformChanged that was executed each time when a transform was changed for any reason. That didn't scale very well, so instead of that, over time, we transitioned to the transform dispatch paradigm.

    With transform dispatch, when one changes the transform values, nothing immediately learns about that fact. It's only when the time for update for that system comes, it asks for the set of transforms that were changed (beforehands the system needs to tell what transforms it is interested in -- it's not a blanket notification with huge arrays of all transforms in a scene).

    Now, transform dispatch is only for transform properties. It is not used for Rigidbody.position/rotation, neither it is used for Collider properties. All of those are directly write through to physx. Queries should be able to pick things up immediately there.

    Hope that is a useful perspective. Anthony.
     
    Wilhelm_LAS and MUGIK like this.