GameStart

5.2k words

特性

渲染顺序

alt text


GD Script

if & for

if

if

1
2
3
4
5
6
if a == 12:
# action
elif a == 24:
# action
else:
# action

match

1
2
3
4
5
6
7
8
9
match unit_aligment:
Alignment.ALLY:
print("Hello, friend!")
Alignment.NEUTRAL:
print("I come in piece!")
Alignment.ENEMY:
print("TSATE MY WRATH!")
_:
print("Who art thou")

类似witch,但是不用break

for
1
2
for item in items:
# action
1
2
for i in 8:
# action
1
2
3
4
5
6
var glass = 0.0
while glass < 0.5:
glass += randf_range(0.01, 0.2)
print(glass)

print("The glass is now half full!")

跳出
break & continue


声明变量

显式声明变量的类型(之后无法更改)

下面两个声明效果一样,使用:=为推断类型,自动确定数据类型

1
2
var damage: int = 15
var damage2 := 15
@export - 将变量暴露给检查器
1
@export var damage := 15

此时设置的值为默认值,可以在检查器中更改

常量
1
const GRAVITY = -9.81

枚举Enums

1
2
3
4
5
6
7
8
9
10
11
12
13
enum Alignment {
ALLY,
NEUTRAL,
ENEMY,
}

var unit_aligment = Alignment.ALLY

func _ready() -> void:
if unit_aligment == Alignment.ENEMY:
print("You are not welcome here.")
else:
print("Welcome.")

在枚举中使用@export

1
@export var unit_aligment: Alignment

alt text

自定义枚举的值

1
2
3
4
5
enum Alignment {
ALLY = 1,
NEUTRAL = 0,
ENEMY = -1,
}

函数Func

一个具有输入输出的函数
1
2
3
4
5
6
7
func _ready() -> void:
var result = add(6, 8)
print(result)

func add(num1, num2):
var result = num1 + num2
return result
指定参数类型,返回类型
1
2
3
func add(num1: int, num2: int) -> int:
var result = num1 + num2
return result

常用函数

randf()

返回 0.0~1.0(包含) 的随机浮点数

1
2
3
4
5
6
7
func _ready() -> void:
var roll = randf()
print(roll) # 例 0.82803469896317
if roll <= 0.8:
print("You found a COMMON item.")
else:
print("You found a RARE item!!")
randi_range() & randf_range()

返回指定范围的随机数 (整数 & 浮点数)

1
2
3
4
5
func _ready() -> void:
var character_height = randi_range(100, 210)
print("Your character is " + str(character_height) + "cm tall.")
var character_power = randf_range(0.0, 15.0)
print("Your character power: " + str(character_power))

常见数据结构

Vector2 & Vector3
1
2
3
4
5
var position2D = Vector2(6, -2)
print(position2D) # (6, -2)
var position3D = Vector3(-5, 9, 6)
position3D.z += 2 # (-5, 9, 8)
print(position3D)
数组Array
1
var items = ["Potion", 3, 6.8]

可以放置不同数据类型

指定类型

1
2
3
4
5
6
7
8
var items: Array[String] = ["Potion", "Feather", "Stolen harp"]
print(items[1]) # Feather

items[1] = "Staff"
items.remove_at(2)
items.append("Overpowered sword")

print(items) # ["Potion", "Staff", "Overpowered sword"]
字典Dict
1
2
3
4
5
6
7
8
9
10
11
12
var players = {
"Crook": {"Level": 1, "Health": 80},
"Villain": {"Level": 50, "Health": 150},
"Boss": {"Level": 100, "Health": 500},
}

for username in players:
print(username + ": Level: " + str(players[username]["Level"]))

# Crook: Level: 1
# Villain: Level: 50
# Boss: Level: 100

访问节点

使用路径访问

拖放

1
$Player/Weapon

节点路径引用

$Player/Weapon = get_node(“Player/Weapon”)

ctrl拖放

1
@onready var weapon: Sprite2D = $Player/Weapon

节点路径引用,同时创建变量

@onready确保所有子节点被创建完再访问

一般在访问子节点时使用路径

使用@export访问
1
@export var my_node: Node

alt text

信号Signal

通知发生了某个事件

查看信号的来源与目标
alt text

事件发生的源头 → 事件本身 → 要通知的目标

使用信号来连接不同的模块

例如角色升级发送信号给UI模块改变显示,
成就模块解锁成就,角色背包模块获得道具…

节点自带信号

节点界面选择连接
alt text

自定义信号
  1. 声明信号

    1
    signal leveled_up
  2. 使用代码连接/界面连接

    1
    signal.connect(method_name)
    1
    signal.disconnect(method_name)
  3. 发送信号

    1
    signal.emit()
带参数的信号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
signal leveled_up(msg)

var xp := 0

func _ready() -> void:
leveled_up.connect(_on_leveled_up)

func _on_timer_timeout() -> void:
xp += 5
print(xp)
if xp >= 20:
xp = 0
leveled_up.emit("GZ!")

func _on_leveled_up(msg) -> void:
print(msg)

在经验值达到20的时候发送升级的信号leveled_up
附带一条消息msg

自定义变量的get & set

生命值改变

1
2
3
4
5
6
7
8
9
10
11
12
signal health_change(new_health)

var health:= 100:
set(value):
health = clamp(value, 0, 100)
health_change.emit(health)

func _ready() -> void:
health = -150

func _on_health_change(new_health: Variant) -> void:
print(new_health)

自定义set()

  • 使用clamp()限制了生命值的赋值范围
  • 同时发送生命值改变的信号health_change

机会百分比转换

1
2
3
4
5
6
7
8
9
10
11
12
var chance:= 0.2
var chance_pct: int:
get:
return chance * 100
set(value):
chance = float(value) / 100.0

func _ready() -> void:
print("---chance_pct test---")
print(chance_pct)
chance_pct = 60
print(chance)
  • chance_pct 为 chance 的百分比显示,自定get和set进行转换
getter/setter不会被调用的情况
  • 变量在进行初始化时
  • 在一个变量的 setter 函数和 getter 函数内访问 该变量的变量名

类Class

1
2
3
4
5
6
7
8
9
10
class_name Character

extends Node

@export var profession: String
@export var health: int

func die():
health = 0
print(profession + " died.")
  • 使用class_name指定类名
  • 给类的属性加上@export便于修改

当我们新建一个类时,也相当于新建了一个我们自己的节点
alt text

内部类Inner Class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class_name Character

extends Node

@export var profession: String
@export var health: int
var chest := Equipment.new() # 胸甲
var legs := Equipment.new() # 腿甲

func _ready() -> void:
chest.armor = 50
print(chest.armor)
print(legs.weight)

func die():
health = 0
print(profession + " died.")

class Equipment:
var armor := 10 # 护甲值
var weight := 5 # 重量

EquipmentCharacter的内部类
Character里使用Equipment.new()创建Equipment实例

使用GD Script时的一些良好习惯/规范

  • 节点间通信:Call down, Signal up

    父节点调用子节点函数,子节点发送信号给父节点
    兄弟节点间通信,由父节点将其中一个兄弟节点发出的信号连接到另一个兄弟节点的函数上(这通常在_ready()函数中完成)

官方指南

常用节点

Resource
  • 数据容器
  • 游戏资源文件与游戏程序的中转站(下载的资源文件 -> 转为Resource对象 -> 被节点使用)
  • 继承自RefCounted,引用计数器归零时,资源被释放
  • 引擎从磁盘加载资源时, 它只加载一次

复制节点时,记得对节点使用的资源进行唯一化处理,因为复制后两个节点使用的是同一资源对象

加载Resource

  • load()
    使用变量,可以动态/可变的路径加载资源,从磁盘加载无引用的资源时,可能会导致延迟,此时可以使用preload(),或是将资源存储在变量中
  • preload()
    运行时,资源将在解析脚本时加载,无法使用变量作为动态路径

常用函数

访问节点
get_node()

通过节点路径访问

get_child()

通过节点索引(0,1,2…,-1)访问子节点

get_parent()

访问父节点

get_children()

获取包含所有直接子节点的数组

常用内置单例

官方文档

节点帮助文档

alt text

alt text

快速进入当前节点文档

alt text

全局范围的常量和函数,内置对象

alt text

内置 GDScript 常量、函数、注解。

alt text

常用快捷键

F 聚焦
ctrl + A 添加节点
按住Alt 移动当前/选中行代码