我在Godot中创建了一个2D生存类游戏,已经用了大约4个月的时间了。因为我是单人开发,所以我想分享一下实际上对我有帮助的东西,而不是在这个社区里已经有的“使用信号而不是轮询”的建议。

有三件事情比我想象的要有帮助。另外,在第一个部分,我建议你停止一下阅读一个很有用的博客文章。

数以千计的敌人而不损坏老旧的GPU:

  • 如果你正在制作生存类游戏,你就知道这回事了,数以百计的敌人和弹药在屏幕上同时出现,并且需要在不是最新的硬件上运行良好。我自己的开发机器上有一个GTX 1080,我故意把它作为我的基准。
  • 在你触摸任何东西之前,请阅读一下:Rendering a Million Objects in Godot。我今年读到的最有用的东西之一,帮助我避免了两周时间内重新发明它。
  • 我最终得出的结论是:每个纹理/层级/颜色组合都有一个MultiMeshInstance2D,任何共享该组合的内容都只需要一个绘制调用,无论有多少个。不同动画帧存储在Texture2DArray中,所以批处理不会因为一个动画片有8帧而分裂。
  • 我没想到的是:池化实例(不再不断创建和释放)有帮助,但在计数高的时候,它不是什么都不能做的。绘制调用才是关键。我也用了750个个体VisibleOnScreenNotifier2D节点代替了一个一次帧运行一次的AABB检查,结果帧时间有了明显的改进。
  • 当前的数字:能够存活下来的敌人有1200个,活跃弹药的池子有8000多个而没有崩溃。有一天,“感觉更平滑”的标准就不够了,所以我构建了一个小型基准测试,发起了一个难以应付的编程波浪,并将p50/p95/p99帧时间写入csv。比盯着调试器猜测帧时间要好得多。

平衡应该是表格,而不是代码改变

  • 我进入游戏开发时没有被警告过的是:平衡比创建游戏本身还要长。你的数字会被改变很多次,所以设置好改变一个数字不需要编码。

  • 我的游戏中每个武器、敌人、物品都是一个资源文件。目前有35个武器,282个敌人资源文件(约80种敌人类型),126个物品,所有的调节都可以直接在调试器中进行。想测试一下在某个难度等级上减少boss的HP乘数?改变一个数字,点击播放,完成。

  • 比个别资源更大的胜利是:我把我的整个难度曲线(boss的HP乘数、敌人生成率、存活限制等)都放在一个资源中作为平行数组,而不是每个难度等级都有一个拷贝的文件。现在我可以一次看到整个曲线,并捕捉到难度等级之间的奇怪跳跃。基于波浪的精英缩放只是一个Curve资源,你可以拖动点而不需要编写任何代码。

  • 我陷入的一个陷阱是:我的注册表曾经只是在运行时扫描一个文件夹来找到所有资源。编辑器里工作得很好。导出的构建文件默默地找不到任何东西,因为PCK不允许你像这样走遍一个文件夹。结果我不得不改成在编辑时生成一个索引文件(一个插件在保存时重新生成它)。如果你的东西在编辑器里工作,但在导出的构建文件里就消失了,这很可能是为什么。

在你有数百个字符串需要修复之前就设置本地化

  • 我知道,没人想听“早就设置本地化”这个建议,尤其是你还没有开始其他语言的发布。无论如何,还是要做。现在不花钱,后来花费大量时间。

  • 我从一开始就有一个规则:不允许直接在脚本或场景中输入原始文本。每个字符串都要通过一个key查找来获取,英文fallback作为缺省值。这样一来,缺少的翻译就不会打断任何东西。所有的字符串都存储在一个csv文件中,Godot在导入时根据locale进行编译。

  • 因此,去掉一个语言时只需要添加一个列,而不需要修改每个场景。还有一个lint脚本在CI中运行,捕捉到未翻译的关键字、孤立的关键字、复制的英文、缺少的CJK字符、不匹配的占位符等。

  • 我甚至编写了一个伪本地化模式,任何未翻译的字符串都会被标记出来。这样就不用在所有语言中读取了。

锁上门,即使什么都没有完全锁上

  • 默认情况下,Godot的导出是一个zip文件,原来的源代码就躺在那里,任何人都可以打开。有工具可以从一个发布的游戏的pck中提取源代码,例如GDRE Tools。要不然,随机人就可以窃取你的武器逻辑或你的平衡表。

  • 我用了两层保护。第一层是一个名为gdmaim的插件,它在导出时对整个代码库进行混淆,重命名所有标识符并移除注释。即使有人得到你的源代码,你的代码也会变成一堆无意义的名称。第二层是Godot的内置AES-256加密功能,它加密了pck本身。要获取源代码就更难了。

  • 我最终被击中的东西是:我有“加密pck”选项勾选,密钥设置,配置看起来正常,但结果却什么都没做。Godot只会加密匹配一个“包含过滤器”模式的文件。如果过滤器是空白的,那么就什么文件都不会加密。没有错误,没有警告,它们只是静静地把一个未加密的pck发了出去,而选项却是勾选着。

  • 因此,我不再信任勾选的选项了。在每次导出之后,一个脚本尝试从我的构建中提取源代码,失败了。如果它找到可读的代码或未重命名的标识符,就会失败构建。

  • 如果你正在发布任何东西,值得保护的逻辑,就至少开启pck加密,确保过滤器不是空白的,运行自己的构建通过一个公共的提取工具(GDRE Tools是最常见的)。假设有人最终会尝试提取你的源代码。