Work in progress

The content of this page was not yet updated for Godot 4.2 and may be outdated. If you know how to improve this page or you can confirm that it's up to date, feel free to open a pull request.

Optimization using MultiMeshes

大量のインスタンス(数千)で、常に処理する必要がある(および一定量の制御を保持する必要がある)場合、using servers directly が推奨される最適化です。

オブジェクトの数が数十万または数百万に達すると、これらのアプローチはいずれももはや効率的ではありません。それでも、要件によっては、もう1つの最適化が可能です。

MultiMesh

MultiMesh は、一度に最大数百万のオブジェクトを描画できる単一の描画プリミティブです。 GPUハードウェアを使用してこれを行うため、非常に効率的です(ただし、OpenGL ES 2.0では、ハードウェアサポートがないため効率が低下します)。

唯一の欠点は、個々のインスタンスに対して screen または frustum カリングができないことです。これは、MultiMesh全体の可視性に応じて、何百万ものオブジェクトが常にまたは決して描画されないことを意味します。それらにカスタムの可視領域矩形 (Visibility Rect)を提供することは可能ですが、常に all-or-none の可視性になります。

オブジェクトが十分に単純な場合(ほんの2、3の頂点)、ほとんどの最新のGPUはこのユースケースに最適化されているため、これは一般にそれほど問題ではありません。回避策は、ワールドのさまざまな地域に複数のマルチメッシュを作成することです。

It is also possible to execute some logic inside the vertex shader (using the INSTANCE_ID or INSTANCE_CUSTOM built-in constants). For an example of animating thousands of objects in a MultiMesh, see the Animating thousands of fish tutorial. Information to the shader can be provided via textures (there are floating-point Image formats which are ideal for this).

Another alternative is to use a GDExtension and C++, which should be extremely efficient (it's possible to set the entire state for all objects using linear memory via the RenderingServer.multimesh_set_buffer() function). This way, the array can be created with multiple threads, then set in one call, providing high cache efficiency.

最後に、すべてのMultiMeshインスタンスを表示する必要はありません。表示されるものの量は、MultiMesh.visible_instance_count プロパティで制御できます一般的なワークフローでは、使用するインスタンスの最大量を割り当て、現在必要なインスタンス数に応じて表示される量を変更します。

Multimeshの例

以下は、コードからMultiMeshを使用する例です。 GDScript以外の言語は、数百万のオブジェクトに対してより効率的かもしれませんが、数千に対してはGDScriptで十分です。

extends MultiMeshInstance3D


func _ready():
    # Create the multimesh.
    multimesh = MultiMesh.new()
    # Set the format first.
    multimesh.transform_format = MultiMesh.TRANSFORM_3D
    # 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)))