godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.54k stars 20.66k forks source link

Objects can't use forces while global_transform.basis is being changed #26382

Open Ace-Dragon opened 5 years ago

Ace-Dragon commented 5 years ago

Godot version: Godot 3.1 Beta 8 official

OS/device including version: Windows 10 64 bit (April update); Ryzen7 2700X CPU; GTX 1060 6GB GPU

Issue description: In Beta 3 and before, you can move an object with forces while changing its _globaltransform.basis property (using functions like slerp()). Now, you can't do that on the same frame, any object movement with forces will stop immediately, even though we're not changing the object's position.

Steps to reproduce: Run the project and watch the cube stop as soon as it starts spinning. The position shouldn't see an override because it's only changing the orientation.

Minimal reproduction project: Test Project2.zip

akien-mga commented 4 years ago

I'm not sure to fully understand what the bug should look like, but it seems to behave OK in the current master branch? On the other hand it raises a lot of errors, but I don't know if they're due to the project's code or an engine issue.

tom-jk commented 4 years ago

Can reproduce issue as described in 3.2.2.stable.

Video (length 0m14s): https://youtu.be/AomtL1_obTI

to silence the errors add an orthonormalized() to line 15:

global_transform.basis = global_transform.basis.slerp(ahead.global_transform.basis.orthonormalized(),0.25)
Zylann commented 3 years ago

Keep in mind that in GDScript, when you assign global_transform.basis, it actually assigns global_transform as a whole, so technically the engine might see it as both rotation and translation could have changed. It's unclear wether the engine makes a difference.

Also, I think the transform you see on Spatial is off by a frame or two for rigidbodies, because it is updated after simulation. It is not the direct one because it is controlled by the physics engine instead. The engine uses its own transform, and updates the node one only at specific times. So when you assign Spatial.global_transform you might accidentally tell the physics engine to force teleport the body back to the transform it had after the previous physics-to-node update.

On the other hand, the transform you would get in _integrate_forces (direct body state) is the one on which you could apply these changes directly.

So adding forces and also setting the global_transform property seems a bit contradictory, at least in the current design. Controlling rigidbodies in general should not involve this, except maybe for teleporting.