囿里有条小咸鱼 发表于 2023-2-24 13:09:49

Godot 4.X —— 从入门到入门(对比3.X版本的对比学习帖)

本帖最后由 电童·Isamo 于 2023-5-26 21:42 编辑

随着Godot 4.X的到来,Godot也步入了一个全新的时代,而随之而来的则是一大堆新的变化、新的GDScript语法以及新的界面。
本贴会对比该贴来对4.X版本起发生的变化进行一个较为详细的说明。
如果你想从0开始直接入坑4.0,那么本人推荐先点击上面的蓝字去先学习3.X的基础知识,然后在学习完每一章后再拐回来看本帖学习4.X的使用方法。

接下来是本贴的目录,其中绿字表示已经完成的部分,带“-X”的表示其后面表示上方蓝字所指向的帖子的对应章节序号X

[*]序言 —— Godot 4是个啥玩意儿?
[*]节点类大更名 - 2
[*]GDScript 2.0基础语法一:基本变化、枚举作为类型 - 4、5
[*]GDScript 2.0基础语法二:函数类Callable和信号类Signal - 6、8
[*]GDScript 2.0基础语法三:注解与导出 - 5、7、13
[*]GDScript 2.0基础语法四:set函数和get函数 - 11
[*]GDScript 2.0基础语法五:静态类型数组 - 9
[*]GDScript 2.0高级语法一:await取代yield - 18
[*]GDScript 2.0高级语法二:为自动api提供注释
[*]GDScript 2.0高级语法三:全面静态类——静态成员变量 - 4、24

囿里有条小咸鱼 发表于 2023-2-24 13:33:34

本帖最后由 电童·Isamo 于 2023-5-26 21:44 编辑

序言 —— Godot 4是个啥玩意儿?
北京时间2023年3月1日晚,Godot终于发布了4.0的stable版本,标志着Godot 4的全面问世与Godot引擎的跨时代重磅更新。如果你已经看过1L蓝字的帖子开头关于Godot的说明,那么我可以这么形容Godot 4:它可以说是Godot 3引擎的升级,但又与Godot 3是两个完全不同的引擎。之所以说Godot 4还是Godot系列的引擎,这明显是废话了,毕竟还是那个团队开发的,而且内容上大部分也跟Godot 3保持一致。但说它跟Godot 3又是俩完全的不同的引擎,是因为Godot 4有着跟Godot 3几乎完全不同的背景,最主要的是:Godot 4的更新非常巨大,几乎是跨越式、破坏式的更新,导致其工程文件不向下兼容,同时,Godot 3的工程到Godot 4还要经过自动+人工的转化后才能用,这就导致这两个引擎出现了迭代裂痕。

[*]Godot 4的起源
关于Godot 4到底是因何产生的,我暂时无法得到确切的考证,但这张图,却说明了一个很有意思的情况:https://s1.ax1x.com/2023/02/24/pSzlBh4.png这就是官方4.0最早的版本,也就是pre-alpha版本,它最早出现于2021年7月,而我们看看3.3.3版本的发布日期:https://s1.ax1x.com/2023/02/24/pSzlhND.png
现在的最新版本是3.5.1(未来3.X版本最多更新到3.6.X),但很有意思的是:3.X还没更完,就出现了4.0的版本,有人可能会说了:这也没啥啊!欸,一般的人可不会这么觉得,按照正常的思路,不应该是到结束大版本更新以后停更一段时间然后出新版本嘛?为什么官方在3.X还没结束的时候就已经在准备4.0了呢?这就要扯到4.0的诞生的目的了。
(注:以下大部分均为个人臆测,但有可能为官方的真实想法,仅供参考)目前最可靠的流传,说是官方的开发团队当时开发了Godot 3之后,为了追寻更高性能的渲染,看中了Vulkan管线(性能卓越的渲染管线,旨在替代OpenGL),当时官方的打算是:将用Vulkan渲染管线的Godot 3版本更号为Godot 4。你认为仅此而已吗?那是绝对不可能的(虽然官方刚开始对Godot 4的定位就是“Vulkan版的Godot 3”,但现实不停膨胀的需求让他们意识到:仅仅是将Godot的渲染管线替换为Vulkan那是不可能的,还需要适应更加现代化的需求。因此,Godot 4开始逐渐脱离原本的“Vulkan版Godot 3”的定位,开始探索适合自己发展的道路:
[*]官方团队对Godot 4的外观进行了调整,使得原本的UI更加现代化。
[*]官方还针对更加膨胀的3D需求下了狠功夫,现在3D功能更加强大。
[*]官方对Godot所使用的GDScript进行了升级,对部分繁琐的语法进行了更加人性化、python化的调整,大大提高了开发者的编写效率。
[*]官方还对Godot 3的不足进行了提升,在Godot 4内得以实现。
[*]由于大量的内容更新,Godot 4的文件大小已经不再像Godot 3那么轻便了,光是软件本体现在就需要100MB,足足翻了一倍

直到2022年初,官方才发布了4.0的第一个alpha版本。然而,受疫情影响,加上开发道路上的各种bug层出不穷,原计划去年发布的4.0正式版却要推迟到本月末发布。不过如今,我们终于可以使用4.0版本的Godot了。


[*]Godot 4对2D开发的影响
由于更换为了Vulkan管线,Godot 4对2D渲染的效率肯定是大大提升的,尤其是对于性能偏下等但支持Vulkan的的机子来说,Vulkan的出现算是它们的救命稻草。同时,对于2D节点,Godot 4也对它们在检查器列表中的表现进行了强化,使得原本一些不能在检查器里修改的属性现在可以直接在检查器中修改了。但刚刚也说了,4.0还是走出了属于自己的道路,这其中就包括对2D节点的属性进行的更改,包括但不限于更名与重写方法。因此相较于Godot 3,Godot 4的2D开发可能会对我们已经熟悉了3的操作来说的开发者来说还是有些挑战的。


[*]Vulkan管线对Godot 4的影响
前面提到,vulkan管线的引入,可以说是Godot 4最核心的一个升级,它不但为Godot 4提供了更卓越的渲染性能,还让Godot 4更加适应现代化的需求。但是,vulkan还是新兴管线,对于那些还不支持vulkan管线的老电脑用户来说,用Godot 4导出的游戏是望尘莫及的。不过官方也很用心,考虑到了这一点,于是在后来的某4.0alpha版本中新增了对OpenGL ES3(也就是Godot 3中的GLES3)的回滚支持,这一引入使得开发者能够导出兼容OpenGL渲染管线的作品,照顾那些还不能使用vulkan管线的老电脑用户。


总之,Godot 4就是这么一个玩意儿——它继承了Godot 3的优点,同时又对Godot 3中的缺陷进行了弥补。但因为走出了属于自己的路,导致与Godot 3无法完美衔接。
但不论如何,学习Godot 4的道路还是要以学习Godot 3的道路为基石的。因此,如果你需要从0开始学习Godot 4,不妨先学习1L蓝字链接所指向的帖子里的基础内容,然后拐回来学习Godot 4的新内容

囿里有条小咸鱼 发表于 2023-2-24 13:57:20

本帖最后由 囿里有条小咸鱼 于 2024-2-12 16:35 编辑

节点类大更名Godot 4中最重要的更新,便是对Godot 3中的一大堆节点的名称进行了更新,本贴会列出那些已经发生变化的节点,以及Godot 4中新加入的节点。不涉及到2D开发的节点,在本贴中均只简单进行介绍。


[*]节点列表大更新
https://s1.ax1x.com/2023/02/24/pSz356A.png
- Viewport
首先,Godot 4中场景元根节点root现在不属于Viewport类,因为现在Viewport类属于抽象类,无法实例化。Godot 4中,root元根节点现在属于4.0新加入的Window类。原来的Viewport类现在要通过SubViewport类来实现

- Node2D和Node3D
针对原来2D、3D节点命名的混乱,Godot 4对其进行了命名校正,原来负责3D的Spatial节点现在更名为Node3D节点,其下面所有节点现在大部分均附带3D后缀名,而不再像Godot 3的3D那样无后缀名标识。原来负责2D的Node2D节点保持原名称不变,其下的节点发生如下变化:

[*]隶属于PhysicsBody2D的KinematicBody2D节点现在更名为CharacterBody2D节点(更详细的变化我们日后再讲)
[*]StaticBody2D现在新增扩展类AnimatedBody2D,用于制作平台等物体,需要AnimationPlayer节点操作
[*]新增CanvasGroup节点,将多个2D节点放置在同一绘制处理过程中
[*]Light2D现在作为不可应用类,无法在节点树上手动实现。原来的Light2D现在作为其子类PointLight2D,同时对Light2D新增子类DirectionalLight2D
[*]原来的Position2D节点现在更名为Marker2D
[*]ParallexLayer节点更换图标
[*]新增ShapeCast2D节点,类似于Raycast2D节点,但采用形状位移来检测碰撞,部分情况下可以替代Area2D使用(会在3.6版本中回滚添加这一节点)
[*]Sprite和AnimatedSprite节点现在均附带2D后缀名
[*]VisibilityNotifier和VisibilityEnabler均改名为VisibleOnScreenNotifier和VisibleOnScreenEnabler(这条视情况再追加2D/3D后缀名)

- Multiplayer相关
Godot 4新增对Multiplayer游戏的快捷支持,新增了MultiplayerSpawner和MultiplayerSynchronizer这两个节点,有关这两个节点的使用可以前往官网这篇文章学习

- Tween
Tween不再作为节点使用,与Godot 3.5新增的SceneTreeTween融并为引用计数对象


[*]影响
对我们开发2D游戏的而言,影响最大的莫过于部分节点的更名和类型更改。因此,在将Godot 3的工程迁移到Godot 4的时候,如果内置conventer未能将这些类进行转化,请务必手动对其进行更改。

囿里有条小咸鱼 发表于 2023-2-24 15:18:11

本帖最后由 电童·Isamo 于 2023-2-24 16:46 编辑

GDScript 2.0基础语法一:基本变化、枚举作为类型要说到Godot 4最大的更新,莫过于对GDScript语法的升级,从本章开始,我们向各位同学介绍Godot4.0中GDScript所发生的变化,以及如何在4.0中适应这些变化


[*]界面的变化与功能的升级
首先,序章里已经提到了,Godot 4的UI发生了很大变化,其中也包括我们在编写GDScript时所使用的字体的变化。下面两张图就对比了Godot 3和Godot 4所使用的两个不同的代码字体:
Godot 3:
https://s1.ax1x.com/2023/02/24/pSzYr9O.png
Godot 4:
https://s1.ax1x.com/2023/02/24/pSzYs3D.png
其次,Godot 4对一些运算符进行了现代化处理,当你输入某些运算符时,他就会显示成另外的样子:
比如,同样是“!=”运算,在Godot 4中默认显示为https://s1.ax1x.com/2023/02/24/pSzYIC8.png,但你可以通过
https://s1.ax1x.com/2023/02/24/pSztbRO.png
将这个"!="表示成https://s1.ax1x.com/2023/02/24/pSztXsH.png
虽然对看不懂代码运算符或者厌烦了固有的代码运算符的开发者来说是个福音,但是对于看习惯了老式运算符的开发者来说可能还难以接受。因此官方做成了可选项,且默认关闭。
其次,Godot 4中对每个自定义的类实现了内置API,不论是否是具名类
比如我现在这个例子:
https://s1.ax1x.com/2023/02/24/pSzNewn.png
那么我可以在https://s1.ax1x.com/2023/02/24/pSzNMWT.png中输入我这个类的文件名(如果不是具名类),或者这个类的类名(如果是具名类)
https://s1.ax1x.com/2023/02/24/pSzNtT1.png
然后双击它打开,就可以看到你所写的脚本的的内置API了
https://s1.ax1x.com/2023/02/24/pSzNcTI.png
有关如何编写这种API,我们会在本贴后面的章节中学习。


[*]continue关键字的战略性失能
Godot 4中另外一个值得我们注意的就是match分支条件句中continue关键字不再用于跳出分支条件判断。
在Godot 3中,我们可以这样写以屏蔽掉一些二级条件:
var a: int
var b: int = -1

func somefunc() -> void:
      match a:
                1:
                        if b < 0: continue
                        print("hehe")
                2:
                        print("whoooho")
      print("done")然而在Godot 4中,分支条件句里不再支持continue关键字进行跳出判断。因此,你需要这样写:
var a: int
var b: int = -1

func somefunc() -> void:
      match a:
                1:
                        if b >= 0:
                              print("hehe")
                        else:
                              <do_something>
                2:
                        print("whoooho")
      print("done")但是这个失能(可能)仅限于4.0,因为官方表示会在4.1版本中对分支条件句进行优化,continue关键字或将回归,那就让我们一同期待吧。


[*]枚举作为类型使用
GDScript 2.0中支持将枚举直接作为类型使用,这项改动不仅仅是GDScript 2.0对编程语言严谨性的提升,同时也是为后面注解的引入做出的便利
在Godot 3的时候,我们都是这样用枚举的:
enum Dir {LEFT = -1, RIGHT = 1}

var direction: int = Dir.LEFT现在我们可以直接这样写:
enum Dir {LEFT = -1, RIGHT = 1}

var direction: Dir = Dir.LEFT # 直接将枚举名称作为类型限定数值量这样写有两个好处:

[*]严格限定该变量的范围,防止改变量被误赋值为其他不合规数值。如果在编辑器里给以枚举为类型的变量输入了不合规数值,则编辑器会弹出警告。
[*]提醒开发者:这是个枚举引申。
缺点也是有的:如果不进行类型转换,则编辑器会弹出警告。

接下来我们会讲到的导出注解,也可以用这种方法来实现Godot 3的枚举导出

囿里有条小咸鱼 发表于 2023-2-24 15:41:24

本帖最后由 电童·Isamo 于 2023-7-7 18:10 编辑

GDScript 2.0基础语法二:函数类Callable和信号类SignalGodot 4中另外一个非常重要的更新便是将函数和信号均抽象为了类使用,这也是出于对语法安全性和语法严谨性的考量而设计的。


[*]Callable类
我们说调用函数,其在英文中的表达就是call a function,call的意思就是“调用”,那么"callable"的意思就是“可调用的”,这里的可调用的东西不就是指函数(方法)么。因此,函数的类名为Callable
也就是说,在Godot 4中,我们有两种声明函数的方法:
# Godot 3 样式的声明方法
func somefunc() -> void:
      pass

func withparam(par1,par2) -> void:
      pass

# Godot 4 中新的声明函数的方法
var somefuncnew: Callable = func() -> void:
      pass

var withparamnew: Callable = func(par1, par2) -> void:
      pass
正如大家所见,既然都可以作为类使用了,那我为啥不把函数当成变量来用呢?像这样,将函数当作变量使用,函数名作为变量名,这样的表达函数的方法就叫做匿名函数(Lambda function,也叫做lambda表达式)
既然都可以用变量来声明函数了,那么我们马上就能想到的那当然是在函数里声明子函数了((
func somefunc() -> void:
      var subfunc: Callable = func() -> void:
                <do_something>
      <do_something>如果要调用匿名函数,只需要输入匿名函数的变量名(也就是这个匿名函数的函数名),然后输入".call()"就可以了
func somefunc() -> void:
      var subfunc: Callable = func() -> void:
                <do_something>
      subfunc.call() # 调用上面的匿名函数当然,对于所有函数来说,都可以用函数名.call()/.call_deferred()的形式来调用:
func somefunc() -> void:
      print("I'm somefunc")

func _ready() -> void:
      somefunc.call()对于带参数的匿名函数,我们有两种方法:

[*]在call()/call_deferred()的括号内输入对应参数值
[*]在调用call()/call_deferred()之前,输入".bind()",在bind()的括号内输入对应数值,然后再将.call()/.call_deferred()写在后面
比如下面这个例子
func add(a,b) -> void:
      print(a + b)

func _ready() -> void:
      add.call(1,2)
      add.bind(1,2).call()当然,在Godot 3中,我们用FuncRef来指向一个函数,并用funcref来将被指向函数作为参数传入其他函数中。在Godot 4中,有了Callable,就不需要指向函数这个操作了,我们直接将对应函数名输入作为参数即可
func call_function(function: Callable) -> void:
      print(function.get_method())

func somefunc() -> void:
      pass

func _ready() -> void:
      call_function(somefunc)
      # 注:如果在函数名后面加了括号,则表示调用该函数,使用的是该函数的返回结果
      # 如果不加括号,则是将函数作为Callable变量进行引用和传参一定要注意注释中所说的话!
在Godot 4中,每个函数都是Callable类的变量,因此,我们可以在需要传入Callable的地方直接输入匿名函数:
func call_function(function: Callable) -> void:
      print(function.get_method())

func _ready() -> void:
      call_function(func() -> void:
                pass
)
注:实际上Callable类是Godot 3中FuncRef类的升级,因此在Godot 4中FuncRef类被Callable类完全取代。如果你在1L那个教程中已经学习了FuncRef,请务必注意将FuncRef改写成Callable类的形式!

[*]Signal类
除了Callable类,Godot 4中还将信号也抽象成了一个类——Signal。
以前我们在发射信号的时候是这样写的:
emit_signal("signal_name", )4.0中当信号作为Signal类使用后,我们就可以这样写:
some_signal.emit(params...)这样写有两个好处:

[*]使代码编写更为严谨安全,防止出现字符串找不到对应函数而出错的情况
[*]支持快速补全,减少函数参数,大大提升代码编写效率
类似的,连接信号也是以some_signal.connect(object.func_name)的形式来实现的
下面这个就是在Godot 4中连接ready信号到自身方法的例子:
func _ready() -> void:
      ready.connect(_on_ready) # 如果直接加函数名则默认是该对象自身的函数

func _on_ready() -> void:
      print("Ready!")其他跟signal有关的函数也是同理。
当然你说以前的emit_signal还能不能用,确实可以用,但是它的用法也发生了变化……
emit_signal(name: StringName, method: Callable)其中StringName是4.0中新增的字符串类型,你可以认为是String。
对于信号连接带参函数的操作,我们可以借助Callable中的bind()方法来实现:
func _ready() -> void:
      ready.connect(_on_ready.bind(3,4))

func _on_ready(par1,par2) -> void:
      print("Ready!")对于Godot 3中无法给带参信号限定类型这个问题,在Godot 4中得以解决
signal some_signal(par1: int, par2: float) # Godot 4中允许这么做了同时,对于带参信号的参数数目多于目标函数的参数个数导致无法连接的问题,Godot 4给Callable类一个名叫unbind(n: int)的方法,当信号要传入该函数时,该函数会将最后n个参数屏蔽掉,比如下面这个例子
signal my_signal(par1, par2)

func somefunc(par1) -> void:
      print(par1)

func _ready() -> void:
      my_signal.connect(somefunc.unbind(1))
      my_signal.emit(1,2)
      # 传入参数时,par2不会被传入somefunc()中,只有par1会被传入上面这个例子中somefunc调用了Callable类的函数unbind(),输入参数1,将该信号的最后一个参数par2屏蔽掉


以上就是有关Godot 4中函数类Callable和信号类Signal的主要用法。

囿里有条小咸鱼 发表于 2023-3-7 23:55:47

本帖最后由 电童·Isamo 于 2023-6-16 12:49 编辑

GDScript 2.0基础语法三:注解与导出
我们在学习Godot 3的时候曾经学过导出的语法、onready关键字语法和tool脚本,他们在GDScript 1.0时代都以关键字的形式存在
然而在Godot 4中,他们却变成了一个全新的编程结构:注解(Annotation)


[*]何为注解?
注解是编程语言中的一种语法结构,通过这种结构来改变其后面的代码的行为。在Godot 4中,注解以“@”符号开头,即Godot 3中作为NodePath的符号。在Godot 4中,你需要用 ^"" 来声明一个NodePath,而非 @""
在Godot 4中,注解分为成员注解、类注解和忽略警告注解这三大类,其中,导出注解作为成员注解中的一种,其数目最多


[*]注解的特性
在Godot 4中,注解具有以下特性:

[*]跨行修饰性:不同于关键字,在Godot 4中,注解可以对其下一行的代码进行修饰:@export var a: int= 1
# 等价于
@export
var a: int = 1
[*]联并修饰性:不同于部分关键字,在Godot 4中,一些注解可以同时作用在一条代码上,也就是说,一个代码可以拥有多个注解进行修饰:@onready @export var a = 1 # 在Godot 3中,onready和export是不可以同时作用于var上的,但是在Godot 4中,注解的机制允许你这么写了
# 虽然理论上这种写法是可以的,但Godot 4会默认这是个错误写法,并会弹出报错。但这个错误并不影响你的工程运行,且你可以手动关掉这个报错。



[*]注解——导出注解
在Godot 3所处的GDScript 1.0的时代,我们要导出一个变量需要export关键字,而在GDScript 2.0中,我们的export关键字变成了注解@export。
# Godot 3:
export var a = 1
# Godot 4
@export var a = 1同时,在Godot 4中也原生支持用注解直接进行高级导出操作,这些注解均以@export_开头
页: [1]
查看完整版本: Godot 4.X —— 从入门到入门(对比3.X版本的对比学习帖)