Java游戏引擎

22

最近我一直在研究游戏开发,我的第一种编程语言是Java。在玩了许多用c++开发的惊人游戏后,我想知道为什么游戏行业没有大量使用Java。我看了jMonkeyEngine 3和其他一些游戏引擎环境,但我看到的截图远不如《极品飞车 热力追踪》和育碧的《刺客信条》那样逼真。

为什么Java不能制作出这样的工业级别游戏呢?是艺术设计的问题吗?

Java和C#都有自动垃圾回收机制,而c++没有。程序员必须更加注意内存使用,以避免悬空指针等问题。

谢谢大家。


试试看 LWJGL,它是一个很棒的 Java 图形库。不过,如果我没记错的话,它还是比较新的。 - anon
6个回答

26
Java和C#具有自动垃圾回收机制,而C++没有。程序员需要更加关注内存使用,以避免出现悬空指针等问题。在游戏编程中,垃圾回收并不是一个优势。即使对于大多数任务来说,Java的性能与C++相当,JIT甚至可以进行非常激进的优化,超过静态分析所能做的优化;但垃圾回收可能会在最糟糕的时刻导致帧率下降。另外,在图形密集型任务中,Java并不是很适合,因为运行时认为许多东西是不安全的,因此被禁止(如将指针强制转换为重新解释数据)。另一个重要的问题是行业已经确定的专业知识。在游戏行业中,C++的惯性非常巨大。今天所有的游戏开发者都知道C和C++。拥有庞大的开发人员池可以减轻关键人物离开公司这一管理风险之一。但尽管如此,仍然有一些成功的游戏部分是用Java编写的,比如吸血鬼:救赎。像我的世界这样的较新游戏完全使用Java编写;但它并不具备最先进的图形技术,因为更多的重点放在虚拟环境的动态性上。

许多其他游戏和引擎都有一个运行时,支持在高性能渲染和网络平台(用C/C++编写)之上构建的托管(安全自动内存分配和回收)脚本语言,例如虚幻引擎


你有没有关于《吸血鬼:黑血盛宴》中使用Java的任何参考资料?我现在在我的硬盘上有这个游戏,如果使用了Python,那么其他所有东西似乎都是本地代码(C/C++ DLLs),但是没有任何JAR文件的痕迹。我在互联网上找不到任何相关信息。我错过了什么吗? - paercebal
@paercebal 你说得对,它是系列中的前一款游戏“吸血鬼:救赎”是用Java编写的脚本,而Bloodlines似乎是用Python编写的(请查看此次采访:http://www.gamasutra.com/view/feature/3147/nihilistic_softwares_vampire_the_.php?print=1) - fortran
@fortran:太棒了!我是一个粉丝,承认《救赎》实际上正在我的GOG库中等待着我。现在,在《救赎》中,Java并不用于实际的游戏引擎,而是用于脚本部分,这并不需要高性能。我怀疑问题并不是关于Java的那种使用方式... - paercebal

19

通常来说,这里说的都是不适合使用Java进行游戏开发的原因;“过去时”。目前,游戏行业正在经历一次“范式转换”。有三个事情已经改变或正在改变游戏行业:

  • 盗版
  • 客户端-服务器程序模型
  • 模块化网络程序模型

游戏不再完全依赖于自身。在以前低级语言中存在的关键优势正在被C#和Java等高级语言的优势所代替。两个简单但不可否认的例子是可以在Facebook上工作的游戏,以及可以在远程媒体(例如手机、平板电脑等)上工作的游戏。

重要的是要指出,在这两种情况下,所有列出的三个问题都得到了解决。需要服务器才能工作的游戏无需担心被盗版(不包括通过逆向工程进行私人托管的情况)。对于需要网络的游戏,需要一种可以在系统性能和网络性能之间平衡的语言(通常是Java和C/C++之间的僵局,由于现有库的丰富而倾向于C/C++)。然而,在模块化网络程序模型中设计的游戏将无法使用低级语言(如C/C++)进行开发。对于希望使用C/C++为模块化网络程序模型设计游戏的公司,必须创建一个完全专注于该游戏的虚拟机,或者重新编程/编译游戏多次,这种想法太疯狂了。在我看来,尽管现在可能还为时过早,但我基于以下三个关键原因把我的赌注放在Java上。

  • 1)JVM允许基于Java的应用程序在几乎任何平台上运行,包括Apple、Android、Windows 8或Linux/UNIX衍生版(也可以在几乎支持任何硬件平台上运行)。

  • 2)Java使用OpenJL(OpenGL的派生版本),可以作为OpenGL的客户端运行-- jMonkey是一款使用OpenJL设计的引擎。需要注意的是,只有Microsoft Windows使用DirectX,因为OpenGL在其他平台上的支持更具优势。

  • 3)Java具有可移植性和跨平台性,并且可以实现模块化设计。 模块化网络程序模型就是Java最适合的场景之一,但Java同样也适用于其他类型的游戏。

尽管如此,它仍有一个缺点。几乎所有能运行游戏的操作系统都能够使用OpenGL进行渲染,模块化设计也在推动这一点(就像以前从未经历过的)。 (请注意,微软正在通过垄断Windows 8的分发来偏离这个问题)。

  • 3) Java支持JVM内部的线程,这使其无需使用任何第三方库即可充分利用多核处理器。目前,这对于所有其他语言(特别是为手机开发的语言)来说都是一个障碍。

  • 虽然JVM确实存在延迟问题,但应该注意到这些问题可以通过线程处理来排除。我也不会太担心Windows 8和Microsoft的推动。谷歌股票价格为每股720美元,苹果为526美元,而微软到今天为止只有27美元。尽管由于使用C#,苹果可能会受到微软的影响,但另一方面,谷歌可能会从中获利。微软在与谷歌竞争时从来没有太大的运气,而谷歌/Android广泛使用Java。愤怒的小鸟最初是用Java设计的,供iPhone使用时转换到了C#。如果Google / Android强制标准化,那么Microsoft将像苍蝇一样消失,带着苹果一起消失。


    “在 iPhone 上使用 C#” - 你的意思是 Objective-C,对吗? - Big McLargeHuge
    4
    不确定个别股票价格与此有关。市值可能稍微更相关,但仍与此没有太大关系。 - Nathan Adams
    三年后,我知道了,但我想指出Xamarin早于你的评论,所以他可能在谈论那个。@david - highboi

    5
    我想讨论这个问题的一个副题,但垃圾回收并不一定有助于创建 AAA 类型游戏引擎中的底层性能关键点。事实上,避免使用那种对象引用和收集系统对于对象是有帮助的。你希望即使是用户定义的类型也在内存中连续,并且适合缓存中相邻的对象等等。
    除了定期收集垃圾和将对象分散在内存中的性能问题之外,游戏不能在其更大的资源上浪费,而垃圾回收器会妨碍这些事情。是的,我刚才说过垃圾回收器妨碍了避免泄漏的能力。
    垃圾回收并不是防止资源泄漏的万能药。
    尽管听起来有些违反直觉,但看看今天最容易泄漏的应用程序:使用时间越长,内存使用量就会越来越多的应用程序。通常它们不是 C 或 C++ 应用程序。C/C++ 应用程序可能因崩溃而臭名昭著,但不太可能泄漏。那些泄漏的应用程序往往是使用垃圾回收语言编程的。
    例如,考虑 Flash 游戏。有许多这样的游戏,不仅仅是业余软件,它们会在你玩游戏时使用越来越多的资源,并变得越来越慢,有时需要重新启动浏览器才能使游戏快速运行。然而,它们是用 ActionScript 编写的,这是一种具有垃圾回收功能的语言。
    理论上,垃圾回收应该减少泄漏。实际上,它通常会消除更便宜、更易于修复和发现的物理泄漏(哎呀,我忘了删除这个字符串),以换取更昂贵、更难以隔离的逻辑泄漏(哎呀,系统的逻辑导致笨重的资源一直存在,直到整个游戏关闭)。
    这是因为在 GC 语言中,如果你想创建一个新资源 R 的共享所有权,则只需在另一个对象 A 中存储一个句柄/引用。B 和 C 也可能存储对 R 的句柄,现在 R 有三个所有者,并且只有当所有三个所有者释放引用时,R 才会被释放。用户只看到并使用 A 存储的内容,因此游戏逻辑涉及周期性地从 A 中删除 R,但是对它的引用在 B 和 C 中默默地残留,代码忘记了释放。在 C/C++ 中,这里的悬空指针实际上可能更可取,因为它会导致在游戏测试期间立即检测到并纠正问题,开发人员运行调试器将非常快速地发现并修复问题。在 GC 语言中,很难检测到,虽然程序不会崩溃,但泄漏可能会变得严重。
    垃圾回收确实避免了悬空指针的问题,但是如果在C/C++中存在悬空指针问题而在垃圾回收语言中不存在,则这是垃圾回收语言中的逻辑资源泄漏和C/C++中的段错误。换句话说,垃圾回收将悬空指针转化为永久存在的悬空资源。它将可能导致明显崩溃的问题变成了隐蔽的泄漏,这可能是一个长期的调试噩梦(甚至在产品发布后仍然可能被忽略)。因此,在像创建大规模、动态世界、图形、物理对象等内容,尤其是在每一帧都有可能发生的情况下,逻辑资源泄漏是一个大问题。
    垃圾回收最适用于不需要过度关注资源泄漏的情况。
    在使用GC的大型团队环境中,上述情况很常见,特别是当每个程序员并没有非常谨慎地注意垃圾回收的陷阱和弱引用的重要性时。因此,垃圾回收并不一定是制作游戏的优势,除非你只是谈论最高级别的人类逻辑。在需要不断创建、访问和销毁资源的低级、精细系统逻辑中,即使是在避免泄漏方面,没有垃圾回收通常也会更好。

    4
    你的问题的答案是艺术作品和财务资源。最初,Minecraft是由一人在Java中开发的。而AC或NFS等游戏则是由数千人的团队开发的。比较一下资源。此外,Ubisoft使用自定义游戏引擎。如果你是唯一的开发者,应该专注于创意,因为缺乏资源。如果你有一个想法,在正常的唯一开发者游戏中,垃圾收集器是不可察觉的。作为唯一的开发者,你应该选择最快速的开发技术。

    1

    在游戏产业中完全没有使用垃圾回收是不准确的。虚幻引擎3已经为'脚本'类实现了垃圾收集。对于它们来说,当轻度使用时性能是可以接受的;重负荷由管理自己内存的C/C++代码完成。

    正如fortran所说,由于速度的原因(Java在VM上运行代码,而不是本地运行...大多数情况下)和因为有许多才华横溢的游戏程序员已经用C和C++编写了许多常用的代码,所以 Java实际上并没有在游戏产业中得到广泛使用。这并不是说你不能利用Java来制作游戏,因为有一些Java游戏存在,但“主流”的游戏产业已经大力投资了C / C++后端。


    3
    稍作更正:现代JVM可以以本地速度运行代码。 JVM配备了一个JIT编译器,它会跟踪代码运行的频率,一旦引用计数达到一定阈值,就会将该代码编译为本机机器代码。这就是为什么许多Java基准测试包括抛弃式运行,通过强制JIT编译代码来“预热”引擎。 - jeckhart

    0

    Fortran和James已经很好地涵盖了它,但我想提到的另一件事情是,当谈到惯性时,Fortran暗示的一个巨大的C++库池,几乎可以为您所能想到的任何东西提供多个C++库,这是不切换到Java的重要原因。这并不是说现在没有Java的库,但C++的库已经成熟,并拥有经验丰富的开发人员社区。不必重复编写以前做过1000次的相同内容,这可以节省大量时间。


    2
    我认为说没有成熟的Java库是有点不准确的。虽然在Java世界中可能没有那么多专门用于游戏的库,但几乎所有与Java相关的成熟库都可以免费获取。 - jeckhart

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接