在交付一个 6 万行代码的项目后,我对 Lua 的看法
[中文正文内容]
Luden.io
·
Follow publication
Luden.io 是一家教育游戏开发商
Follow publication
在交付一个 6 万行代码的项目后,我对 Lua 的看法
Oleg Chumakov
·
Follow
Published in
Luden.io
·
15 min read
·
May 30, 2024
177
1
Listen
Share
大家好!我是来自 Luden.io 的 Oleg。我们决定与 Ivan Trusov(视频游戏 Craftomation 101 的首席程序员)就 Lua 编程语言进行一次深入而有意义的对话。Craftomation 101 包含约 60,000 行 Lua 代码,并使用 Defold 游戏引擎制作。
我要求 Ivan 谈谈实际问题并展示真实代码,而不是“为公众精心准备的假设代码,用于说明我们认为应该如何做,而不是我们实际如何做。”
Craftomation 101 是一款关于自我复制机器人的游戏,通过视觉编程指令来制造(和食用)资源,从而改造一个冰冻的星球。该游戏最近在 Steam、itch.io 和 GOG 上发布了 Windows、macOS 和 Linux 的 Early Access 版本。此外,还有一个 可在 Web 浏览器中玩的免费演示。
该游戏受到了玩家的好评,目前在 Steam 上拥有“非常积极”的用户评价。此外,发布 2 个月后,一些教育机构正在将其用于计算机科学课程和编码训练营(这让我们非常兴奋和鼓舞!)
Oleg Chumakov:Ivan,首先,为什么选择 Lua?在开发之初,我们为什么没有考虑使用 TypeScript、Haxe、纯 C++ 或其他东西?
Defold 引擎提供 C++ 和 Lua 支持,但有一个开源的 TypeScript + Defold 工具包 https://ts-defold.dev/ 和 Haxe 支持库 https://github.com/hxdefold/hxdefold。
选择 Defold 引擎是因为它提供了超级轻量级的 Web 构建版本,与 Chromebook 兼容,以及适用于 PC、控制台和移动平台的原生构建版本。这很重要,因为我们的游戏被许多拥有 Chromebook 的教育机构使用。
**Ivan Trusov:**我问了 Dmitry……
Dmitry 是我们的同事,也是 Defold 引擎的老手。他告诉我 Lua 一切都很棒。我问他 Lua 是否是我们用来编写 Redis 配置文件的那种语言。他向我保证一切都会很棒,因为他已经用它交付了很多项目。
所以我信任了 Dmitry……
Ivan Trusov - Craftomation 101 的首席程序员
我之前的经验是 C++(我以为我了解 C++,但使用 ClickHouse 后我才发现并非如此)、Python(尽管我知道 Python 在游戏开发中不是一个重要的角色)和 Java。所以我的技术栈不在主流游戏开发引擎的范围内。此外,Defold 提供对 Lua 和 C++ 的原生支持,这使它成为一个简单的决定。
我听说 Lua 在游戏开发者中也以易于集成的小型语言而闻名,适用于任何自制引擎,尤其是在你想为你的游戏设计师在实现复杂的游戏内系统(如能力或法术效果)时提供更大的灵活性时。
另一方面,当游戏设计师在其 Lua 脚本中使用一些“黑魔法”时,你可能会偶尔在性能分析器中发现性能峰值。
但这种作为游戏设计师的附加语言的集成并不是我们想要的;我们打算用 Lua 编写所有的游戏逻辑。
O.C.:所以你开始用 Lua 开发。你还记得一开始 Lua 有什么让你感到惊讶的吗?
**I.T.:**当然,缺少自增操作,没有 "continue" 指令,以及数组索引从 1 而不是 0 开始。这些差异可能会让人感到不适应,尤其是在为不同的项目/脚本在两种语言之间切换时。我仍然有时会写 [array.length-1] 来获取最后一个元素的索引;在使用 C++ 和 Python 工作多年后,你就是无法适应这一点。
此外,在我大学期间,我选修了两门关于 Haskell 的课程。令人惊讶的是,我看到了将函数式语言的方法应用到 Lua 中的一些好处。例如,创建一个有 4 个步骤的非柯里化函数,然后对其进行折叠和装饰。
我想说的是,Lua 可能是受到一些函数式元素以及简单脚本语言的启发。这就是为什么一些函数式模式可以为 Lua 开发人员的生活带来新想法。
这些函数式的氛围让我感到非常惊讶。我可以用这样的例子来说明:
带有语法糖,又名 “Haskell 氛围”不带语法糖,又名 “Haskell 氛围”
这里还有一个更复杂的例子,说明 Lua 中 柯里化函数 和 另一种解决方案 以供比较的 “Haskell 氛围”。
O.C.:那么 Lua 中缺少类呢?
**I.T.:**实际上,我一直喜欢简单的解决方案,并且从来都不是 OOP 的粉丝。要创建一个好的类,你需要了解很多关于其未来用途和 OOP 原则的知识。每当回忆起过去编程工作面试中被问到的问题,如“告诉我 OOP 的三个原则”时,我仍然会感到尴尬。也许有些公司仍然会在面试中问到这些问题。我们在这里不做评判。
Lua 中的代码组织对我来说非常直观。由于其简单的 "一切都是表" 的方法,它甚至更清晰。但这个基本原则并没有被清楚地传达,我只是在遇到 "表中的表不是表,而是对表的引用" 的错误并试图修复它时才明白这一点。我只是使用 "=" 设置了一些值,之后,我的表被引用而不是被复制,所以游戏的两个部分开始编辑同一个表,我得到了一些 "有趣和意想不到" 的结果。
此外,我们游戏中确实有一个表!元素的表。
让我们用一些代码来说明一下。我有下面显示的函数,我想创建一个队列的表,在其中我会写入然后排序机器人(我不记得这个队列是做什么用的了)。所以,我创建了一个大小为 100*1 的队列,给它一个像 {x=0, y=0} 这样的表作为默认值。
然而,正如你在下面看到的,默认值是通过 "=" 分配的,而没有将其复制到每个元素。结果,很长一段时间,我不明白发生了什么,以及为什么我的机器人排序总是产生某种无稽之谈。
事实证明,该表包含 100 个对相同坐标的引用。每次我在这个表的一个元素中重写 x 和 y 时,我实际上是在一个表中重写它们,并且对这个表的引用被分配给了所有表的值。所以,我最终对 100 个相同的元素进行了排序。
最后,我这样修复了它,但在过程中我学到了关于 Lua 的重要一课。
O.C.:好的,你对……有什么看法?
**I.T.:**请允许我再讲一点关于表的内容!
总而言之,我认为用 Lua 中的所有这些表来编写游戏逻辑(或业务逻辑)比用 C++ 方便得多。如果与 Python 在基本层面上进行比较(我是指纯粹的语言,而不是所有惊人的包,如 PyTorch、NumPy 和成千上万的其他包),我认为将 Lua 视为 Python 的简化版本是公平的。
几乎任何在 Python 中容易实现的东西在 Lua 中也容易实现。然而,当涉及到将代码分成模块或包时,Python 更方便。
O.C.:好的,我明白了关于表的内容,我想问关于……
**I.T.:**请允许我最后再讲一点关于表的内容!
“一切都是表” 的另一方面是 —— 你不需要在选择结构时做出艰难的决定,因为没有提供其他选项!
现在我讲完关于表的内容了,谢谢。
O.C.:你有没有就这种 “表” 的方法与其他 Lua 开发者交流过?
**I.T.:**在那之后,我回到 Dmitry 那里,问他我对 “一切都是表” 的理解是否正确,如果是这样,为什么 Lua 要这样设计。Dmitry 告诉我,Lua 是在里约热内卢天主教大学创建的,对于天主教大学来说,以这种方式设计编程语言是可以接受的。
O.C:你如何看待性能?
**I.T.:**单凭感觉,用 Lua 开发会让你觉得这是一种 “感觉很快” 的语言。在 Craftomation 101 中,由于语言速度的原因,我们实际上很少遇到性能问题,所以我们的情况可能并不完全具有代表性。这就是为什么我称之为 “感觉很快” 而不是仅仅是 “快”。有一些 基准测试 以数字形式显示了它的速度。
在 Defold 中可以选择编写 C++ 代码,例如创建一个模块或修改引擎本身(代码可在 GitHub 上获得)。对我来说,这是一种潜在的解决方法,可以在将来我可能需要处理计算复杂的任务时使用。
我总是先用 Lua 实现一个模块,如果性能分析器显示出明显的 CPU 问题,我希望用 C++ 重写它。然而,问题并没有那么严重,并且将一些算法知识应用到 Lua 代码通常可以解决或最大限度地减少它们。
与 Warnament(我们的另一个 Defold 项目,严重依赖 C++ 模块)等项目相比,该游戏在技术上相对简单。此外,Defold 生态系统中还提供了原生实现的 C/C++ 模块,例如 A* 寻路。
O.C.:凭借你在 C++ 和 Java 方面的经验,你是否曾经觉得 “在运行时发生问题之前,我对任何问题都一无所知”,因为没有编译步骤,而且你没有严格类型编译语言提供的信心?
**I.T.:**是的,当然,但这没什么大不了的,因为当时我一直在使用 Python。这不仅仅是用 Python 编写的业务逻辑。那是大约三年的 Python 机器学习经验。隐藏在大量数据(以及所有用于处理 “脏” 数据的代码)中的问题比隐藏在解释代码中的问题更难以控制。
O.C.:你使用过 Linter 或其他代码分析工具吗?
**I.T.:**实际上,我非常喜欢使用默认的 “库存” 设置,直到我发现真正让我兴奋的东西。在前六个月,我甚至使用 Defold 的嵌入式代码编辑器编写代码,因为 Dmitry 告诉我这是处理代码的好方法(它甚至有语法高亮显示!)。
Defold 的嵌入式代码编辑器
在那之后,我切换到了 VS Code(这篇文章的作者是 Sublime 的忠实粉丝,忍不住要加上这句话,说 Sublime 是最好的!)。但是,我必须提到我真的没有使用 Linter 的经验,这就是为什么简单地在 Google 上搜索 “VS Code Lua Linter” 并按照顶部的链接安装任何找到的东西并没有给我的编程体验带来巨大的改变。
但是基本的 VS Code Lua 包提供了一个类型检查器,它可以帮助突出显示代码中的一些问题,这非常有用。
带有 Lua 代码的 VS Code
O.C.:我记得在一次站立会议上,你告诉我你讨厌 Lua 并建议切换到 TypeScript。当时,项目中大约有 60,000 行代码。当你最终得到这么多代码时,添加一些静态分析工具是不是一个好主意?
**I.T.:**静态分析工具或 TypeScript 始终在我的脑海中,但在后台,作为 “未来要做的事情”。在开发期间,当我们缺乏 QA 并且我不确定游戏是否稳定时,它会更多地出现在我的脑海中。在更接近其中一个里程碑的一轮 QA 之后,我修复了许多 “这是一个向量,但由于某种原因,它被分配了一个字符串” 之类的问题。在 QA 过程中,事实证明游戏比我预期的要稳定得多。
O.C.:对于下一个可能同样大甚至更大的项目,你想从 TypeScript 开始吗?
**I.T.:**实际上,就目前而言,我不这么认为。Defold 中的 TypeScript 支持级别可能是我遇到的更大的问题之一 —— 它是非官方的,即使有最好的社区支持,你也不能确定所有引擎更新都会被实现,或者你是否有时间自己实现它们。
我希望任何 “Lua 的替代方案” 都具备两个主要优点,这是众所周知的:
- 我想在编译期间而不是在执行期间意识到我的代码问题。
- 我想以一种方便而简单的方式组织我的代码库。在像 Lua 这样的动态类型语言中,在组织代码库和设计架构方面有如此多的灵活性,以至于有时它可能不如强制执行特定样式的系统方便。
O.C.:有一些传言说 Luau 正在考虑集成到 Defold 中。在 Lua 5.1 中有效的代码在 Luau 中也有效。你怎么看?
Luau 是一种派生自 Lua 的渐进类型语言,由 Roblox 制作。
**I.T.:**实际上,我从未尝试过 Luau,据我所知,在 Defold 中将 Lua 版本更新到 5.2 存在问题。Lua 5.2 包括一个自增操作,但我真正想要的是 Lua 5.4(亲爱的 Defold 团队,请!)。
但我们在这里讨论的是 Luau。我认为 Luau 可以让生活更轻松,但不会显着改善,因为它介于 Lua 和严格类型语言之间。TypeScript 也出现了类似的情况,它诞生于 JavaScript 和严格类型语言之间。
理想的情况是在 Defold 中正式实现 TypeScript,或者,如果我们能梦想成真,另一种从一开始就被设计为严格类型的语言。
O.C.:哪一种?
**I.T.:**有一次,我的大学朋友问我为什么不能用 Go 为 Defold 编写代码。我问,我们为什么要考虑这一点?他们回答说,这是因为 Go 是一种非常酷的语言,为什么不呢!当然,这是一个假设性的疯狂问题,与我们拥有像 WebAssembly 这样的语言无关的系统的假设性未来有关,WebAssembly 已经集成到 Defold 中。
由于 Unity,C# 现在是我们行业中的领导者之一。但是,我不确定是否可以在不牺牲引擎轻量级感觉的情况下将其集成到 Defold 中。
O.C.:在 Craftomation 101 中,哪些事情可以用严格类型语言做得更好?
**I.T.:**例如,我们有一个巨大的地图,其中包含许多交互式对象。玩家可以与它们互动,我们的机器人 CraftoMates 也可以与对象互动。此外,他们还可以搜索特定的对象以从中挖掘资源。
地图上的所有对象都是存储在数组中的参数化对象,类似于 ECS 中的实体。有很多类型的对象,如火焰、木材、木材上的火焰、壁炉等。为了用严格类型语言协调所有这些,我可以直观地使用 OOP 或 ECS,并使用特定的管理器、控制器或系统来处理特定类型。或者,我可以创建一个具有一系列 IF 语句的宏伟的管理器-处理程序。
在 Lua 中,所有这些也是可能的,但由于它不是那么直接,开发人员可能会开始怀念在 C# 等语言中发现的易于实现性。
这是 “if 选择器” 的代码,它是项目中导致 bug 的绝对冠军。
Lua 中有元表,在某些方面可以作为类的替代品。但是,从我的角度来看,最好从一开始就使用元表,或者忽略它们,而不是尝试将元表方法引入到现有的代码库中。
Defold 有一个名为 Druid 的大型 UI 库,它使用元表实现,并具有一些 OOP 的感觉。似乎在 Lua 中使用 OOP 可能会迅速而令人惊讶地导致开发人员陷入添加新功能变得非常困难的境地。
O.C.:在使用 Defold 和 Lua 的 CI 方面有什么特别之处吗?
I.T: Defold 构建项目的速度让我感到非常惊讶。我记得听过一些朋友用 Unreal Engine 制作游戏的故事,他们说构建过程非常漫长。我们工作室还有其他用 Unity 制作的项目,Unity 相当不错,但 Defold 中的构建时间感觉就像纯粹的魔法。
即使现在,项目非常庞大,平均构建时间也只有 4 分钟。我们使用 GitHub actions 和本地 runner 来构建游戏。使用带有 M1 Apple silicon 的 Mac Mini 作为我们的本地 runner,我们只需一台机器即可构建所有平台。
所有平台 25 个构建版本的完整矩阵
O.C.:对下一个项目有什么想法吗?
**I.T.:**首先,Craftomation 101 的完整发布仍在进行中;路线图仍然非常大。对于下一个 Lua 和 Defold 项目,我将使用更加基于模块的代码组织。由于我目前的代码组织方式,我使用了大量的 “消息”(Defold 提供的游戏对象之间的通信方式)。我认为将来我不应该过多地依赖它们。
我想做的另一件事是创建更多原子游戏对象管理器,因为它们已经变得非常庞大,并使它们更加独立。
单元测试和其他自动化测试听起来很棒,但与制作视频游戏的情况一样,它们的使用可能非常有限。但是,我真的很喜欢自动化测试来检查用户交互场景的想法,我肯定会尝试一下。
O.C.:你有什么材料可以推荐吗?
I.T.:
- 在 官方网站 上有一些关于 Lua 的官方书籍。
- 此外,我认为阅读一些关于 Haskell、Clojure 甚至 OCaml 的东西是有益的。
- 当然,虽然不是专门关于 Lua 的,但经典著作 "Game Programming Patterns" 是一座金矿。
O.C.:Tab 还是空格?
**I.T.:**Tab!
O.C. 你喜欢用什么键盘工作?
**I.T.:**我使用 Dark Project One 键盘。我还想提一下我的鼠标,因为它从高中开始就一直完美地工作:Bloody TL70。最近,我买了 Logi MX Master 3S。
而且在我的工作桌上,我确实有一个 非常有用的立方体。
你有什么秘密吗?
Ivan 透露了一个秘密,但这有点令人震惊。请在向下滚动以了解它是什么之前三思。为了你的安全,我在下面放了一张游戏路线图的长图,所以你不会不小心滚动到秘密揭示处。你已经被警告了!
**秘密:**我更喜欢这种 VS Code 的配色方案,切换到暗色只是为了给这篇文章截图。
附注:如果我不表达我们对所有玩家的爱和巨大的感谢,我就无法结束这篇文章 —— 你们真是太棒了,并且感谢你们所有人,我们受到启发继续进行我们的游戏项目:程序员、教育家、父母、学生、工程师以及来自各地的所有好奇心 ❤️
特别奖励部分:我们请 Defold 的全能 Björn Ritzl 对这篇文章发表评论,他非常友善地同意了:
“我想评论一下其他语言可能是有意义的:
- 我们不再考虑使用 Luau (Roblox)。
- 相反,我们已决定为我们的工具(编辑器和命令行)添加通用转译器支持。
- 这将允许开发人员创建自己的扩展,以将其他语言转译为 Lua,并使用 Defold 附带的标准 Lua 虚拟机运行。
- 为了展示如何做到这一点,我们已决定提供对 Teal 的官方支持,Teal 是一种转译为标准 Lua 代码的类型化 Lua 方言。当你使用 Teal 文件(扩展名为 .tl 的文件)时,这将为你提供构建时类型错误。现在还处于早期阶段,我们还没有 Teal 的语法高亮和 LSP 支持,但它已经很有用了。
值得指出的另一件事是,我们现在还在编辑器中内置了 Lua LSP 支持,使用了一个众所周知的 Lua LSP 以及 LuaCheck。这将为你提供代码的静态代码分析,并在编写代码时提供提示,如果 Lua 语法有误,则会提供构建错误。
最后,我们也在重写 C++ SDK 的公共部分,该 SDK 目前用于编写本机扩展。我们现在正在开发一个 C SDK,并扩展了可用 SDK 函数的集合,以便可以使用本机代码编写整个游戏。
这个更新后的 C SDK 将用于生成今天用于本机扩展的 C++ SDK,它还将用于为那些希望使用 C# 编写游戏或扩展代码的人生成 C# 绑定。C# 的使用将完全是可选的,并且不会以任何方式膨胀引擎或降低那些选择不使用它的人的性能。
C++ 和 Lua 仍然是 Defold 中的主要语言。
诸如 Teal 之类的转译语言和诸如 C# 之类的编译语言将是可选的。”
注册以发现加深您对世界理解的人类故事。
免费
无干扰阅读。没有广告。 使用列表和重点突出组织您的知识。 讲述您的故事。找到您的听众。 免费注册
会员
阅读仅限会员的故事
支持你最常阅读的作家
为你的写作赚钱
听音频旁白
使用 Medium 应用程序离线阅读
试用价为每月 5 美元
Programming
Programming Languages
Lua
Gamedev
Game Development
177
177
1
Follow
Published in Luden.io
224 Followers
·Last published May 30, 2024
Luden.io 是一家教育游戏开发商
Follow
Follow
Written by Oleg Chumakov
622 Followers
·202 Following
Follow
回复 (1)
写回复
你有什么想法?
取消
回复
Ivan Quirino
Jun 28, 2024
"Dmitry 告诉我,Lua 是在里约热内卢天主教大学创建的,对于天主教大学来说,以这种方式设计编程语言是可以接受的。"Dmitry 真的想摆脱你……更多
2
回复
更多来自 Oleg Chumakov 和 Luden.io
In
Luden.io
by
Oleg Chumakov
Generated Adventure — The Postmortem of a Game Made With chatGPT and Midjourney (Prompts Included)Generated Adventure 是一款在 Ludum Dare 53 游戏创作大赛期间制作的免费网页点击冒险游戏,涉及所有生成式……
May 24, 2023
3311
In
Luden.io
by
Oleg Chumakov
Learn more about Machine Learning关于机器学习的教育资料汇编
Jan 23, 2019
221
In
Luden.io
by
Oleg Chumakov
Meet while True: learn()了解机器学习的工作原理
Dec 1, 2017
6531
In
Luden.io
by
Oleg Chumakov
while True: learn() 发布或关于 1 年每周更新、机器学习和猫的故事你好。很难相信这一天终于到来了。我们的小型机器学习专家模拟器即将离开 Early Access。你……
Jan 17, 2019
130
See all from Oleg Chumakov
See all from Luden.io
来自 Medium 的推荐
In
rustycrab
by
[Uday Hiwarale](https://blog.