Skip to content

Allow CollisionShape nodes to be indirect children of bodies#77937

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

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

Conversation

@aaronfranke

@aaronfranke aaronfranke commented Jun 7, 2023

Copy link
Copy Markdown
Member

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
Comment thread scene/3d/collision_shape_3d.cpp Outdated
Comment thread scene/3d/collision_shape_3d.cpp Outdated
Comment thread scene/2d/collision_shape_2d.cpp Outdated
Comment thread scene/2d/collision_shape_2d.cpp Outdated
Comment thread scene/3d/collision_shape_3d.cpp Outdated
@fire

fire commented Jun 8, 2023

Copy link
Copy Markdown
Member

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

aaronfranke commented Jun 8, 2023

Copy link
Copy Markdown
Member Author

@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

fire commented Jun 8, 2023

Copy link
Copy Markdown
Member

Can't you use the NOTIFICATION_TRANSFORM_CHANGED?

@aaronfranke

Copy link
Copy Markdown
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

fire commented Aug 31, 2023

Copy link
Copy Markdown
Member

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

aaronfranke commented Aug 31, 2023

Copy link
Copy Markdown
Member Author

@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
@venilark

venilark commented Oct 6, 2025

Copy link
Copy Markdown

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
Copy Markdown
Member Author

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

@venilark

venilark commented Oct 7, 2025

Copy link
Copy Markdown

@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
Copy Markdown
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.

Comment thread scene/2d/physics/collision_shape_2d.cpp Outdated
@lyuma

lyuma commented Nov 14, 2025

Copy link
Copy Markdown
Contributor

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

venilark commented Dec 4, 2025

Copy link
Copy Markdown

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

mikest commented Jan 20, 2026

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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.

@aaronfranke aaronfranke force-pushed the col-shape-descendant branch from 3bc8705 to 4cb5741 Compare March 5, 2026 08:28
@aaronfranke aaronfranke force-pushed the col-shape-descendant branch from 4cb5741 to a45da53 Compare March 30, 2026 04:38
@aaronfranke aaronfranke force-pushed the col-shape-descendant branch from a45da53 to 52c849c Compare May 7, 2026 03:25
@funkysandwich

funkysandwich commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

This PR has been extremely useful for me when working with inherited CollisionObject3D scenes.
Using my draft PR #106048 with this, It's possible to import models with collisionshapes only, and reuse them by instancing the imported scenes under different collision body types.
image
It also helps keep the hierarchy much more organized visually where some models may have a ton of collisionshapes.

I really hope that this PR will be merged.

@aaronfranke aaronfranke force-pushed the col-shape-descendant branch from 52c849c to 2d04b02 Compare June 14, 2026 02:05
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