从 Unity 迁移到 Godot 引擎

本指南从Unity用户的角度概述了Godot引擎,旨在帮助您将现有的Unity体验迁移到Godot的世界中.

注解

本文讨论了旧版本的Unity.可嵌套的预制件( 嵌套的预制件(Nested prefabs) )已添加到Unity 2018.3中.可嵌套的预制件类似于Godot的场景,允许采用更像Godot的方式进行场景组织.

差异

Unity

Godot

许可证

专有,封闭,有收入上限和使用限制的免费许可证

MIT许可证,免费,完全开源,没有任何限制

操作系统(编辑器)

Windows、macOS、Linux

Windows、macOS、X11(Linux, *BSD)

操作系统 (导出)

  • 桌面端: Windows、macOS、Linux

  • 移动端: Android、iOS、Windows Phone、Tizen

  • 网页: WebAssembly 或 asm.js

  • 游戏主机: PS4、PS Vita、Xbox One、Xbox 360、Wii U、Nintendo 3DS

  • 虚拟现实(VR): Oculus Rift、SteamVR、Google Cardboard、Playstation VR、Gear VR、HoloLens

  • 电视端: Android TV、Samsung SMART TV、tvOS

  • 桌面端: Windows、macOS、X11

  • 移动端: Android、iOS

  • 网页: WebAssembly

  • 游戏主机:Godot支持的游戏机

  • 虚拟现实端: Oculus Rift、SteamVR

场景系统

  • 组件/场景 (游戏物体(GameObject) > 组件(Component))

  • 预制体

场景树和节点,允许场景被嵌套和/或继承其他场景

第三方工具

Visual Studio 或 VS Code

显著优势

  • 庞大的社区

  • 丰富的素材商店

编辑器

Godot引擎提供了功能丰富的编辑器,可让您构建游戏.下图显示了两个编辑器的默认布局,并带有彩色块,以指示常用功能.

../../_images/unity-gui-overlay.png ../../_images/godot-gui-overlay.png

尽管两个编辑器看起来很相似,但外表下有许多差异.两者都允许您使用文件系统来组织项目,但是Godot的方法更简单,只需一个配置文件,简约的文本格式且没有元数据.这使Godot对VCS系统(如Git,Subversion或Mercurial)更加友好.

Godot的场景面板与Unity的层次结构面板类似,但是由于每个节点都有特定的功能,因此Godot所使用的方法更具视觉描述性.一目了然地了解场景干什么.

Godot 的属性检查器更为简单,它仅显示属性.得益于此,对象可以向用户暴露大量有用的参数,而无需把功能隐藏在语言 API 中.另外,Godot允许可视化地动画化这些属性.无需编写代码就可以实时更改颜色、纹理、枚举、甚至是资源链接.

屏幕顶部的工具栏在两个编辑器中都相似,提供对项目运行的控制.Godot中的项目在单独的窗口中运行,而不是在编辑器中运行(但是仍然可以在调试器窗口中浏览树和对象).

这一方法有着如下优点:

  • 运行项目以及关闭它的速度很快(Unity必须保存、运行项目、关闭项目、然后重新加载先前的状态).

  • 实时编辑更为有用,因为对编辑器所做的更改会在游戏中立即生效,并且在游戏关闭时不会丢失(也不必同步).这样允许出色的工作流程,例如在运行游戏时创建关卡.

  • 编辑器更稳定,因为游戏在单独的进程中运行.

  • 通过在编辑器视窗中切换”摄影机替代”按钮,可以从不同角度浏览正在运行的游戏,该按钮将在使用编辑器视图和游戏摄影机视图之间进行切换.

最后,Godot的顶部工具栏包括一个用于远程调试的菜单.这些选项允许将设备部署到设备(通过HTML5连接的手机、平板电脑、或浏览器),并在导出游戏后对其进行调试/实时编辑.

场景系统

这是Unity和Godot之间的最重要区别,也是大多数Godot用户最喜欢的功能.

在Unity中一个 关卡 上工作通常意味着将所有必需的素材嵌入场景中,并将它们与组件和脚本链接在一起.

Godot的场景系统表面上类似于Unity.一个 关卡 由一组节点组成,每个节点都有其自己的用途:Sprite、Mesh、Light等.但是,在Godot中,节点排列在一棵树中.每个节点可以有多个子代,这使得每个子代都是主场景的一个子场景.这意味着您可以用存储在不同文件中的不同场景组合成整个场景.

例如,一个平台游戏的关卡.您可以用多个元素来组合它:

  • 砖块

  • 金币

  • 游戏角色

  • 敌人

在Unity中,您将所有游戏对象(GameObjects)放置在场景中:游戏角色、敌人的多个实例、到处都是用砖块构成关卡的地面,然后在关卡中放置的硬币的多个实例.然后,您将向每个元素添加各种组件以链接它们并在关卡中添加逻辑:例如,您将 BoxCollider2D 添加到场景的所有元素,以便它们可以碰撞.这一理念在Godot中不同.

在Godot中,您将整个场景分为三个单独的较小的场景,并在主场景中对其进行实例化.

  1. 仅用于游戏角色(Player)的场景.

将游戏角色视为我们要在不同父场景(例如 关卡 场景)中使用的元素.在我们的例子中,游戏角色元素至少需要一个 AnimatedSprite 节点.该节点包含各种动画(例如,行走动画)所需的精灵纹理.

  1. 一个用于敌人的场景.

敌人也是我们想在多个场景中使用的元素.它与 Player 节点几乎相同.唯一的区别是脚本(需要 AI 程序来生成敌人的行为)和 AnimatedSprite 节点使用的精灵纹理不同.

  1. 一个关卡场景.

关卡场景由砖块(用于平台),硬币(供玩家收集)和敌人场景的多个实例组成.每个实例都是关卡场景树中的一个节点.这些实例是单独的敌人,最初具有在敌人场景中定义的共同行为和外观.您可以为每个敌人节点设置不同的属性(例如,更改其颜色).

4. A Main scene. The Main scene would be composed of one root node with 2 children: a Player instance node, and a Level instance node. The root node can be anything, generally a “root” type such as “Node” which is the most global type, or “Node2D” (root type of all 2D-related nodes), “Spatial” (root type of all 3D-related nodes) or “Control” (root type of all GUI-related nodes).

如您所见,每个场景都被组织成一棵树.节点的属性也是如此:您不会像Unity那样向节点 添加 一个碰撞组件以使其可碰撞.相反,您可以使该节点创建一个 子级 节点,即具有碰撞属性的新特定节点 .Godot根据用途使用各种碰撞类型节点(请参阅 物理介绍).

  • 该系统的优点是什么?这个系统不会增加场景树的深度吗?而且Unity是否还是不允许您通过将游戏对象放到空的游戏对象中来组织游戏对象?

    • Godot的系统更接近众所周知的面向对象的范例:Godot提供了许多不明确的”游戏对象”节点,但它们为子节点提供了自己的功能:这就是继承.

    • Godot允许抽取一个场景的子树以使其成为它自己的场景.因此,如果场景树变得过深,则可以将其拆分为较小的子树.这对于可重用性来说也很好,因为您可以将任何子树作为子级包含在其他任何节点中.在Unity中,将多个 GameObject 放入空 GameObject 中不会提供相同的功能.

项目组织

../../_images/unity-project-organization-example.png

没有完美的项目架构.任何架构都可以在Unity和Godot中使用.

但是,Unity项目的通用架构是在根目录中有一个 Assets 文件夹,其中包含各种文件夹,每种素材类型有一个文件夹:音频(Audio)、图形(Graphics)、模型(Models)、材质(Materials)、脚本(Scripts)、场景(Scenes)等.

由于Godot允许将场景拆分为较小的场景,在项目中,每个场景和子场景都作为文件存在,因此我们建议对项目进行一些不同的组织.该手册为此提供了一个页面: 项目组织.

我的预制体在哪里?

Unity提供的预制件是场景的 模板 元素.它是可重复使用的,并且场景中存在的预制体的每个实例都有其自己的存在,但所有它们都具有与预制体所定义的相同的属性.

Godot本身不提供预制件,但其场景系统提供了相同的功能:场景系统组织为一棵树.Godot允许您将场景的任何子树保存为一个场景文件.然后,可以将这个新场景作为任意节点的子节点实例化任意多次.您对此新的独立场景所做的任何更改都将应用于其实例.但是,您对实例所做的任何更改都不会对 模板 场景产生任何影响.

../../_images/save-branch-as-scene.png

确切地说,您可以在属性检查器面板中修改实例的参数.组成此实例的节点最初被锁定.如果需要,可以通过右键点击场景树中的实例并在菜单中选择 可编辑子代 来解锁它们.您无需执行此操作即可向该节点添加 新的 子节点.请记住,任何新的子项都将属于该实例,而不是磁盘上的 模板 场景.如果要将新的子项添加到 模板 场景的每个实例,则应将在 模板 场景中添加.

../../_images/editable-children.png

术语对应

  • 游戏对象(GameObject) -> 节点(Node)

  • 添加组件(Add a component) -> 继承(Inheriting)

  • 预制件(Prefab) -> 可重用的场景文件(Reusable Scene file)

编写脚本:GDScript、C# 和 Visual Script

设计

Unity支持C#.C#受益于它与Visual Studio的集成,并具有理想的功能,例如静态类型.

Godot提供了自己的脚本语言, GDScript,以及对 Visual ScriptC# 的支持.GDScript虽然从 Python 中借用了它的语法,但与它无关.如果您想了解自定义脚本语言的原因,请阅读 GDScript 基础常见问题 页面.GDScript与Godot API紧密相连,无需花太多时间即可学习:一个经验丰富的程序员的一个晚上、一个完全的初学者的一周时间,即可学会.

Unity允许您将任意数量的脚本附加到 GameObject 上.每个脚本都会向 GameObject 添加一个行为:例如,您可以附加一个脚本,使其对玩家的控制做出反应,而另一个脚本则控制其特定的游戏逻辑.

在Godot中,每个节点只能附加一个脚本.您可以使用外部GDScript文件,也可以将脚本直接包含在节点中.如果需要将更多脚本附加到一个节点,则可以根据场景和要实现的目标考虑两种解决方案:

  • 在目标节点与其当前父节点之间添加一个新节点,然后向该新节点添加脚本.

  • 或者,您可以将目标节点拆分为多个子节点,并在每个子节点上附加一个脚本.

如您所见,将场景树变成一团糟很容易.考虑将任何复杂的场景分为多个较小的分支.

连接:编组和信号

您可以通过脚本访问节点以及在其上调用内置或用户定义的函数来控制节点.您还可以将节点放在一个编组中,并在该编组中的所有节点上调用函数.有关更多信息,请参见 脚本文档.

发生指定的操作时,节点可以发送信号.可以设置信号来调用任何函数.您可以定义自定义信号并指定触发它们的时间.请参阅 信号文档 中的更多内容.

脚本序列化

Unity可以通过两种方式处理脚本序列化:

  • 隐式:如果类型是可序列化的类型(Dictionary 不可序列化),则类中的所有公共字段都会自动进行序列化.

  • 显式:可以使用 [SerializeField] 属性来序列化非公共字段.

Godot也具有内置脚本序列化系统,,但它仅显式工作.您可以使用 export 关键字序列化任何可序列化的类型( 内置和各种引擎类型,包括 ArrayDictionary).有关详细信息,请参见 导出器文档.

Unity还具有一个名为 ScriptableObject 的数据类型,用于序列化自定义素材对象.它在Godot中的等效项是所有资源的基类: Resource.创建一个继承了 Resource 的脚本,将允许您创建自定义的可序列化对象.有关资源的更多信息,请参见 这里.

在 Godot 中使用 C++

Godot允许您使用其API直接使用C++开发项目,而这在Unity中目前是不可能的.例如,您可以将Godot引擎的编辑器视为使用Godot API用C++编写的 游戏.

如果您对使用Godot时使用C++感兴趣,您可能想要开始阅读 用C++开发 页面.