Search Unity

Unity.Physics is overwriting any direct changes to an Entity's Translation

Discussion in 'Physics for ECS' started by Abbrew, Jan 26, 2020.

  1. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    This only happens when a RigidBody Monobehaviour is added to an Entity marked for conversion. I check isKinematic as well as unchecking isGravity so that the Entity would only be moved by scripts, but my System's effects are being overwritten. The only way to fix this is to add [UpdateAfter(typeof(StepPhysicsWorld))] to my Systems writing to Translation, but that decreases performance
     
  2. Adam-Mechtley

    Adam-Mechtley

    Administrator

    Joined:
    Feb 5, 2007
    Posts:
    290
    Hi! You don't actually want to move kinematic bodies by writing directly to their Translation/Rotation. Just as classic Unity requires you to use Rigidbody.MovePosition() and Rigidbody.MoveRotation(), you need to write to the PhysicsVelocity component to enqueue movements before the simulation. Otherwise you are just teleporting the body around and can miss sweep tests.
     
  3. MihaiAilioai

    MihaiAilioai

    Joined:
    Apr 10, 2013
    Posts:
    2
    Howdy, I'd like to chime in as well regarding this issue.

    Classic Unity doesn't "require" you to use Rigidbody.MovePosition() as you can directly set the rigidbody's position via this https://docs.unity3d.com/ScriptReference/Rigidbody-position.html, and sometimes that is exactly what you want, meaning the rigidbody will teleport to the new location ignoring any kind of interpolation or collisions between its old position and new.

    I'm struggling to replicate this behaviour using ECS physics and it seems pretty much impossible at the moment. I can calculate the linear velocity required to get the body from A to B in a single step, but in my case most of the time there's plenty of other rigidbodies along the way and i end up with many unintended collisions which send the involved bodies flying in all directions due to the high velocity of the teleporting object.

    I've also tried setting the collision layer on the teleporting object at runtime to something that doesn't collide with anything else, but the only way i could find was using PhysicsCollider.[BlobAssetReference<Collider> Value].Value.Filter which internally seems to be pointing to the same Collider data for all instances of the same prefab, meaning that if i try to set the layer on my teleporting object it actually sets the same layer on all instances, which as you can imagine is not what i'd want.

    If there's a way to replicate the intended behaviour, which is to teleport an object from A to B without it calculating collisions, i haven't been able to find it and any kind of help would be greatly appreciated.
     
  4. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    You can simply set the values of an Entity's Translation and Rotation Components if you really do wish to teleport a dynamic body, but any Teleport system needs to be careful about when it is ran.

    Unity Physics has 3 main systems
    1. BuildPhysicsWorld (reads ComponentData and converts to Simulation ready format),
    2. StepPhysicsWorld (updates Simulation data) and
    3. ExportPhysicsWorld (writes Simulation data back to ComponentData).

    So, the issue is likely that the ExportPhysicsWorld system is writing back the new dynamic body positions and rotations after your own Teleport system has updated. Therefore, make sure your teleport system is not running between BuildPhysicsWorld and ExportPhysicsWorld, so your changes are not overwritten when ExportPhysicsWorld updates.

    I think you are getting lucky here and your system is probably being ran after ExportPhysicsWorld (check in the entity debugger for the system update order).
    I'm curious about why this is a performance killer though. Are there job dependencies being setup that kills the critical execution path?
     
    florianhanke and PhilSA like this.
  5. MihaiAilioai

    MihaiAilioai

    Joined:
    Apr 10, 2013
    Posts:
    2
    Thank you so much for this clarification. It makes a lot of sense and i wasn't aware of exactly what happened in the BuildPhysicsWorld/ExportPhysicsWorld systems.

    I had tried to set the Translation value, just like the OP, but it wasn't working and it's now clear that it was because once the world is built, any changes to the attached components wouldn't register until the next update but they would be overwritten by the results of the physics simulation since my system was running precisely after BuildPhysicsWorld and before StepPhysicsWorld.

    As for performance, in my particular case i couldn't notice any kind of difference, regardless of at which moment in time my system would run.
     
    Last edited: Apr 22, 2020