Move (Dynamic) Non-Kinematic Rigidbody by setting transform.position

Howdy,

I have a following situation. I have an object (eg. cube) moving vertically up at constant speed using:

transform.localPosition = Vector3.MoveTowards(..)

The cube has a rigidbody that is set to non-kinematic with position x, y and z frozen. I move the parent of the rigidbody using the code above. When I fire at the cube with projectiles (as it is moving vertically at a constant speed) it has a cool effect of spinning about its own axis because of the force of projectiles on it. Because the rigidbody is non-kinematic I should not be moving it using the transform but should be using force, but this is not a viable option. Does anyone know how bad moving a non-kinematic rigidbody with transform is? Docs just say that you shouldn’t do it, but it doesn’t say why? Is it a technical reason or just in most cases the behaviour that will be observed is not physics accurate and that’s the reason?

Not sure if it matters for your application but usually moving a rigid body without using force will neglect collisions if there are obstacles in its path when moving it from point A to B. Another issue from my experience is that the velocity also will not update to reflect the change in position. You could probably use the ForceMode parameter with the AddForce() method to achieve what you want but I found that the default ForceMode in my experience behaves stably in the long run. In my case, I would use a PID controller to achieve constant speed.

About MoveTowards(), I never tried it but I’m guessing it operates similarly to MovePosition() except it is for transforms. Even so, you are modifying the properties on the transform rather than the rigid body so it will possibly end up clipping through colliding objects as I have said before.

Modifying the transform of a rigidbody (either kinematic or not) instantly “teleports” it to the new location. There’s no difference if you move it 1 mm or 50 m, the result is an instant teleport.

Some side consequences are:

  • Bypasses any collision detection, friction effect, or effects to/from other bodies. The object might be instantly teleported directly inside another collider.
  • The calculations of the physics solver are overridden. The physics engine calculates a physically correct new position, but this is discarded so the object is just teleported to the specified position.
  • When the physics engine runs the next step, it has to resolve whatever situation the body is in now. For example, now it might be well penetrating another object, so the physics engine will calculate and report collisions, and try to separate them.
  • Messes up the visual interpolation, if enabled in the rigidbody. The physics engine had calculated a new position so the body is being visually interpolated towards that position, so setting a different position causes visual glitches.

As rule of thumb, the methods for moving rigidbodies that are optimal and don’t cause side effects are:

Notes:

  • All these must be called from FixedUpdate.
  • Never use Time.deltaTime or Time.fixedDeltaTime in the calculations of values to be passed to AddForce* / AddTorque* methods.

Of course, there are legit reasons for modifying the transform of a rigidbody. For example, respawn the object in a different position. But using for actually moving an object each step is not a good idea as per the consequences above.

5 Likes

Thank You for the suggestions and information. I’ve came up with another way of achieving the effect I need without violating documentation and the rules you mention. Here is a short video of the effect I’m talking out.

9b925w

I have now a Kinematic rigidbody (barrel) which I move using MovePosition vertically. It is hard to tell on the video but it is moving vertically slowly. To achieve an effect of it getting hit with projectiles and spinning in place I’ve created a duplicate barrel off camera. This “barrel” is collider and rigidbody only and is Non-Kinematic (is Dynamic). When the visible barrel gets hit I take the impulse collision data and convert it to a force and apply it to the off screen barrel (the Non-Kinematic dynamic one). Then I simply set the visible barrel rotation using MoveRotation to the same rotation as the barrel that is offscreen. So I’m using the offscreen one as a rotation force data source.

I know that if there are many objects this strategy is not viable since you’ll need many duplicates, but in my case since I only have one at a time this woks just fine. Let me know what you think.

So you know, non-Kinematic could mean Static or Dynamic. If you mean the “IsKinematic” is not checked, then it’s Dynamic.

Hello, thanks for chiming in. Yes I do mean, IsKinematic is not checked, there is a rigidbody and static flag is off. From my understanding Static would imply that there is no rigidbody on it, just a collider with static flag checked on the GameObject. So I figured by specifying that Rigidbodies are involved that would imply that it is Dynamic. I don’t think there is a case where you can have a static flag on Rigidbody? If there is please correct me. I’ll edit the title to explicitly say dynamic.

That is nothing to do with physics, that’s a rendering thing.

in 3D physics, a Rigidbody is Dynamic by default (collision response etc). If you check the “IsKinematic”, it’s Kinematic. Unfortunatley a Static Rigidbody isn’t exposed but it’s implicitly Static (the colliders) if there is no Rigidbody.

For example, in 2D you can explicitly select which of the three body types: https://docs.unity3d.com/Manual/class-Rigidbody2D.html

No worried about the title, it was just a FYI. :slight_smile:

2 Likes

I see. Thank you for clarification, much appreciate your time. For some reason I associated static check box on GameObject flag with physics. Looking over documentation there is nothing that suggests so, my bad. Thanks for pointing that out. Just so I’m understanding this correctly, a lone collider can be looked at as having a default “hidden” rigidbody and being Static. If a rigidbody is added to the GameObject where the collider resides or to a parent GameObject then the collider rigidbody becomes Dynamic if “IsKinematic” is also turned off on that added rigidbody. So it’s as though the added dynamic (in this case) rigidbody overrides the static “hidden” one on the collider. It is unfortunate that this is not visible in the editor and is implied, but I can see the problem with exposing it and having static/dynamic designations change on the fly as rigidbodies are added/deleted. If I’m still off, feel free to point it out. Regards…

Yes and this is actually true, just not a Rigidbody(2D). It’s known as the ground body and lives at the world origin with no rotation.

Yes. By default, it’s Dynamic. It’s Kinematic when that is checked. Note that colliders themselves are not actually Static, Kinematic or Dynamic: the body determines that. Colliders are like joints in that they are attached to a body and the body moves (or doesn’t).

It is in 2D as I linked above. In 2D if you don’t add a Rigidbody2D then the Colliders are attached to the Static Ground body just like 3D physics. In 2D however you can also add a Rigidbody2D and set it to Static.

1 Like

Much appreciate your time. Thank You for the information, it’s tattooed on my brain now.

1 Like