Work in progress

The content of this page was not yet updated for Godot 4.4 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 优化

对于需要不断处理(且保留一定控制的)大量实例(成千上万),建议直接使用服务器进行优化。

当对象数量达到数十万或数百万时, 这些方法都不再有效. 尽管如此, 根据要求, 还有另一种可能的优化方法.

MultiMesh

A MultiMesh is a single draw primitive that can draw up to millions of objects in one go. It's extremely efficient because it uses the GPU hardware to do this.

唯一的缺点是, 对于单个实例, 不可能进行 屏幕视锥 剔除. 这意味着, 根据整个MultiMesh的可见性, 数百万个对象将被 始终不会 绘制. 可以为它们提供一个自定义的可见性矩形, 但它将始终是 全或无 的可见性.

如果对象足够简单(只有几个顶点), 这通常不是什么大问题, 因为大多数现代GPU都为这种用例进行了优化. 一个变通的方法是为世界的不同区域创建多个MultiMeshes.

也可以在顶点着色器中执行一些逻辑(使用 INSTANCE_IDINSTANCE_CUSTOM 内置常量). 关于在MultiMesh中对数千个对象进行动画制作的例子, 请参见 Animating thousands of fish 教程. 可以通过纹理向着色器提供信息(有浮点 Image 格式是理想的格式).

另一种选择是使用 GDExtension 和 C++,这应该非常高效(可以通过 RenderingServer.multimesh_set_buffer() 函数使用线性内存设置所有对象的全部状态)。这样,可以使用多个线程创建数组,然后在单次调用中设置,从而提供较高的缓存效率。

最后, 并不是所有的MultiMesh实例都必须是可见的. 可以通过 MultiMesh.visible_instance_count 属性来控制可见的数量. 典型的工作流程是先分配最大数量的实例, 然后根据当前需要的数量改变可见的数量.

多重网格示例

这里是一个从代码中使用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)))