Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CollisionShape does not update moving AnimatableBody3D? #67257

Open
stesproject opened this issue Oct 11, 2022 · 13 comments
Open

CollisionShape does not update moving AnimatableBody3D? #67257

stesproject opened this issue Oct 11, 2022 · 13 comments

Comments

@stesproject
Copy link

Godot version

4.0.beta2

System information

Windows 11

Issue description

I created a moving platform composed this way:
image
The Playback Process Mode of the Animation Player is set to "Physics", though it looks like the CollisionShape doesn't follow its parent, the AnimatableBody3D.

Test.DEBUG.2022-10-11.15-39-12.mp4

Steps to reproduce

I attached the project.
Just open it with Godot 4 and run pressing F5.
Try to walk above the moving platform.

Minimal reproduction project

Test.zip

@rburing
Copy link
Member

rburing commented Oct 11, 2022

The workaround is to compose your moving platform like this:

sync_to_physics

and make the RemoteTransform3D node push its transform directly to the AnimatableBody3D.

This is because the AnimatableBody3D with the sync_to_physics = true only reacts to changes of the local transform:

case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {

which explains why your other node composition didn't work.

This should be either properly documented or fixed.

@stesproject
Copy link
Author

The workaround is to compose your moving platform like this:

sync_to_physics

and make the RemoteTransform3D node push its transform directly to the AnimatableBody3D.

This is because the AnimatableBody3D with the sync_to_physics = true only reacts to changes of the local transform:

case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {

which explains why your other node composition didn't work.

This should be either properly documented or fixed.

Thank you!
With the new structure it works! 🥳

@rburing
Copy link
Member

rburing commented Oct 11, 2022

You're welcome for the workaround. This still needs to be documented or fixed, so let's keep this open until that's done :)

@rburing rburing reopened this Oct 11, 2022
@Calinou Calinou added this to the 4.0 milestone Oct 12, 2022
@YuriSizov YuriSizov modified the milestones: 4.0, 4.x Feb 27, 2023
@GNSS-Stylist
Copy link
Contributor

AnimatableBody3D and CharacterBody3D seem to work differently in this regard:

2023-04-01.01-00-10.mp4

In this video green plate is CharacterBody, red AnimatableBody. Transparent red MeshInstance shows the original position of the AnimatableBody.

AnimatableBody (or collision shape of it?) stays on it's original position as said in this thread, but CharacterBody follows the rotation of the parent (AnimatableBody and CharacterBody are siblings and childs of a common rotating Node3D here). So isn't this more like a bug in implementation than documentation?

MRP (used in the video above):
AnimatableBody3DTransformBug.zip

Godot version: v4.1.dev.custom_build [c29866d] (identical in 4.0.1 stable)

@rburing
Copy link
Member

rburing commented Apr 1, 2023

@GNSS-Stylist As I wrote above, AnimatableBody3D only reacts to changes of the local transform. In your scene you are rotating the Rotator node which is the parent of the AnimatableBody3D, so the local transform of the AnimatableBody3D does not change, so you are not using the node in the intended way.

If you rotate the AnimatableBody3D directly then your scene works as expected.

So this needs to be documented.

Edit: Or animatable bodies should use the NOTIFICATION_TRANSFORM_CHANGED notification instead, if that works.

Edit 2: Briefly tried that (also using set_notify_transform), but what I tried didn't work.

@GNSS-Stylist
Copy link
Contributor

@rburing I understand how it currently works. But it feels kinda weird that AnimatableBody3D works differently than for example CharacterBody3D (or especially RigidBody3D, see later), IMHO.

Made some tests and tried if just "touching" (overwriting the local transform with itself, in this case by $Rotator/AnimatableBody3D.transform = $Rotator/AnimatableBody3D.transform) fixes the issue and it looks like it does. And modifying the local transform also does the trick (as already said). But if the local transform is modified (or "touched") only occasionally, it leads to "teleporting". Also it seems that StaticBody3D reacts to changes in it's parents' transforms (checked this as it is the base class for AnimatableBody3D).

Video:

2023-04-02.20-29-33.mp4

Green plate is CharacterBody3D, red AnimatableBody3D and blue StaticBody3D. Transparent red MeshInstance shows the original position of the AnimatableBody.

Modified "MRP":
AnimatableBody3DTransformBug_V2.zip

Doesn't the current behavior lead to strange issues if AnimatableBody3D is used in vehicles etc?

That said, now after reading the documentation about StaticBody3D and AnimatableBody3D more thoroughly I don't quite get their difference. Although documentation for AnimatableBody3D says "When the body is moved manually, either from code or from an AnimationPlayer (with AnimationPlayer.playback_process_mode set to physics), the physics will automatically compute an estimate of their linear and angular velocity." it looks like it just teleports. So maybe it's just documentation issue after all.

@Mineorbit
Copy link

Mineorbit commented Apr 14, 2023

Hey,
i dont have any knowledge of the engine internals, but may this issue be related to #75894?

@nanodeath
Copy link
Contributor

Still present in 4.2.1.

So, this was kinda alluded to earlier, but simply setting sync_to_physics=false also seems like a valid alternative to adding RemoteTransform3D. I think it'll work for me, and I have a similar node hierarchy (but with a script-based "motor" instead of an AnimationPlayer).

@eliaskowitz
Copy link

I'm assuming its related but I've also noticed that with the node setup that rburing suggested and having sync_to_physics set to true, this causes the moving_platform not to move if get_tree().paused = true even if the moving_platforms's process_mode is set to always

@jbromberg
Copy link

This was very confusing to me and I thought there were bugs in my implementation. Is the intended design that global transforms are ignored when sync_to_physics is true? What's the reason behind that choice if so? Seems like it would be feasible to still respect parent transforms while syncing movement to physics. As a side note, I've noticed that this works as expected if the parent's initial transform is set to identity and then is later on manipulated.

@Kaio20
Copy link

Kaio20 commented May 13, 2024

When setting up a AnimatableBody2D with a CollisionShape2D this can also happen. In one instance when I animated the AnimatableBody2D and not the default Node 2D it works with "Sync to Physics" but when I duplicated the moving 2D Platform and animated the parent 2D Node it didnt work anymore. I do not understand the reason behind it to only respect the local transform. So this problem persists in 4.2.2 and in 2D.
EDIT: here is a video showing the problem in further detail for 2D and a "solution" that seems rather tacked on to me.

@superlou
Copy link

superlou commented May 17, 2024

The RemoteTransform approach seems workable for scenes where there is only one AnimatableBody that must move relative to another node (the PathFollow3D in the original issue), but in a scene where a moving platform is composed of many AnimatableBodies, is there a recommended way to apply this? For example, something like:

  • Player (CharacterBody3D)
  • TrainCar1 (AnimatableBody3D)
    • Door1 (AnimatableBody3D)
    • Door2 (AnimatableBody3D)
    • Bench1 (StaticBody3D)
    • Bench2 (StaticBody3D)

The player moves with the train car because of the physics engine matching their velocity to the floor. TrainCar1 is moved with a script in _physics_process(). The animatable and static bodies, however, have collision objects that don't move relative to TrainCar1 and cause weird behavior. Manually moving the collision objects seems very tedious and noisy to set up with nodes.

I guess this is a long way of me asking if the original posted issue be treated more like a bug than expected behavior?

@azur-wolve
Copy link

azur-wolve commented Oct 2, 2024

then if understood correctly, the solution is
AnimatableBody3D.sync_to_physics = false

(and just call any movement, applied to its local transform, from a _physics_process() to keep it sync to physics ticks)

The thing here is that AnimatableBody3D seems to have been designed to be moved by an AnimationPlayer node.

But what people really expects from it to be is just "a StaticBody3D that is optimized to being moved and not affected by other bodies".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Todo
Development

No branches or pull requests