Using convex decomposition as collider

Godot Version 4.2.1

Question

I have a model I have made in blender.

I have also created a convex decomposition of it in blender.

The model is complex, and the decomposition is made of several convex shapes.

I can export/import the models into Godot. But I cant seem to assign the collision mesh as the shape.

I assume I am just approaching it wrong.

After I create the rigidBody3d and CollisionShape3D, I go to assign a shape to it.

But I cant assign my collision mesh to it. It is looking for a .tres or similar while the engine has imported it as glb.

I assume either my approach is misguided or it is a simple thing I am missing.

Any help would be appreciated, thank you.

You can add a suffix to the objects in Blender that will automatically convert them to the correct Node when imported. More info here Node type customization using name suffixes — Godot Engine (stable) documentation in English

I will try this later tonight.

I apologize I cannot try it right now, so I have a few additional queations.

So, if I understand, I should put -rigid in the name of the mesh for the visual model, and -convcolonly (not -convcol?) in the names of the collision meshes.

Does the hierarchy within blender affect this at all?

Since my collision is several shapes, will it import them seperately, or as one object?

Okay, I have tried to follow this - and tried many variations of it, but don’t quite get the correct results.

For example:

In blender, I created a simple concave test shape. I decomposed it into convex shapes.

In blender, the convex shapes are parented under the original shape and have the “-convcolonly” suffix. For the parent shape, I have tried bot not giving it a suffix and giving it a suffix of “-rigid”.

Regardless, what I get is a scene that

  1. has the original shape as a RigidBody3D
  2. automatically created by Godot (not mine) convex collider (CollisionShape3D).
  3. My custom convex shapes become children that are StaticBody3D, each with the CollisionShape3D corresponding to a custom convex shape.

#2 isnt an issue, as I can easily tell the import process to skip that.

But, the result isnt usable. The main mesh has child static bodies and grandchild collision shapes (which doesnt behave as desired). I think what is needed is the collosion shapes should be direct children of the rigidbody, but that is not what happens.

Can you help me understand what I am missing?

Sorry, it seems that it only works by creating static bodies.

You could try using a EditorScenePostImport script to generate the collision nodes and shapes. You can use Mesh.create_convex_shape() to generate the ConvexPolygonShape3D.

So, I ended up making a custom import script to re-import the mesh as desired.

  1. I used blender to decompose the object. The mesh should have its own decomposition as children meshes.

  2. Then I imported it into Godot. Then went to the re-import tab and used the following script to re-import it:

@tool # Needed so it runs in the editor.
extends EditorScenePostImport

func _post_import(scene):
	print(scene.transform)
	
	print("Starting post-import processing.")
	# Ensure there is exactly one child (the main MeshInstance3D)
	if scene.get_child_count() != 1:
		push_error("Scene should have exactly one child.")
		return scene

	# Get the main MeshInstance3D
	var mesh_model = scene.get_child(0)

	# Check if the first child is a MeshInstance3D
	if not mesh_model is MeshInstance3D:
		push_error("Scene's first child should be MeshInstance3D.")
		return scene
	
	# Ensure the MeshInstance3D has at least one MeshInstance3D child
	if mesh_model.get_child_count() < 1:
		push_error("MeshInstance3D should have at least one MeshInstance3D child.")
		return scene
	
	# Check if the first grandchild is a MeshInstance3D
	if not mesh_model.get_child(0) is MeshInstance3D:
		push_error("MeshInstance3D's first child should be MeshInstance3D.")
		return scene
	
	# Detach the main MeshInstance3D from the scene
	scene.remove_child(mesh_model)
	
	# Create a new RigidBody3D and configure it
	var rigid_body = RigidBody3D.new()
	rigid_body.name = mesh_model.name + "_rigid"
	
	# Add the main MeshInstance3D as a child of the new RigidBody3D
	rigid_body.add_child(mesh_model)
	# Set the owner to the rigid_body to ensure it's saved with the scene
	mesh_model.owner = rigid_body  

	# Iterate through MeshInstance3D children to create individual collision shapes
	for child in mesh_model.get_children():
		if child is MeshInstance3D and child.mesh:
			var mesh_shape = child.mesh.create_convex_shape()
			var collision_shape = CollisionShape3D.new()
			collision_shape.shape = mesh_shape
			# Apply the original mesh child's transform to the collision shape
			collision_shape.transform = child.transform
			# Add the collision shape to the RigidBody3D
			rigid_body.add_child(collision_shape)
			# Set the owner to ensure it's saved with the rigid_body
			collision_shape.owner = rigid_body
			print("Added CollisionShape3D for: ", child.name)
			# Remove the original MeshInstance3D as it's now represented by a collision shape
			child.queue_free()
	
	# Free the original scene root, as it's no longer needed
	scene.queue_free()
	print("Finished setting up RigidBody3D and collision shapes.")
	# Return the new root node (RigidBody3D) to replace the original scene root
	return rigid_body

Also of note:

I used the following blender plugin to help decompose and export:

although I had to tweak it to run on the current version. I also tweaked it to export as gltf. But it supports CoaCD which is much better IMO than VHaCD.

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