Up to date

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

从 Godot 3 升级到 Godot 4

我应该升级到 Godot4 吗?

在开始升级之前,有必要考虑一下升级会给你的项目带来的优点和缺点。

升级的优点

除了 4.0 中提供的新功能之外,升级还有如下优点:

  • 许多问题已经在4.0进行了修复,但是由于各种各样的原因(例如不同的图形API以及向后兼容性等),这些问题无法在3.x版本中修复。

  • 4.x 版本将享受更长的支持周期。Godot 3.x 也将在 4.0 发布之后支持一段时间,但最终将会放弃支持。

记录 Godot 4.0 中新功能的文档页面列表见 PopupMenu

升级的缺点

如果你不需要 Godot 4.0 中的功能,留在 Godot 3.x 中可能有如下原因:

  • Godot 3.x 是身经百战了,而 Godot 4 还太年轻。

    • Godot 4.0 应该会有一些工作流和性能问题,在 Godot 3.x 中则没有对应的问题。这些问题会在后续的 Godot 4.x 版本中陆续解决。

  • Godot 4 的第三方教程比 Godot 3.x 要少。如果你是游戏引擎小白,使用 Godot 3.x 的体验会丝滑很多。

  • Godot 4 的基准硬件需求要稍高一些(例如内存占用),无论是编辑器还是导出后的项目。这些都是实现核心优化所必须的。

  • 由于 Godot 4 比 Godot 3 包含更多的功能,Godot 4 导出的项目二进制文件相比更大。这个问题可以通过针对大小优化构建来缓解,但是启用模块相同的前提下,4.0 构建的大小仍然会比 3.x 构建要大。为 Web 导出时可能会造成一些问题,因为二进制文件的大小对引擎初始化的速度有直接影响(不考虑下载速度)。

  • Godot 4 不支持且不会提供对 GLES2 渲染器的支持。(使用新的 OpenGL 后台,Godot依然支持 GLES3 渲染器,这意味着不支持Vulkan的设备依旧可以运行Godot 4。)

    • 如果你的目标是像 Intel Sandy Bridge(第二代)集成图形一样极其老旧的硬件,升级后将阻止项目在此类硬件上运行。软件 OpenGL 实现可以用来绕过这个限制,但对于游戏来说太慢了。

升级的注意事项

由于 Godot 4 在许多方面都是完全重写的,一些功能在这个过程中不幸地丢失了。其中一些功能可能会在未来的 Godot 版本中恢复:

  • Bullet 物理引擎被移除以支持 GodotPhysics。这只会影响使用默认物理引擎(即 Bullet)且没有手动更改为 GodotPhysics 的3D项目。没有在核心中重新添加 Bullet 物理引擎的计划,但由于 GDExtension,可以为其创建第三方附加组件。

  • 2D 渲染不在执行HDR,这意味着 modulate中的 “overbright” 不会产生效果。我们计划在未来某个时候进行修复。

  • 虽然使用 Forward Plus 或 Forward Mobile 后端时,渲染仍然会以 3D HDR 形式进行,但视口无法再返回 HDR 数据。 计划在未来某个时候恢复这一功能。

  • Mono 被替换为 .Net 6。这意味着现在不支持导出 C# 项目到 Android,iOS 和 HTML5。导出 C# 项目到桌面平台依然是支持的,并且从 4.2 开始,实验性支持导出到移动平台。随着上游支持的改进,将 C# 项目导出到更多平台的支持将在未来的 4.x 版本中恢复。

你可以通过在 GitHub 上搜索`'issues labeled' 为"regression"而不是"bug" <https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen +label%3Aregression+-label%3Abug>`_ 来找到更完整的功能回归列表。

升级前的准备(可选)

如果你想在未来升级到 Godot 4,可以考虑在你的项目中使用 TweenerTime 单例。这些类在 Godot 3.5 及更高版本中都已可用。

如此,你便不用再依赖已弃用的 Tween node 和 OS time 函数,这两个函数在 Godot 4.0 中都被删除了。

使用 .gdshader 后缀来替换 .shader 后缀是一个很好的点子。Godot 3.x 支持这两种后缀,但 Godot 4.0 仅支持 .gdshader 这一种。

运行项目升级工具

警告

升级前,请将显示进行完整备份!项目升级工具不会对升级的项目进行备份。

你可以使用版本控制备份项目,也可以将项目文件夹复制到其他位置。

使用项目管理器

使用项目升级工具:

  1. 打开 Godot 4 项目管理器。

  2. 使用导入按钮导入 Godot 3.x 项目,或者使用扫描按钮在文件夹中查找项目。

  3. 双击导入的项目(或者选中项目后选择编辑)。

  4. 你将看到一个带有两个选项的对话框:仅转换 project.godot转换整个项目。在确保你的项目已经备份之后(见上面的警告),请选择转换整个项目仅转换 project.godot 选项只应该用于高级用例,处理转换工具失败的情况。

  5. 等待项目转换完成。由许多场景组成的大项目将花费更多的时间。

  6. 当项目管理器界面再次可用时,双击项目 (或选中项目,然后选择 编辑) 在编辑器中打开。

如果由于某些项目文件过大或过长而遇到转换问题,你可以使用命令行来升级项目(参见下面的内容)。这将允许你覆盖转换器的大小限制。

使用命令行

要从 命令行 使用升级工具,建议通过使用如下参数运行 Godot 编辑器二进制文件来验证项目转换:

# [<max_file_kb>] [<max_line_size>] are optional arguments.
# Remove them if you aren't changing their values.
path/to/godot.binary --path /path/to/project/folder --validate-conversion-3to4 [<max_file_kb>] [<max_line_size>]

如果计划升级列表无误,在 Godot 编辑器二进制文件上运行以下命令来升级项目文件:

# [<max_file_kb>] [<max_line_size>] are optional arguments.
# Remove them if you aren't changing their values.
path/to/godot.binary --path /path/to/project/folder --convert-3to4 [<max_file_kb>] [<max_line_size>]

[<max_file_kb>][<max_line_size>]可选参数,用于指定要转换的文件的最大大小(单位分别为 KB 和行)。默认限制分别为 4MB 和十万行。如果文件达到上述任何一个限制,则项目转换器将不会对其进行升级。这对于防止大量资源占用会降低升级速度来说非常有用。

如果你仍然希望通过项目升级工具转换大文件,请在运行项目升级工具时增加大小限制。例如,运行带有这些参数的 Godot 编辑器二进制文件会使这两个限制都增加10倍:

path/to/godot.binary --path /path/to/project/folder --convert-3to4 40000 1000000

备注

只有Godot 3.x的项目可以使用 Godot 4 编辑器中的项目转换工具升级。

建议在使用项目升级工具之前检查你的项目是否为最新的 3.x 稳定版。

运行项目升级工具后修复项目

项目升级完成之后,你可能会注意到某些东西看起来不太正常。脚本还可能包含各种错误(在大项目中可能有几百个)。这是因为项目升级工具无法满足所有的情况。因此,升级过程的很大一部分问题仍然需要手动的解决。

自动重命名节点和资源

以下列表是 Godot 4.0 为了一致性或清晰性而简单重命名的节点。项目升级工具会在你的脚本中自动重命名它们。

在 3D 节点中有一些重命名值得注意,它们中与 2D 功能相似的节点全部以 3D 为后缀。例如 Area 现在为 Area3D

为了方便搜索,此表列出了所有已更名并自动转换的节点和资源,不包括仅在旧名称后添``3D``后缀的节点和资源:

旧名称(Godot 3.x)

新名称(Godot 4)

AnimatedSprite

AnimatedSprite2D

ARVRCamera

XRCamera3D

ARVRController

XRController3D

ARVRAnchor

XRAnchor3D

ARVRInterface

XRInterface

ARVROrigin

XROrigin3D

ARVRPositionalTracker

XRPositionalTracker

ARVRServer

XRServer

CubeMesh

BoxMesh

EditorSpatialGizmo

EditorNode3DGizmo

EditorSpatialGizmoPlugin

EditorNode3DGizmoPlugin

GIProbe

VoxelGI

GIProbeData

VoxelGIData

GradientTexture

GradientTexture1D

KinematicBody

CharacterBody3D

KinematicBody2D

CharacterBody2D

Light2D

PointLight2D

LineShape2D

WorldBoundaryShape2D

Listener

AudioListener3D

NavigationMeshInstance

NavigationRegion3D

NavigationPolygonInstance

NavigationRegion2D

Navigation2DServer

NavigationServer2D

PanoramaSky

Sky

Particles

GPUParticles3D

Particles2D

GPUParticles2D

ParticlesMaterial

ParticleProcessMaterial

Physics2DDirectBodyState

PhysicsDirectBodyState2D

Physics2DDirectSpaceState

PhysicsDirectSpaceState2D

Physics2DServer

PhysicsServer2D

Physics2DShapeQueryParameters

PhysicsShapeQueryParameters2D

Physics2DTestMotionResult

PhysicsTestMotionResult2D

PlaneShape

WorldBoundaryShape3D

Position2D

Marker2D

Position3D

Marker3D

ProceduralSky

Sky

RayShape

SeparationRayShape3D

RayShape2D

SeparationRayShape2D

ShortCut

Shortcut

Spatial

Node3D

SpatialGizmo

Node3DGizmo

SpatialMaterial

StandardMaterial3D

Sprite

Sprite2D

StreamTexture

CompressedTexture2D

TextureProgress

TextureProgressBar

VideoPlayer

VideoStreamPlayer

ViewportContainer

SubViewportContainer

Viewport

SubViewport

VisibilityEnabler

VisibleOnScreenEnabler3D

VisibilityNotifier

VisibleOnScreenNotifier3D

VisibilityNotifier2D

VisibleOnScreenNotifier2D

VisibilityNotifier3D

VisibleOnScreenNotifier3D

VisualServer

RenderingServer

VisualShaderNodeScalarConstant

VisualShaderNodeFloatConstant

VisualShaderNodeScalarFunc

VisualShaderNodeFloatFunc

VisualShaderNodeScalarOp

VisualShaderNodeFloatOp

VisualShaderNodeScalarClamp

VisualShaderNodeClamp

VisualShaderNodeVectorClamp

VisualShaderNodeClamp

VisualShaderNodeScalarInterp

VisualShaderNodeMix

VisualShaderNodeVectorInterp

VisualShaderNodeMix

VisualShaderNodeVectorScalarMix

VisualShaderNodeMix

VisualShaderNodeScalarSmoothStep

VisualShaderNodeSmoothStep

VisualShaderNodeVectorSmoothStep

VisualShaderNodeSmoothStep

VisualShaderNodeVectorScalarSmoothStep

VisualShaderNodeSmoothStep

VisualShaderNodeVectorScalarStep

VisualShaderNodeStep

VisualShaderNodeScalarSwitch

VisualShaderNodeSwitch

VisualShaderNodeScalarTransformMult

VisualShaderNodeTransformOp

VisualShaderNodeScalarDerivativeFunc

VisualShaderNodeDerivativeFunc

VisualShaderNodeVectorDerivativeFunc

VisualShaderNodeDerivativeFunc

VisualShaderNodeBooleanUniform

VisualShaderNodeBooleanParameter

VisualShaderNodeColorUniform

VisualShaderNodeColorParameter

VisualShaderNodeScalarUniform

VisualShaderNodeFloatParameter

VisualShaderNodeCubeMapUniform

VisualShaderNodeCubeMapParameter

VisualShaderNodeTextureUniform

VisualShaderNodeTexture2DParameter

VisualShaderNodeTextureUniformTriplanar

VisualShaderNodeTextureParameterTriplanar

VisualShaderNodeTransformUniform

VisualShaderNodeTransformParameter

VisualShaderNodeVec3Uniform

VisualShaderNodeVec3Parameter

VisualShaderNodeUniform

VisualShaderNodeParameter

VisualShaderNodeUniformRef

VisualShaderNodeParameterRef

手动重命名的方法、属性、信号、枚举和常量

由于项目升级工具的工作方式,并非所有 API 的重命名都可以自动执行。 以下列表包含了必须使用脚本编辑器手动执行的所有重命名项目。

如果你在下面的列表中找不到节点或资源,请参考上表查找其新名称。

小技巧

你可以在脚本编辑器打开时按 Ctrl + Shift + R 使用 在文件中替换 对话框来加快替换速度。 但是需要小心,“在文件中替换”对话框不提供任何撤消替换的方法。 使用版本控制定期提交升级工作。 如果你要比编辑器的“在文件中替换”对话框更灵活的工具,也可以使用`sd <https://github.com/chmln/sd>`__ 等命令行工具。

如果使用 C#,请记住在项目中使用 PascalCase 表示法(即帕斯卡命名法)搜索过时的 API 使用情况(并使用 PascalCase 表示法执行替换)。

方法

  • 文件和目录类已被 FileAccessDirAccess 取代,它们拥有完全不同的 API。现在有几种方法是静态的,这意味着你可以不创建对象而直接使用 FileAccess 或 DirAccess 的方法。

  • OS 单例中与屏幕和窗口相关的方法(例如 OS.get_screen_size())已被移至 DisplayServer 单例。方法命名也改为使用 DisplayServer.<对象>_<get/set>_property() 的形式。例如,OS.get_screen_size() 变成了 DisplayServer.screen_get_size()

  • 时间和日期方法已从 OS 单例移动至 Time 单例。( 在Godot 3.5 以及其后的版本中依旧如此。)

  • 你可能需要将一些``instance()``调用替换为``instantiate()``。转换器*应该*会自动处理这个,但这依赖于可能无法在100%的情况下工作的自定义代码。

  • AcceptDialog的``set_autowrap()``现在是``set_autowrap_mode()``。

  • AnimationNode的``process()``现在是``_process()``(注意前面的下划线,表示虚方法)。

  • AStar2D和AStar3D的``get_points()``现在改为``get_points_id()``。

  • BaseButton的``set_event()``现在改为``set_shortcut()``。

  • Camera2D的``get_v_offset()``现在改为``get_drag_vertical_offset()``。

  • Camera2D的``set_v_offset()``现在改为``set_drag_vertical_offset()``。

  • CanvasItem的``update()``现在改为``queue_redraw()``。

  • Control的``set_tooltip()``现在是``set_tooltip_text()``。

  • EditorNode3DGizmoPlugin的``create_gizmo()``现在改为``_create_gizmo()``(注意前面的下划线,表示虚方法)。

  • ENetMultiplayerPeer的``get_peer_port()``现在是``get_peer()``。

  • FileDialog的``get_mode()``现在是``get_file_mode()``。

  • FileDialog的``set_mode()``现在改为``set_file_mode()``。

  • GraphNode的``get_offset()``现在改为``get_position_offset()``。

  • GridMap的``world_to_map()``现在改为``local_to_map()``。

  • GridMap 的 map_to_world() 方法现在叫 map_to_local()

  • Image的 get_rect() 方法现在为 get_region()

  • ItemList 的 get_v_scroll() 方法现在为 get_v_scroll_bar()

  • MultiPlayerAPI 的 get_network_connected_peers() 现在改为 get_peers()

  • MultiPlayerAPI 的 get_network_peer() 现在改为 get_peer()

  • MultiPlayerAPI 的 get_network_unique_id() 现在改为 get_unique_id()

  • MultiPlayerAPI 的 has_network_peer() 现在是 has_multiplayer_peer()

  • PacketPeerUDP 的 is_listening() 现在是 is_bound()

  • PacketPeerUDP 的 listen() 现在是 bind()

  • ParticleProcessMaterial 的 set_flag() 现在是 set_particle_flag()

  • ResourceFormatLoader 的 get_dependencies() 现在是 _get_dependencies()(注意前面的下划线表示虚方法)。

  • SceneTree 中的 change_scene() 现改为 change_scene_to_file()

  • Shortcut 中的 is_valid() 现改为 has_valid_event()

  • TileMap 中的 world_to_map() 现改为 local_to_map()

  • TileMap 中的 map_to_world() 现改为 map_to_local()

属性

备注

如果此处列出了属性,则要在项目中使用,必须手动重命名其关联的 getter 和 setter 方法。例如, PathFollow2D 和 PathFollow3D 的 set_offset()get_offset() 必须分别重命名为 set_progress()get_progress()

  • Control 中的 margin 现改为 offset

  • Label 中的 percent_visible 现改为 visible_ratio

  • MultiPlayerAPI 中的 refuse_new_network_connections 现改为 refuse_new_connections

  • PathFollow2D 和 PathFollow3D 中的 offset 现改为 progress

  • TextureProgressBar 中的 percent_visible 现改为 show_percentage

  • CSG 节点和 VoxelGI 上的 extents``属性必须被替换成 ``size,并且将设置的值减半(因为它们不再是半个范围了)。这也同样影响它的 setter/getter 方法, set_extents()get_extents()

  • Engine.editor_hint 属性被移除以支持 Engine.is_editor_hint() 方法 。这是由于它是只读的,而 Godot 中属性不可用于只读的值。

枚举

  • CPUParticles2D 中的 FLAG_MAX 现在为 PARTICLE_FLAG_MAX

信号

  • FileSystemDock中的 instantiate 现在为 instance

  • CanvasItem 中的 hide 现在是 hidden 。 这个重命名不会影响 hide() 方法,只是信号的重命名。

  • Tween 中的 tween_all_completed 现在为 loop_finished

  • EditorSettings 中的 changed 现在为 settings_changed

常量

  • Color 中的所有属性现在均为大写并由下划线来分割。例如, Color.palegreen 现在为 Color.PALE_GREEN

  • Mainloop的 Notification_ 常量被复制到 Node ,这意味着你可以在引用它们时移除 Mainloop. 前缀。

  • MainLoop 中的 NOTIFICATION_WM_QUIT_REQUEST 现在为 NOTIFICATION_WM_CLOSE_REQUEST

检查项目设置

数个项目设置已被重命名,其中一些项目以不兼容的方式(例如阴影滤波质量 shadow filter quality )改变了枚举。这意味着你可能需要再次设置一些项目设置的值。确保在项目设置对话框中启用了 高级 切换选项,以便你可以看到所有项目设置。

检查环境设置

图形质量设置已从环境属性转移到项目设置。这样做是为了使运行时质量调整更加容易,而无需访问当前活动的环境资源再去修改其属性。

因此,你必须在项目设置中配置环境质量设置,因为旧的环境质量设置并不会自动转换为项目设置。

在 Godot 3.x 中,如果你在图形设置菜单中更改了环境属性,则必须更改相关的代码来调用 RenderingServer 中能影响环境效果质量的方法。只有每个环境效果的“基本”切换及其视觉旋钮保留在环境资源中。

更新着色器

因为着色器语言有一些更改所以无法使用升级工具进行转换。

不在支持后缀为 .shader 的文件,你需要把后缀为 .shader 的文件重命名为 .gdshader 并且在 场景/资源 设置中重新引用。

在着色器中你需要重命名以下字符:

  • 纹理过滤和重复模式现在在单独的 uniform 上设置,而不是在纹理文件本身。

  • hint_albedo 现在是 source_color

  • 内置矩阵变量已重命名。

  • 粒子着色器不再使用 vertex() 处理器函数。使用 start()process() 来代替它。

详见 着色语言

更新脚本时将向后不兼容的更改考虑在内

Godot 3.x 和 4 之间的一些变化并没有重新命名,但由于默认行为的不同,它们仍然会破坏向后兼容性。

最显著的例子如下:

  • _ready()_process() 等生命周期函数不再隐式调用同名的父类函数。相反,你必须在子类中的生命周期函数的顶部使用 super() 以调用父类中的这些生命周期函数。

  • StringStringName 现在都暴露给了GDScript,这使优化成为可能,因为 StringName 是专门为“常量”字符串设计的,这些字符串创建一次后可能会重复使用多次。String 与 StringName 类型严格来说并不等同,这意味着``is_same("example", &"example")`` 会返回 false 。虽然在大多数情况下它们可以互换( "example" == &"example" 返回 true ),但是有时候你可能需要使用 &"example" 来替换 "example"

  • GDScript 的 setter 和 getter 语法 已经发生了变化,但是转换工具仅对其进行了部分转换,在大多数情况下,需要手动更改才能使 setter 和 getter 重新工作。

  • GDScript 信号连接语法已经做了改动。转换工具将使用 Godot 4 中仍然存在的基于字符串的语法,但建议改用链接页面中描述的基于 Signal 的语法。通过这种方式,就不会在信号连接中涉及字符串,从而避免了只能在运行时发现的信号名称错误问题。

  • 作为 tool scripts 的内置脚本不会将 tool 关键字转换为 @tool 注解。

  • Tween 节点已经被移除,取而代之的是在 Godot 3.5 及更高的版本中可用的 Tweeners。详情请参见 original pull request <https://github.com/godotengine/godot/pull/41794>

  • randomize() 现在会在项目加载时自动调用,因此使用全局 RandomNumberGenerate 实例进行确定性随机化需要在脚本的 _ready() 函数中手动设置种子。

  • call_group()set_group()notify_group() 现在默认为立即调用。如果在包含大量节点的组中调用代价高昂的函数可能会导致卡顿。要像以前一样使用延迟调用,请将 call_group(...) 替换为 call_group_flags(SceneTree.GROUP_CALL_DEFERRED, ...) (并分别对 set_group()notify_group() 也进行类似的替换)。

  • 现在编辑器中的 rotation 属性取代了旧有的 rotation_degrees 属性,在检查器面板中,它会自动显示为度。这可能会破坏动画,因为转换工具无法自动处理转换。

  • AABB 的函数 has_no_surface() 被反转并重命名为了 has_surface()

  • AABBRect2 的 函数 has_no_area() 被反转并重命名为了 has_area()

  • AnimatedTexturefps 属性被 speed_scale 属性取代,其作用与 AnimationPlayer 的 playback_speed 属性相同。

  • AnimatedSprite2DAnimatedSprite3D 现在允许设置负的 speed_scale 值。如果你过去的工作依赖于 speed_scale 属性在内部被限位为 0.0 , 现在这可能会破坏动画。

  • AnimatedSprite2DAnimatedSprite3Dplaying 属性现在已经被移除。请使用 play()/stop() 方法来代替或者通过 SpriteFrames 底部面板配置 autoplay 动画(但不能同时使用这两种方法)。

  • Array's slice() second parameter (end) is now exclusive, instead of being inclusive. For example, this means that