跳转到内容

GDCC 0.0.3 发布:更完整的 GDScript 语义、更完整的使用体验

返回博客

GDCC 是一个将 GDScript 编译为 GDExtension 本机二进制库的编译器。从 0.0.2 到 0.0.3,我们花了4个月,40个PR的更改之后, 我们有了一个语义更完整、使用更舒适的 GDCC。以下是我们所作的更改:

更可靠的对象语义

我们把类型系统的地基从头重写了一遍。is / is not 类型判断、as 类型转换、对象 == 判等、for-in 遍历、range() 迭代,现在全部按 GDScript 语义工作。

对于 if body is CharacterBody2D、for child in get_children() 这类 GDScript 里的日常写法,此前,在 GDCC 里要么编译失败,要么行为与解释器不一致。 在我们“艰苦卓绝”的努力下,对象值内部表示被重新设计,类型身份与所有权生命周期一并被纳入管理。 现在 GDCC 编译器中它们直接通过编译,且行为与解释器完全一致。这意味着大量真实游戏代码中的类型分派与容器遍历不再需要改写。

Lambda 与 Callable

匿名函数、闭包捕获、方法引用、把函数当值传递等等这些对于 Godot 而言极为重要的特性,现已全部可用~

button.pressed.connect(func(): print("clicked"))
array.sort_custom(func(a, b): return a.hp < b.hp)
var cb := Callable(self, "_on_timeout")

常见的 connect 一个 lambda、sort_custom 传一个比较函数、把 Callable 存起来稍后调用等 GDScript 里的高频写法已经全部支持。 在 0.0.3 中,UI 事件绑定、回调式 API 不再受限。

协程、信号与异步流程

这个版本中 GDCC 最大的语义更新,那可就莫过于 await 与自定义 signal 了。 现在,协程可以跨帧挂起与恢复,信号可以声明、发射、连接,也可以直接 await:

signal health_depleted
func _ready() -> void:
await get_tree().create_timer(1.0).timeout
health_depleted.emit()
func _on_boss_fight() -> void:
await health_depleted
play_game_over()

等动画播完再走下一段逻辑、等资源加载完成、按钮点击异步响应、技能冷却与时序控制——涉及时序的游戏逻辑现在用 GDScript 原生写法即可表达。

热重载

要让使用 GDCC 就像你现在使用 Godot 中内置的解释器一样,如呼吸般自然,那改完代码不用重启编辑器这个功能就是必不可少的啦~

在编辑器里点击 Build 按钮,编译完成后动态库会被自动部署并热重载,你不需要重启 Godot 编辑器、也不需要重载场景,场景中已建立的信号连接与 Callable 会自动指向新代码。

调参数、改 UI、修 Bug 的 “修改—构建—验证” 循环也正是因此变得飞起。 配合下一节的编译提速,从点击 Build 到热重载完成不超过 1 秒,开发迭代节奏追平原生 GDScript。

其他语言特性

本版本还落地了一批语言特性,按用途归类如下:

  • 类型与声明:enum、static var、@tool / @export 注解。
  • 函数与调用:参数默认值、super(...) 父类调用、虚函数多态。
  • 表达式:字符串 % 格式化、三元表达式、not in、NodePath 字面量与 $Node 简写。
  • 数据与内建:PackedArray 引用语义、容器字面量、assert、load / preload、全局常量直访、match 模式匹配。

至此,GDScript 的常用语义在 GDCC 下接近完整。

并行构建

在 0.0.3 以前,GDCC 原生库的构建流程是单线串行的。现在我们将多个翻译单元分发到所有可用的 CPU 核心并行编译,最后统一链接:

GDCC 并行构建示意图

上图以 GDCC 一次真实的模块构建为例:5 个翻译单元在 4 个核心上同时开工。 更关键的是,引擎绑定、协程与热重载运行时这些不随脚本变化的单元在二次构建时直接命中缓存、不用再重新去编译了,这意味着日常迭代中真正需要编译的只有脚本生成的 entry.c,随后一次链接即可产出动态库。

进程内编译

快快快如闪电的编译!

对一个数千行的典型项目,从源码到编译、链接为动态库,耗时不到 0.3 秒;从点击编辑器 Build 按钮到热重载完成,整个流程不超过 1 秒。

在新版本的 GDCC 编辑器插件中,点击 Build 的瞬间,编辑器里跑的就已经是新代码了,你的编程体感与写内置 GDScript 几乎没有任何差别。 GDCC 0.0.3 雄辩地证明了,编译型工作流完全可以追平解释型工作流的迭代速度。

为了达到这一目的,我们让 GDCC 编译器在自身进程内直接产出原生库,不再调用外部 C 编译器,也不再写入中间文件。 少一层进程调用,少一轮磁盘往返,在 Windows 这样层层杀毒软件、权限访问控制堆叠的灾难环境中,我们硬生生抠出来了闪电速度

编译服务器

GDCC 现在可以作为长驻后台进程运行,以 JSON-RPC 形式向外部工具提供语法分析、诊断与构建能力。 编译服务器的服务具备容错能力:即使代码暂时写错、语法树残缺,它依然能向你(或者是你的AI Agent)回答“光标处是什么类型”、“这里能补全什么”

正是有了这一服务,Godot 编辑器才能第一次获得真正意义上的 IDE 级体验。呃 ( ╯□╰ ) 好像这抢了下一节的内容……

编辑器插件

GDCC 0.0.3 通过定制的 Godot 插件,为 Godot 编辑器带来了完整的 .gd3 开发体验,兼容 4.5 以后的任何 Godot 编辑器。

我想你会疑惑 .gd3 是什么? 其实,.gd3 就是 GDCC 用来识别需要使用 GDCC 编译的脚本用的后缀名,GDCC 默认不会编译你项目中的 .gd 结尾的脚本。 要让某个脚本启用 GDCC 编译功能,只需要重命名它的后缀名为 .gd3 即可。

至于为什么是 .gd3 ……,因为3长得真的很想两个倒着的c连起来啊……

GDCC 编辑器插件提供以下功能:

语言与编辑方面:

  • 实时诊断:键入即查,错误与警告实时标注,无需保存。
  • 智能补全:成员、参数、关键字、引擎 API 全覆盖,并高亮当前参数。
  • 悬浮与跳转:悬停查看类型与文档,一键跳转定义。
  • 大纲与高亮:侧栏大纲定位函数与成员;配色与 Godot 原生风格一致。

构建与部署方面:

  • 一键构建:标题栏 Build 按钮触发编译,动态库自动部署并热重载;弹出面板可切换编译后端、优化级别与严格模式。
  • 状态反馈:底部 Dock 显示连接、诊断与构建状态及日志。

环境管理方面:

  • 服务自启与安装向导:gdcc serve 未运行时按配置自动拉起;向导可检测并安装 JRE 与编译器,一键配置编译环境(约60MB磁盘占用)。

GDCC 编辑器插件(中文界面)

结语

0.0.3 是 GDCC 一个里程碑式的重要版本,我们在在语言完整性、构建效率与编辑器体验三个方向同时推进。 GDCC 由此从能编译迈入能用的新阶段。我们将认真听取您的意见,向着更好的 GDScript 这个目标继续进发~!

一如既往,编辑器插件、Jar 和平台分发包已发布在 GitHub Releases。欢迎各位来尝试、反馈、参与。