Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Detecting a "child" collider and moving it

Discussion in 'Physics for ECS' started by Nothke, Nov 6, 2019.

  1. Nothke

    Nothke

    Joined:
    Dec 2, 2012
    Posts:
    112
    (I've accidentally put this in the Physics Previews forum instead of DOTS Physics)

    So, I'm trying to implement slider interaction on a collider parented to a rigidbody.

    Basically, (in classic physics thinking) I cast a ray, detect a child collider and move it by some mouse offset.

    Now, it was easy in GameObject-physics because objects kept parent-child relationships. However, in Unity Physics, as far I understand, during the conversion process, everything gets detached and child colliders become a part of a PhysicsCollider of the root rigidbody, while the graphical part hangs around in separate entities. So, there is no way to keep the relationship with standard authoring components.

    I managed to hack this by first adding a Body Authoring to the slider, it makes sure that the collider doesn't become part of the root during conversion. Then I add a FauxParent component to the child that stores the parent Entity during the conversion process. Then I override the position and rotation in relation to the FauxParent's Local2World. So the entities are completely separate but the slider "snaps" to the parent. Of course, the parent body and slider colliding-layers never interract (and shouldn't). Then, I also remove PhysicsVelocity so that the rigidbody doesn't get updated. It works, but it's a crazy workaround.

    sliderp2.gif

    (in the preview it's just moving to one side because I just add x++ on racast hit for testing :p, but it should eventually work like a slider, but not important right now)

    What I really want is actually just to detect collision to the slider, without any physics, no bodies, the root body shouldn't change center of mass and stuff like that and the sliders are not going to interact with anything else except the mouse. BUT I want to still have the nice authoring component where I can design the slider collider. I just don't want the collider to become part of root body entity automatically. What about some "don't become part of root rigidbody" tickbox in physics shape? :)

    Or am I getting it wrong and there is a nicer way to do this?
     
  2. Nothke

    Nothke

    Joined:
    Dec 2, 2012
    Posts:
    112
    Ok, here's what I did, I used a similar hack as I mentioned, except I separated the "visual" and the "physical" slider. Another problem that I noticed that is very important to solve is that the slider will drift if the body is at a velocity, and that is because I'm applying the world transform before the transform system updates.

    Unity_2019-11-06_19-32-14.png

    I fixed this by having a visual slider separate from collider, I put them both under the same root. The thing is that since the visual slider has a Parent and LocalToParent (because it is not automatically unparented by the Body Authoring), I can modify its Position and Rotation and it will be correctly calculated to parent during the Transform System update. While the physical slider is now outside of the hierarchy and changing its Position and Rotation changes its world position.

    BUT there's 2 more things to consider, when do you raycast, and when do you apply the camera position (considering the camera follows the parent body). I had to move the raycast post-ExportPhysicsWorld so that the applied physical-slider position is at a correct position. And I had to make the camera update after the RenderMesh system, so that it also doesn't lag behind the graphics.

    So, here is the drifting problem solved:

    fallingsphere2.gif

    So, you can see the Big white sphere is the parent rigidbody. It is falling down at a high speed. The yellow cube is the graphical slider. The little white sphere that is drifting upwards is the physical slider, it is drifting because I manually apply its transform to match the slider root transform, which then the physics system "sees" but the render mesh system doesn't see. The yellow lines show that I am correctly casting the ray into the physical slider, but they are also drifting behind because Debug.DrawRay naturally lags behind one frame.

    So, here's the rundown of the systems:

    # UPDATE
    = SimulationSystemGroup
    > SinMoveSliderTestSystem - updates the slider value by sin(time) just for testing
    > SliderUpdateTransformSystem - [on PhysicalSlider] match the Translation and Rotation (world) to Slider root's LocalToWorld (via CDFE)
    >> BuildPhysicsWorld
    >> ExportPhysicsWorld
    > SliderUpdateGraphicsSystem - [on VisualSlider] take the slider value (via CDFE) and update the visual slider Translation and Rotation (local).
    > RaycasterSystem - raycast into world from camera position and detect PhysicalSliders (via CDFE). CombineDependency with ExportPhysicsWorld.FinalJobHandle
    >> TransformSystemGroup
    # PRE LATE UPDATE
    = PresentationSystemGroup
    ^ CameraFollowEntitySystem - match the camera position

    It's a mess, and I'm almost at the point of "I have no idea how this works, but it does" and I'm almost afraid to change anything at this point :( I spent the whole day messing with this. ... but it works! Now I "just" need to implement the slider.
     
  3. Rory_Havok

    Rory_Havok

    Joined:
    Jun 25, 2018
    Posts:
    70
    Just a note, maybe it will just add more questions :)

    You are running the RaycasterSystem after ExportPhysicsWorld. But the collision world that raycasting uses is actually untouched after BuildPhysicsWorld - simulation does not modify the collision world. (That can be opted into using SimulationStepInput.SynchronizeCollisionWorld).