|
|
|
|
Reply From: |
Tim Martin |
You want to do similar to the tutorial here Animating thousands of fish with MultiMeshInstance3D — Godot Engine (stable) documentation in English
Note that when you set instance_count
you effectively lock the multimesh, so do the setup first, set the number, and then set their positions.
E.g. script to be attached to a multimesh node
extends MultiMeshInstance
const HOW_MANY : int = 10
func _ready():
multimesh = MultiMesh.new()
multimesh.transform_format = MultiMesh.TRANSFORM_3D
multimesh.mesh = $"../MY_MESH_INSTANCE".mesh.duplicate()
multimesh.instance_count = HOW_MANY
for i in range(HOW_MANY):
# Set offset coordinates here. Replace Basis() if you need rotation too
multimesh.set_instance_transform(i, Transform(Basis(), Vector3(0, 0, 0)))
I know how to spawn instanced. That’s not my question (I may have been imprecise).
The question is:
How do i manipulate set_instance_transform
to have each instance spawn at a location that is stored in a separate array. So it’s 2 separate arrays, one for multimesh instances (instance count), and one for 3d locations in the world. How do I pair them up?
Macryc | 2020-05-10 11:37
Hello Macryc,
At this point you can just use the same index i
over both arrays?
Supposing you have var positions : Array
with size HOW_MANY
and with each entry a Vector3
, the final line would then be multimesh.set_instance_transform(i, Transform(Basis(), positions[i]))
Tim Martin | 2020-05-10 11:50
Hey Tim, it worked!
Thanks. My next question is going to be: how do I remove an multimesh instance when the ‘grass’ cell is replaced with a different type. Definitely don’t want to reload the whole thing each time…
Macryc | 2020-05-10 12:20
While it might be considered a bit of a hack,
func remove_instance(var i : int):
var t : Transform = multimesh.get_instance_transform(i)
t.origin.y -= 1000
multimesh.set_instance_transform(i, t)
is a valid way of doing this. I.e. just hide it deep, deep underground.
Tim Martin | 2020-05-10 12:46
Awesome, I’ll try that. Cheers.
BTW, do you happen to know how one should go about rotating each instance by 90 degrees on one of the axes? Trying to find this in the docs, no luck so far…
Macryc | 2020-05-10 12:50
Manipulate the Basis
in the Transform
, this is where the rotation data is held (edit - typo)
var b := Basis()
b = b.rotated(Vector3.UP, deg2rad(90))
var t := Transform(b, positions[i])
Tim Martin | 2020-05-10 13:00
thanks. I’ve played around with these and got it to work more or less the way I intended. Just to confirm though - there is not way to queue_free
a multimesh instance, is there? As long as the number of instances has no bearing on performance, that’s ok. It’s just that I’m worried about having dozens or hundreds of instances buried underground and still impacting on performance. Or is this a silly thing to fear?
Macryc | 2020-05-10 13:54
It’s unavoidable, that’s the trade off of using a MultiMesh. It’s batching together one draw call to the GPU for all of your instances, as opposed to sending a single call per mesh.
As a consequence it can either send all of them, or none of them. The occluded ones will have some performance penalty, but it should be very small. MultiMesh is designed to scale to be drawing thousands of instances.
Tim Martin | 2020-05-10 15:09