+2 votes

Hi i try to use MultiMeshInstance with collision node.
The attaches script works so far but the collision shape is only applyed to the MultiMeshInstance and not to the mesh instances.

Looks like MultiMeshInstance not handels collision shapes for all instances respecting translation, scale and rotating

The applied collision shape is static and has the original transformation from the original cube.
So how add a collision shape right to a MultiMeshInstance ?

Here my small test script

extends Node

func _ready():
    # create a simple box mesh
    var mesh = CubeMesh.new()
    mesh.size = Vector3(1,1,1)

    # create multi mesh
    var multiMesh = MultiMesh.new()
    multiMesh.transform_format = MultiMesh.TRANSFORM_3D
    multiMesh.color_format = MultiMesh.COLOR_FLOAT
    multiMesh.mesh = mesh
    multiMesh.instance_count = 4

    var mmi = MultiMeshInstance.new()
    mmi.multimesh = multiMesh;

    # create collision shape
    var collisionNode = StaticBody.new()
    var collisionShape = CollisionShape.new()
    collisionShape.shape = multiMesh.mesh.create_trimesh_shape()
    collisionNode.add_child(collisionShape)
    mmi.add_child(collisionNode)
    add_child(mmi)

    for mesh_index in range(multiMesh.instance_count):
        var position = Transform().translated(Vector3(mesh_index*2, 10+2, 0)).scaled(Vector3(1,1,1))
        multiMesh.set_instance_transform(mesh_index, position)

The official documentation has no info about MultiMeshInstance and using collision.
I use Godot 3.1.1

asked Oct 1, 2019 in Engine by NullPointer (46 points)
edited Dec 1, 2019 by NullPointer

1 Answer

+2 votes

I think a MultiMesh cannot currently be converted directly into a static body mesh. Even if it could, your code would not work for several reasons:
- You are creating your static body from the single mesh, not the multimesh
- You are defining where each instance is located only after creating your static body.

The transforms you are setting at the end are also purely for the renderer.

If you want collision on your instances, you need to create a static body for each of them, and give them the same transform.

Something like this (untested):

var shape = multiMesh.mesh.create_trimesh_shape()

for mesh_index in range(multiMesh.instance_count):
    var position = Transform().translated(Vector3(mesh_index*2, 10+2, 0)).scaled(Vector3(1,1,1))
    multiMesh.set_instance_transform(mesh_index, position)

    # create collision shape
    var collisionShape = CollisionShape.new()
    collisionShape.shape = shape
    var collisionNode = StaticBody.new()
    collisionNode.transform = position
    collisionNode.add_child(collisionShape)
    mmi.add_child(collisionNode)
    add_child(mmi)
answered Oct 1, 2019 by Zylann (27,004 points)

Thanks for the fast anwser

That the anwser i unfortunately expected, ;(

My hope was the MultiMesh has some implemented functionallity to manage collision shapes by it self.
e.g. auto create collision shape for each instance and apply the transform by multiMesh.set_instance_transform( index, ..)

But what happens when i create tousends of multimesh ( original 1 mesh in memory) but additional extra tousends of collision shape nodes?
This takes the optimisations of MultiMesh ad absurdum or ?

Best Regards

Would be a good improvement for MultiMesh ;)

I don't know, I never had the need to give collision to thousands of individual objects at once so far. You could try and see.
The reason MultiMesh exists is because GPU instancing is a common rendering technique. But physics-wise, there doesn't seem to be an equivalent, a static body is a static body.
Perhaps you could at least have a single static body, with a CollisionShape for each instead of many static bodies:

# Re-use the same shape
var shape = multiMesh.mesh.create_trimesh_shape()
# Create one static body
var collisionNode = StaticBody.new()
mmi.add_child(collisionNode)

for mesh_index in range(multiMesh.instance_count):
    var position = Transform().translated(Vector3(mesh_index*2, 10+2, 0)).scaled(Vector3(1,1,1))
    multiMesh.set_instance_transform(mesh_index, position)

    # Create many collision shapes
    var collisionShape = CollisionShape.new()
    collisionShape.shape = shape
    collisionShape.transform = position
    collisionNode.add_child(collisionShape)

Thanks,

yes to use a single static body makes sence ;)
I will do that in this way.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.