用于游戏开发的 Kotlin

Kotlin for game dev

背景:

我一直在寻找一种语言来替代 Java 进行游戏开发。 Kotlin 看起来很有前途,具有良好的 IDE 支持和 Java 互操作性。但是游戏的 FPS 杀手之一(尤其是在 Android 上)是 GC 使用。因此,一些库(如 libgdx)正在使用对象池、自定义集合和其他技巧来避免频繁的 GC 运行。对于 Java 这可以用一种清晰的方式来完成。其他一些 JVM 语言,尤其是具有功能支持的语言,本质上使用大量 GC,因此很难避免。

问题:

  1. 与 Java 相比,Kotlin 是否会产生任何不可见的 GC 开销?
  2. 为了减少 GC 工作,最好避免 Kotlin 的哪些特性?

根据经验,Kotlin 生成的字节码尽可能接近 Java 生成的字节码。因此,例如,如果您使用函数作为值,将创建一个内部 class,如 Java,但仅此而已。还有一些优化技巧,例如 IntArrayinline 可以实现更好的效果。

正如@Peter-Lawrey 所说,衡量特定案例的价值总是更好的主意。

从技术上讲,您将 Kotlin 与 Java 进行比较的问题没有实际意义,它们将执行相同的操作。但是 Kotlin 会是更好的开发体验。

如果 Java 适合编写游戏,那么 Kotlin 只会因为开发人员的生产力而更好。

注意: 游戏库 LWJGL 3 部分使用 Kotlin,GitHub 统计数据显示 67.3% 的代码是 Kotlin(模板模块看起来主要是 Kotlin)。所以询问与 LWJGL 合作的人会给你最好的答案,因为他们在这方面有很多经验。

您可以为 JVM 编写 Kotlin 代码,这会导致与 Java 相应逻辑相同的分配。在这两种情况下,您都必须仔细检查库调用是否在堆上分配了新内存。将 Kotlin 与 LibGDX doesn't introduce any invisible GC overhead. It's an effective way and works well (especially with the ktx 扩展结合使用。

但是 Kotlin 语言的一些特性可以帮助您以更少的分配编写代码。

  1. 单例是一种语言特性。 (Object declarations, companion object )

  2. 您可以为编译为基元的基元类型创建包装器 classes。但是您可以获得类型安全和丰富领域模型的强大功能 (Inline classes)。

  3. Operator overloading and Inline Functions you can build nice APIs which modify objects without allocating new ones. (Example: Allocation-free Vectorial operations using custom operators)

  4. 的组合
  5. 如果您使用任何类型的依赖注入机制或对象池来连接您的游戏逻辑并重用对象,那么 Reified type parameters 可能有助于以一种非常优雅的方式使用它。如果编译器知道实际类型,您可以跳过 class 作为类型参数。

但是还有另一种选择确实可以让您在内存管理方面有不同的行为。感谢 Kotlin Multiplatform,您可以将游戏逻辑编写为 Kotlin 公共模块并将其交叉编译为本机代码或 Java 脚本。
我在示例游戏项目 Candy Crush Clone. It works with Korge a Kotlin 的现代多平台游戏引擎 中执行了此操作。游戏在 JVM 上运行,作为 HTML 网络应用程序和 Win 中的本机二进制文件,Linux、Mac、Android 或 IOS.
本机编译代码有自己的 simpler garbage collection and can run faster。所以速度的提升和不同的内存管理可能会给你更多的动力储备来减少对GC的打扰。

总而言之,我可以推荐 Kotlin 用于游戏开发,也用于 GC 关键场景。在我的项目中,我倾向于在编写 Kotlin 代码时创建更多 classes 并分配更多内存。但这是编程风格的问题,不是技术问题。