Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Ottimizzazione tramite MultiMesh

Per un gran numero di istanze (in migliaia) che devono essere elaborate costantemente (e per le quali è necessario mantenere un certo grado di controllo), l'utilizzo diretto dei server è l'ottimizzazione consigliata.

Quando il numero di oggetti raggiunge centinaia di migliaia o milioni, nessuno di questi approcci rimane efficiente. Eppure, a seconda dei requisiti, è possibile un'ulteriore ottimizzazione.

I MultiMesh

Un MultiMesh è una singola primitiva di disegno in grado di disegnare fino a milioni di oggetti in una volta sola. È estremamente efficiente perché utilizza l'hardware della GPU per farlo.

L'unica pecca è che non è possibile applicare il culling di schermo o frustum per le singole istanze. Ciò significa che milioni di oggetti saranno sempre o mai disegnati, a seconda della visibilità dell'intero MultiMesh. È possibile fornire un rettangolo di visibilità personalizzato per gli oggetti, ma la visibilità sarà sempre tutto o niente.

Se gli oggetti sono semplici abbastanza (solo un paio di vertici), questo generalmente non è un grosso problema, poiché la maggior parte delle GPU moderne è ottimizzata per questo caso d'uso. Una soluzione alternativa è creare diversi MultiMesh per diverse aree del mondo.

È anche possibile eseguire certa logica all'interno dello shader dei vertici (utilizzando le costanti integrate INSTANCE_ID o INSTANCE_CUSTOM). Per un esempio di animazione di migliaia di oggetti in un MultiMesh, consultare il tutorial Animare migliaia di pesci. Le informazioni per lo shader si possono fornire shader tramite texture (esistono formati a virgola mobile di Image che sono ideali per questo).

Un'altra alternativa è utilizzare una GDExtension e C++, che dovrebbe essere estremamente efficiente (è possibile impostare l'intero stato per tutti gli oggetti che usano memoria lineare tramite la funzione RenderingServer.multimesh_set_buffer()). In questo modo, l'array si può creare con più thread e poi impostare in una singola chiamata, garantendo un'elevata efficienza della cache.

Infine, non è necessario che tutte le istanze di MultiMesh siano visibili. Il numero di istanze visibili si può controllare tramite la proprietà MultiMesh.visible_instance_count. La tipica procedura consiste nell'allocare il numero massimo di istanze che saranno utilizzate, e poi cambiare la quantità visibile a seconda della quantità necessaria al momento.

Esempio Multimesh

Ecco un esempio di come usare un MultiMesh da codice. Altri linguaggi diversi da GDScript potrebbero essere più efficienti per milioni di oggetti, ma per poche migliaia, GDScript dovrebbe andare bene.

extends MultiMeshInstance3D


func _ready():
    # Create the multimesh.
    multimesh = MultiMesh.new()
    # Set the format first.
    multimesh.transform_format = MultiMesh.TRANSFORM_3D
    # Set the mesh that will be duplicated.
    multimesh.mesh = BoxMesh.new()
    # Then resize (otherwise, changing the format is not allowed).
    multimesh.instance_count = 10000
    # Maybe not all of them should be visible at first.
    multimesh.visible_instance_count = 1000

    # Set the transform of the instances.
    for i in multimesh.visible_instance_count:
        multimesh.set_instance_transform(i, Transform3D(Basis(), Vector3(i * 20, 0, 0)))