Detecting a "child" collider and moving it

(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.

5146583--509585--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? :slight_smile:

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

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.

5146595--509591--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:

5146595--509588--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 :frowning: I spent the whole day messing with this. … but it works! Now I “just” need to implement the slider.

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).