Unexpected behavior when freeing collision bodies from CharacterBody3D

Godot Version

4.2.1

Question

So for some context, I’ve been trying to create enemies made of voxels, where each voxel has its own collision. The enemy is set up so that it is a CharacterBody3D with several CollisionShape3D nodes as children, and those collision shapes are parent to a single MeshInstance3D each. The collision shapes are created and added as children to the character body through code.

My problem is I have a player that fires a bullet when I left click, and when it hits the enemy it’s supposed to queue_free() the CollisionBody3D that it collided with. The first time this works correctly, but subsequent shots have unexpected behavior. If the collision body that I’m trying to free is higher in the SceneTree, then it works as expected, but if my bullet hits a collision body that’s lower in the SceneTree, it will either destroy a different block, seemingly at random and keep the block that it hit, or it will throw out an error if I shoot the same block several times.

E 0:00:03:0674 Bullet.gd:22 @ _physics_process(): Condition “!shapes.has(p_owner)” is true. Returning: nullptr
<C++ Source> scene/3d/collision_object_3d.cpp:600 @ shape_owner_get_owner()
Bullet.gd:22 @ _physics_process()

For some more detail about the enemy, its script calls a function from a global script that takes a text file with coordinate information, parses the data, and creates a new CollisionShape3D and a MeshInstance3D for each coordinate. Then the mesh gets added as a child to the collision shape, and the collision shape is added as a child to the character body.

I am using this section of code from my bullet scene to reference the collision bodies and free them.

I don’t know why using shape_owner_get_owner() returns the CollisionShape3D because its description sounds like it should be getting the shape owners parent which would be the CharacterBody3D of the enemy.

In short I can only free one collision body from my enemy before getting unexpected behavior

Google Drive link to my project if anyone wants to get a closer look at the scripts

https://drive.google.com/file/d/1gnHT2yj3m2Ux4XvTU9hY-7UdbxX31-vl/view?usp=drive_link

The owner_id is not the same as the shape_id

RayCast3D.get_collider_shape() returns the shape_id but CollisionObject3D.shape_owner_get_owner() expects the owner_id. You can get the owner_id from the shape_id with CollisionObject3D.shape_find_owner()

1 Like

the link is Access Denied here

why self queue_free() then you have a block of code under it running? wont it crash by that?

It seems that passing the owner id did fix the issue, I probably got thrown off because when I was passing in the shape id, it by chance was still returning a CollisionBody3D
Also I unrestricted the archive in case anyone still wants to look at it

Edit: Also I think the reason queue_free() at the start isn’t causing issues is because it’s able to finish everything before the end of the frame, but I should still probably have it at the end as good practice

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.