Skip to content

Allow CollisionShape nodes to be indirect children of bodies#77937

Open
aaronfranke wants to merge 1 commit intogodotengine:masterfrom
aaronfranke:col-shape-descendant
Open

Allow CollisionShape nodes to be indirect children of bodies#77937
aaronfranke wants to merge 1 commit intogodotengine:masterfrom
aaronfranke:col-shape-descendant

Conversation

@aaronfranke
Copy link
Member

@aaronfranke aaronfranke commented Jun 7, 2023

EDIT: Note that when this PR was first opened there were some caveats, but those have been resolved now. It should now be fully working including supporting when any node in the tree updates its transform, and should be fast.

Implements and closes godotengine/godot-proposals#535

This PR allows CollisionShape2D and CollisionShape3D nodes to be indirect children of bodies (CollisionObject2D and CollisionObject3D). A shape can only be connected to one body.

Screenshot 2023-06-06 at 10 03 24 PM

This is a highly demanded feature, see the discussion in godotengine/godot-proposals#535, #2174, godotengine/godot-proposals#1049, godotengine/godot-proposals#4559, godotengine/godot-proposals#5746 and https://ask.godotengine.org/31701/possible-rigidbody-have-colliders-that-not-direct-children.

Recently, Eoin from Microsoft has convinced me here that this is a vital feature. While I did debate with him about whether that's something worth standardizing... in terms of just whether the feature is good, I agree with him full stop, I don't see any reason to not have this. It just seems like a universally good idea.

The current code has the CollisionShape(2D/3D) looking for the CollisionObject(2D/3D) by running get_parent() and casting it to CollisionObject(2D/3D). So I made this a loop in the case that this cast fails, continue going up the tree until a body is found. All the code in CollisionObject(2D/3D) already works with a cached body reference and notifies it when things about the shape change like the transform.

Production edit: closes godotengine/godot-roadmap#43

@aaronfranke aaronfranke added this to the 4.2 milestone Jun 7, 2023
@aaronfranke aaronfranke requested a review from a team as a code owner June 7, 2023 03:15
@aaronfranke aaronfranke changed the title Allow CollisionShape3D nodes to be indirect children of bodies Allow CollisionShape nodes to be indirect children of bodies Jun 7, 2023
@aaronfranke aaronfranke requested a review from a team as a code owner June 7, 2023 03:23
@aaronfranke aaronfranke force-pushed the col-shape-descendant branch 2 times, most recently from e635433 to e195156 Compare June 7, 2023 03:56
@aaronfranke aaronfranke requested a review from a team as a code owner June 7, 2023 05:31
@fire
Copy link
Member

fire commented Jun 8, 2023

What is the workaround for changing the transform of an intermediate node would not cause the shape to update we can document?

Recreate the node?

@aaronfranke
Copy link
Member Author

aaronfranke commented Jun 8, 2023

@fire Changing the transform and changing it back would work. Or maybe we should expose _update_in_shape_owner? EDIT: I have updated this PR to expose update_in_shape_owner.

@fire
Copy link
Member

fire commented Jun 8, 2023

Can't you use the NOTIFICATION_TRANSFORM_CHANGED?

@aaronfranke
Copy link
Member Author

@fire Checking the global transform would cause it to update when the body moves, which would be every frame for some bodies.

@fire
Copy link
Member

fire commented Aug 31, 2023

Was there a bandaid for changing the transform of an intermediate node would not cause the shape to update? What is the most popular behaviour for this case?

@aaronfranke
Copy link
Member Author

aaronfranke commented Aug 31, 2023

@fire Bandaid is I exposed the update method.

Another option would be to have CollisionShape3D detect when it's not a direct child, and if so, listen for the global transform changed notification in addition to local transform changed.

@aaronfranke aaronfranke force-pushed the col-shape-descendant branch from 6b76f08 to 063656f Compare August 31, 2023 18:01
@aaronfranke aaronfranke force-pushed the col-shape-descendant branch from f5870df to 9f00001 Compare July 3, 2025 23:45
@aaronfranke aaronfranke requested a review from a team July 4, 2025 00:08
@aaronfranke aaronfranke moved this to Ready for review in Asset Pipeline Issue Triage Jul 4, 2025
@fire
Copy link
Member

fire commented Jul 4, 2025

Did the physics team approve this?

@venilark
Copy link

venilark commented Oct 6, 2025

Would this also work for a CharacterBody3D, with colliders inside bone attachments?

edit: also, could a NodePath or a signal be helpful to avoid making the recursive call if they are set up?

@aaronfranke
Copy link
Member Author

@venilark Yes, it will work for shapes in bone attachments.

@venilark
Copy link

venilark commented Oct 7, 2025

@aaronfranke
could I still add an Area3D with different layers just to detect other Area3Ds and that wouldn't interfere with the colliders? or would they be treated as part of the main CharacterBody3D and override their layers and masks?

@aaronfranke
Copy link
Member Author

@venilark The shapes will use whatever CollisionObject3D node is their closest ancestor, so if an Area3D node is a closer ancestor than the CharacterBody3D, then the shape will be a part of the Area3D.

@lyuma
Copy link
Contributor

lyuma commented Nov 14, 2025

I think the change is looking much better, and I think most of the performance issues from our original changes have been largely mitigated.

@fire Since you quoted my old comment, Aaron added some mitigations to cache the shape in the owner during PARENTED and preserve the existing state in ENTER_TREE, which is good.

The one thing that is still possibly an issue is that this change is removing the shape from owner in EXIT_TREE, which will trigger during reparent. I understand that this might be necessary for indirect children, but for direct child, I think we should skip the EXIT_TREE logic and perform the remove_shape_from_owner in UNPARENTED, since that is guaranteed to be called for the direct child case

Regarding reduz's comment, the cache should largely reduce the performance impact of the moving nodes. Furthermore, another mitigation was added to subscribe to local transform for direct children and only use NOTIFICATION_TRANSFORM_CHANGE for indirect children, so it is much safer than before, and I think we have done the best we can do for addressing reduz's feedback.

I think overall other than my concern about the direct child case for EXIT_TREE, I'm pretty happy with this and I think most of the performance impact has been mitigated. What can we do to get the necessary reviews in place and unblock this PR?

@venilark
Copy link

venilark commented Dec 4, 2025

Feature freeze for 4.6 is around the corner, is there still a chance this will be implemented soon now the performance issues have been resolved?

@mikest
Copy link
Contributor

mikest commented Jan 20, 2026

Sigh. I started working on this, and forgot to check if there is a PR outstanding.

Anything I can do to help move this one along?

@akien-mga
Copy link
Member

Anything I can do to help move this one along?

You can help test and review the implementation to confirm that it's the best implementation we can get.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Ready for review

Development

Successfully merging this pull request may close these issues.

Allow physics bodies to have shapes that are indirect children, not just direct children