Work in progress
The content of this page was not yet updated for Godot
4.5
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.
MultiMeshを使用した最適化
大量のインスタンス(数千)で、常に処理する必要がある(および一定量の制御を保持する必要がある)場合 サーバーを直接使用 する最適化が推奨されます。
オブジェクトの数が数十万または数百万に達すると、これらのアプローチはいずれももはや効率的ではありません。それでも、要件によっては、もう1つの最適化が可能です。
MultiMesh
MultiMesh は、一度に最大数百万のオブジェクトを描画できる単一の描画プリミティブです。これは GPU ハードウェアを使用して実行されるため、非常に効率的です。
唯一の欠点は、個々のインスタンスに対して スクリーン または フラスタム カリングができないことです。これは MultiMesh全体の可視性に応じて、何百万ものオブジェクトが常にまたは決して描画されないことを意味します。それらにカスタムの可視領域矩形 (Visibility Rect)を提供することは可能ですが、常に オールオアナッシング の可視性になります。
オブジェクトが十分に単純な場合(ほんの2、3の頂点)、ほとんどの最新のGPUはこのユースケースに最適化されているため、これは一般にそれほど問題ではありません。回避策は、ワールドのさまざまな地域に複数のマルチメッシュを作成することです。
頂点シェーダー内でいくつかのロジックを実行することもできます (ビルトイン定数の INSTANCE_ID または INSTANCE_CUSTOM を使用)。MultiMesh で何千ものオブジェクトをアニメーション化する例については、チュートリアル Animating thousands of fish を参照してください。シェーダーへの情報はテクスチャ経由で提供できます (これに最適な浮動小数点 Image 形式があります)。
別の方法は GDExtension と C++ を使用することです。これは非常に効率的です (RenderingServer.multimesh_set_buffer() 関数を介して線形メモリを使用してすべてのオブジェクトの状態全体を設定できます)。この方法では、配列を複数のスレッドで作成し、1 回の呼び出しで設定できるため、高いキャッシュ効率が得られます。
最後に、すべての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)))
using Godot;
public partial class MyMultiMeshInstance3D : MultiMeshInstance3D
{
public override void _Ready()
{
// Create the multimesh.
Multimesh = new MultiMesh();
// Set the format first.
Multimesh.TransformFormat = MultiMesh.TransformFormatEnum.Transform3D;
// Then resize (otherwise, changing the format is not allowed)
Multimesh.InstanceCount = 1000;
// Maybe not all of them should be visible at first.
Multimesh.VisibleInstanceCount = 1000;
// Set the transform of the instances.
for (int i = 0; i < Multimesh.VisibleInstanceCount; i++)
{
Multimesh.SetInstanceTransform(i, new Transform3D(Basis.Identity, new Vector3(i * 20, 0, 0)));
}
}
}