Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

优化 3D 性能

剔除

Godot会自动执行视图视锥剔除, 以防止渲染视口外的物体. 这对于发生在小范围内的游戏来说效果很好, 然而在较大的关卡中, 事情很快就会变得很麻烦.

遮挡剔除

比如走在一个小镇上, 你可能只能看到你所在的街道上的几栋建筑, 以及天空和几只飞过头顶的鸟. 然而就一个天真的渲染器而言, 你仍然可以看到整个小镇. 它不会只渲染你前面的建筑, 它会渲染那后面的街道, 与那条街上的人, 那后面的建筑. 你很快就会遇到这样的情况: 你试图渲染比可见的东西多10倍或100倍的东西.

Things aren't quite as bad as they seem, because the Z-buffer usually allows the GPU to only fully shade the objects that are at the front. This is called depth prepass and is enabled by default in Godot when using the Forward+ or Compatibility rendering methods. However, unneeded objects are still reducing performance.

One way we can potentially reduce the amount to be rendered is to take advantage of occlusion. Godot 4.0 and later offers a new approach to occlusion culling using occluder nodes. See 遮挡剔除 for instructions on setting up occlusion culling in your scene.

备注

In some cases, you may have to adapt your level design to add more occlusion opportunities. For example, you may have to add more walls to prevent the player from seeing too far away, which would decrease performance due to the lost opportunities for occlusion culling.

透明物体

Godot通过 MaterialShader 对对象进行排序以提高性能. 然而, 这对透明物体来说是不可能的. 透明物体从后往前渲染, 以便与后面的物体混合. 因此, 尽量少使用透明对象 . 如果一个物体有一小部分是透明的, 尽量让这部分成为一个独立的表面, 有自己的材质.

更多信息请参阅 GPU 优化 文档。

细节程度(LOD)

在某些情况下, 特别是在远处, 用简单的版本**代替复杂的几何图形可能是个好主意. 最终用户可能看不出什么区别. 考虑看看远处的大量树木. 有几种策略可以替换不同距离的模型. 你可以使用较低的多边形模型, 或者使用透明度来模拟更复杂的几何体.

Godot 4 提供了多种控制细节层次的方法:

While they can be used independently, these approaches are most effective when used together. For example, you can set up visibility ranges to hide particle effects that are too far away from the player to notice. At the same time, you can rely on mesh LOD to make the particle effect's meshes rendered with less detail at a distance.

Visibility ranges are also a good way to set up impostors for distant geometry (see below).

Billboard 和 imposter

The simplest version of using transparency to deal with LOD is billboards. For example, you can use a single transparent quad to represent a tree at distance. This can be very cheap to render, unless of course, there are many trees in front of each other. In this case, transparency may start eating into fill rate (for more information on fill rate, see GPU 优化).

另一种方法是不只渲染一棵树, 而是将一些树作为一组来渲染. 如果你能看到一个区域, 但在游戏中不能实际接近它, 这可能是特别有效的.

你可以通过预先渲染对象的不同角度的视图来制作冒牌货. 或者你甚至可以更进一步, 周期性地将一个物体的视图重新渲染到一个纹理上, 作为一个冒牌货使用. 在远处, 你需要将观察者移动相当长的距离, 视角才会发生显著变化. 这可能是复杂的工作, 但可能是值得的, 这取决于你正在制作的项目类型.

使用实例化(MultiMesh)

如果必须在同一地点或附近绘制多个相同的对象, 请尝试使用 MultiMesh 来代替.MultiMesh允许以很小的性能代价来绘制成千上万的对象, 这使得它非常适合用于绘制羊群, 草地, 粒子以及其他任何有成千上万相同对象的地方.

See also the Using MultiMesh documentation.

烘焙照明

Lighting objects is one of the most costly rendering operations. Realtime lighting, shadows (especially multiple lights), and global illumination are especially expensive. They may simply be too much for lower power mobile devices to handle.

Consider using baked lighting, especially for mobile. This can look fantastic, but has the downside that it will not be dynamic. Sometimes, this is a tradeoff worth making.

See 使用光照贴图全局照明 for instructions on using baked lightmaps. For best performance, you should set lights' bake mode to Static as opposed to the default Dynamic, as this will skip real-time lighting on meshes that have baked lighting.

The downside of lights with the Static bake mode is that they can't cast shadows onto meshes with baked lighting. This can make scenes with outdoor environments and dynamic objects look flat. A good balance between performance and quality is to keep Dynamic for the DirectionalLight3D node, and use Static for most (if not all) omni and spot lights.

动画和皮肤

Animation and vertex animation such as skinning and morphing can be very expensive on some platforms. You may need to lower the polycount considerably for animated models, or limit the number of them on screen at any given time. You can also reduce the animation rate for distant or occluded meshes, or pause the animation entirely if the player is unlikely to notice the animation being stopped.

The VisibleOnScreenEnabler3D and VisibleOnScreenNotifier3D nodes can be useful for this purpose.

庞大的世界

如果你要制作大型游戏, 则与小型游戏可能会有所不同.

大型的世界可能需要用碎片建立, 可以在你在世界中移动时按需加载, 这可以防止内存使用失控, 也可以将所需的处理限制在局部区域.

There may also be rendering and physics glitches due to floating point error in large worlds. This can be resolved using 大世界坐标. If using large world coordinates is an option, you may be able to use techniques such as orienting the world around the player (rather than the other way around), or shifting the origin periodically to keep things centred around Vector3(0, 0, 0).