为什么只有少数视频游戏使用Java编写?

174
为什么很少有商业化的3D视频游戏(不包括随意开源2D游戏)使用Java编写?理论上,这样做非常有道理:您可以几乎免费获得生产力提升和跨平台应用程序等优势,还有大量的Java库和内置垃圾回收功能(尽管我承认后者是否是好事情我不太确定)。那么为什么很少使用呢?我只能想到一些流行的商业游戏是为Java平台编写的。

是因为性能的原因吗?如果是,那么大多数繁重的工作都会由GPU完成,不是吗?


10
http://en.wikipedia.org/wiki/Tribal_trouble - Michael Myers
1
回复:mmyers;我有点震惊那个游戏甚至在2005年也赢得了“最佳图形”奖项... - CloudyMusic
2
是的,但大多数“真正的游戏”不是用托管的 .net 制作的,而是用老派的 c/c++ 制作的吧? - Hardwareguy
14
Runescape是用Java编写的。 - GameFreak
46
Minecraft 是用 Java 编写的! - daGrevis
显示剩余7条评论
22个回答

160
游戏开发世界很有趣:一方面,他们经常很快接受新想法,另一方面,他们仍处于石器时代。
事实上,除了C/C++之外,切换到.NET/Java/其他语言很少有太多的激励。
大多数游戏公司从其他公司许可游戏引擎的部分。这些部分是用C++编写的,尽管您可能可以访问源代码以进行移植,但这需要很大的努力(当然,许可证需要允许)。
此外,很多遗留代码已经存在于C++中。如果可以重用以前项目的代码(比如,如果您正在编写续集),那么坚持使用相同的语言而不是在新语言中重写它会更有利(尤其是因为您可能会重新引入大量错误,需要花时间解决)。
最后,游戏很少完全使用C++编写 - 很多使用脚本语言完成,无论是自定义的还是只是集成现有语言(Lua是目前比较流行的其中之一)。
至于垃圾收集,这可能会有点问题。问题不在于它是否存在,而在于它的工作方式 - 垃圾收集器必须是非阻塞的(或者至少保证只会短暂地阻塞),因为游戏在扫描所有分配的内存以查看可以释放哪些内容时冻结10秒钟是完全不可接受的。我知道当Java接近耗尽内存时(对于某些游戏来说,它确实会出现这种情况),它往往会出现GC方面的问题。

您的操作受到限制:由于运行时开销,您无法充分利用硬件。想象一下Crysis用Java编写……即使这是唯一的可见区别,它也不会是相同的(我也很确定您需要Core i7才能运行它)。

这并不意味着这些语言在游戏开发中没有用武之地——不,我不仅指工具编程。对于大多数游戏来说,您不需要从C++中获得额外的性能优势,包括3D游戏,如果您从头开始编写所有内容,使用像XNA这样的东西就可以完美地解决问题——事实上,这有很大的可能性。

就商业游戏而言——RuneScape算吗?那可能是目前最成功的Java游戏。


16
显然,你不会在JVM上运行Crysis;如果你用汇编语言编码这个游戏,即使在最高设置下也需要一台超级计算机来运行它。但是对于这个极好的见解,我要点赞,谢谢。 - Sasha Chedygov
15
如果你关注图形质量,那么不能将Unreal Tournament 3或Crysis与Runescape相比。为了降低开销,你需要使用尽可能少的低层语言。当然,对于独立游戏或者图形不是主要卖点的游戏,Java是C/C++的一个优秀替代品。 - GuiSim
6
对于大多数游戏而言,图形质量并不是一个重要的销售点。我只能想到很少一部分的游戏是以图形为目的创建的(我在想Crysis,同时也有Half-Life 2,在当时)。我认为大多数游戏开发者并不太关心图形,只要它们“够好”(即与大多数其他游戏相当)就可以了。 - Sasha Chedygov
4
图形学和语言关系很小,但物理和人工智能有关系。图形学除外。 - JulianR
10
@JulianR:为了高效地渲染场景,准备和维护场景可能需要大量的工作量,因此语言及其相关开销对于图形很重要。 - KSchmidt
显示剩余5条评论

94
我认为John Carmack说得最好:

最大的问题在于Java非常慢。在纯CPU / 内存 / 显示器 / 通信水平上,大多数现代手机应该比Game Boy Advance更好的游戏平台。使用Java,在大多数手机上,您只能拥有原始4.77 MHz IBM PC的CPU功率,并且对所有内容都没有很好的控制。 [...snip...] “一次编写,到处运行”?哈。哈哈哈哈。我们目前只在四个平台上进行测试,而且没有一个平台具有相同的特点。所有商业游戏都针对每个(通常为100个以上)平台进行调整和编译。可移植性不能成为糟糕性能的辩解。

(来源)

当然,他谈论的是移动平台,但作为一个C++背景的人,我发现Java作为整体存在类似的问题。我想念能够按照自己的条件在堆栈/堆上分配内存。


62
那句话是出自2005年。自那时以来,Java技术和手机性能都有了相当大的提升。将手机游戏与电脑游戏进行比较就像是在比较苹果和橙子。 - Chris Dail
78
约翰·卡马克说了这句话,案子就此结束。 - GuiSim
42
当我读到“Java非常慢”时,我的内心感到不安。这就像说一辆价值5万美元的跑车与一辆价值10万美元的跑车相比速度较慢一样。当然它速度较慢,但90%的时间,它所完成的工作仍然很棒,而且成本只有一半。这并不是要引发争论。我同意上述原因是为什么Crysis和类似游戏没有用Java编写的原因。 - Ross
17
@Chris Dail,这凸显了Java性能的整个问题。 Java性能有改善吗?没有,只是手机变得更快了。游戏应该推动现实主义的极限,因此推动硬件的极限,并在没有编写一行代码之前就丢弃30%-40%的性能是不可接受的。 - cgp
8
我觉得这场争议很奇怪。Java ME并不同于Android上的Java,也不同于PC上的Java。通常情况下,Java ME需要依赖手机制造商来提供JVM,有些制造商做得好,有些不行。难怪卡马克会对它们抱怨。而Android则有自己的虚拟机,并非JVM,并且(从我的角度来看)存在一些严重问题。Oracle的HotSpot VM与这两种情况完全不同。如果人们将所有这些东西进行比较,我唯一能得出的结论就是他们不知道自己在说什么。 - Malcolm
显示剩余10条评论

55

首先,Java缺乏运算符重载,这使得处理图形管线所需的所有数学运算变得非常繁琐且难以阅读。

如果使用良好格式化的数学表达式而非面向对象的表达式,所有必要的矩阵乘法和仿射向量都会更易于理解。

product = vector.multiply(projectionMatrix).dotProduct(otherVector);

太糟糕了。数学不应该看起来像那样。


19
我记得在'96年左右,一些来自Sun的设计师在伯克利做Java的演讲。William Kahan (http://en.wikipedia.org/wiki/William_Kahan) 因为这个问题一直在与他们争论。 :) - JP Alioto
13
我认为不允许在语言中使用运算符重载是有很好的原因的:防止人们滥用它。运算符重载是一个强大的工具,在数学方面非常酷,但对其他方面却很危险。由于编码人员懒惰,他们倾向于滥用它来缩短代码,一旦人们开始执行类似使用函数将可迭代对象与函数相乘的映射操作,甚至当所有算术操作都被定义为函数时,代码的可读性就会接近于零。是的,我已经花了相当多的时间去移植那样的代码。:-S 这是一个设计选择。而设计选择总是容易引起争议的。 - back2dos
19
因为一小部分人的过错就惩罚其它所有人吗?这是我更喜欢使用 C# 的原因之一。如果我真的需要运算符重载,它也是可用的。 - ChaosPandion
1
@MMJZ:Lambda表达式与运算符重载有什么关系? - Sasha Chedygov
1
缺乏运算符重载是Java程序易于维护的一部分(因为您需要更少的上下文来理解给定程序片段的功能)。 - Thorbjørn Ravn Andersen
显示剩余6条评论

27

我认为.NET在某种程度上有很多与Java相同的问题。微软只是在使用XNA方面向开发者做了更好的营销 :-)


10
XNA还可以将你的.NET应用程序部署到XBox上。就我所知,Java没有类似这样顺畅的方式。 - StriplingWarrior
1
你也可以将其部署到Zune上。 - cbeuker
这是一个有点老的问题,但是现在可以更新一下,你也可以为Windows Phone编写XNA游戏了 :-) - Joel Martinez
3
@JoelMartinez,最新消息:无法为Windows Phone 8编写XNA游戏。 - Tomas Andrle
@TomA 现在可以为WP8编写Monogame游戏了。 - Alex Lapa
有点老的问题,但是更新一下,Windows 手机呢? ;) - nomæd

18

首先是一些小问题:

  • Java所带来的生产力提升是假设性的。Java语法与C++几乎相同,因此您真正期望的只是在内存管理和标准库方面节省资源。标准库对游戏开发人员的实际意义不大,而垃圾回收机制由于存在争议,因此内存管理也存在争议。

  • 跨平台“免费”并不像你想的那样好用,因为很少有开发者愿意使用OpenGL,并且一些关键平台可能缺乏良好的Java实现或其本地库的包装器,无论是用于图形、音频、网络等领域。

但主要问题在于向后兼容性。游戏开发人员从C到C++,再从汇编到C,仅仅是因为迁移路线顺畅。每种语言之间紧密互通,所有以前的代码都可以在新语言中使用,通常通过单个编译器即可实现。因此,迁移可以慢慢进行,也可以快速完成。例如,我们今天仍在使用的一些旧头文件中还有 #ifdef WATCOMC 的代码,但我认为这里已经有十年或更长时间没有使用Watcom编译器了。旧代码的投资很大,每个部分只会在需要时被替换和升级。如果您切换到一个与现有代码不能原生互操作的语言,那么从一个游戏到另一个游戏逐步替换和升级各个部分的过程就远远不如实际可行。是的,C++/Java之间的互操作性是可能的,但与仅仅编写“带有少量C++”或嵌入C的asm块比较起来,这非常不实用。

要真正取代C++成为游戏开发人员的首选语言,它必须做到以下两点之一:

  1. 能够轻松地与现有的遗留代码进行互操作,以保护投资并保持访问现有库和工具的权限;或者
  2. 展示足够明显的生产力提升效果,以至于重写所有自己的代码(或将界面转换为可重复使用的组件,以便从该语言中使用)的成本得到更好的覆盖。

就我个人而言,我不认为Java满足这两点要求。如果有人勇敢地成为先锋,一种更高级的语言可以满足第二点要求。(EVE Online可能是我们最好的Python使用示例,但它使用了Python主语言的一个分支,许多C++组件来提高性能,即使在现代条件下这也只是一个相对不那么苛刻的游戏。)


只是想补充一下,EVE Online是一个“在线”太空模拟游戏,1000对1000的玩家对玩家战斗很常见,这可以被视为性能要求较高的场景。虽然它的速度密集部分是用C/C++编写的,但在游戏中使用高级语言(Python)所面临的挑战仍然是一个有趣的研究课题。 - Hakan Deryal
然而,请记住,在多人服务器端游戏中,性能的衡量标准与单人客户端游戏略有不同 - 前者更关注吞吐量,后者则更关注延迟。 - Kylotan
没错,但是这场战斗包括2000多艘船只在屏幕上出现,有2000多个弹道(导弹,带动画效果的爆炸等),需要很高的图形性能。无论如何,感谢您详细的回答,它仍然是正确的。 - Hakan Deryal
1
如果你认为C和Java的语法是相同的,因此与性能有关系,那么你真的不理解正在发生的事情。C怎么可能在运行时决定一个给定的函数是否被重复调用,并将整个函数调用替换为常量,同时在参数有偏差时保留函数调用?我并不是说运行时总是更好或总是更差,只是它与语法完全没有任何关系! - Bill K
1
@BillK - 你好像误读了我的意思。我提到语法只是与“生产力”有关,而不是与“性能”有关。理论上,JIT优化可以使Java更快,但在实践中并没有发生,至少在游戏软件中是这样的。 - Kylotan
@Kylotan 您说得对,我误解了您的意思。虽然我仍然非常不同意您的观点,但我看到我误解了您的意思。我已经很久没有比较打字速度和生产力了,我甚至忘记这是一件事情了。 - Bill K

13
  • 有没有好的游戏引擎/库的端口呢?
  • 许多C/C++开发人员,特别是在Windows上(大部分商业游戏都是在这里编写的),熟悉Visual Studio。在IDE方面没有可比性。
  • 总体而言,Java之所以被企业接受,是因为它的强类型和不会出现内存管理问题的认知。
  • 是的,Java仍然存在速度慢、内存管理差的认知,对于游戏来说,它可能不适合这项任务。如其他答案中所述,当你需要处理实时高性能需求时,垃圾收集器并不能满足要求。视频游戏会将CPU和GPU推向极限。

1
人们似乎没有意识到,当你的游戏运行在20帧每秒时,它通常是硬件限制在20帧每秒。它真的想要达到30帧以上...但它做不到。 - GuiSim
我认为性能问题不仅仅是垃圾回收的问题,也不仅仅是与缓慢的启动阶段相结合的问题...这是一般性能问题,但这只是我的看法。 - rogerdpack
2
我认为在这一点上,我比过去更可能同意。JVM的优化已经得到了改善;然而,考虑到像JavaScript等弱类型语言的性能改进,Java相比之下的表现相当不可原谅。有很多人为Java的性能辩护。(但最终感知到的性能才是最重要的) - cgp

12

我正在玩《模拟人生3》,并且做了一些探索。 图形引擎是C++,而脚本和行为引擎则是C# / Mono。 因此,尽管C++用于时间关键的部分,但其他内容,如交互、游戏逻辑和AI,则在面向对象的托管语言中。


5
然后对于Mac版本,他们将整个内容都塞进了一个修改过的Wine虚拟机中。我认为仍然比直接使用Java更快。 :-) - Ben Gotow
11
Wine不是虚拟机,而是一个运行库,它模仿Windows运行库的行为。因此得名(Wine不是模拟器) 。 - Nate C-K
2
这在游戏中非常常见,通常不需要时间关键性的逻辑会用某种脚本语言编写,常见的是lua或python。 - KSchmidt
不过这并不是普通的Mono。EA需要一个专门的团队全职工作,来开发他们自己定制的CLR,以使其正常运行。 - Crashworks
4
顺便提一下,虚拟人生3游戏即使在优秀的电脑上也因性能不佳而臭名昭著。 - Lotus Notes

10

Java和其他虚拟机语言不常用于游戏开发的最大原因之一是垃圾回收。.NET也同样如此。垃圾回收已经有了很大的进步,在大多数类型的应用程序中表现良好。但是,为了进行垃圾回收,您需要暂停并中断应用程序以收集垃圾。这可能会导致定期出现卡顿。

对于实时应用程序,Java也存在同样的问题。当任务必须在特定时间运行时,很难让自动化任务(如垃圾回收)尊重它。

Java并不是缓慢的,而是不擅长处理实时任务。


1
如果你要将Java移植到新环境中,你可以编写自己的垃圾回收调度程序。无论如何,内存都必须被回收,在实时环境中,你可以选择何时安排垃圾回收...这是两全其美的最佳选择。我必须回到这一点,即当C/C++已经为你完成了这些工作时,没有太多的理由将Java移植到架构上以执行你想要它执行的任务。Java在其他方面表现出色。 - San Jacinto
5
这不是20世纪90年代了。当调整为低暂停时,垃圾收集器现在相当出色。 - Tom Hawtin - tackline

8
很大的原因是视频游戏通常需要直接了解底层硬件,但对于许多架构实际上并没有很好的实现。正是对底层硬件体系结构的知识使得开发人员能够尽可能地提高游戏系统的性能。如果你可以直接编写游戏,为什么要在一个游戏平台上运行Java并在其上编写游戏呢?此外,这不仅是“速度”或“没有正确的库”的问题。这两个问题与此密切相关,但更多的是“如何让像Cell B.E.这样的系统运行我的Java代码?没有真正能够管理管道和向量的好的Java编译器。”

7
性能问题是第一个原因。当你看到Quake引擎中的超级优化C++代码(http://www.codemaestro.com/reviews/9),你就知道他们不会浪费时间在虚拟机上。
当然,可能有一些.NET游戏(哪些?我很感兴趣。真的有一些CPU/GPU密集型的游戏吗?),但我猜这更多是因为许多人是MS技术专家,并且在微软推出新技术时跟随了微软。
哦,而跨平台根本不在视频游戏公司的考虑范围之内。Linux市场份额仅约为1%,Mac OS稍微高一些。他们肯定认为放弃仅限于Windows的技术和库,如DirectX,不值得。

3
“跨平台对于游戏公司来说并不是首要问题”,这就是为什么我非常尊重那些能够实现跨平台的公司。 :) - Sasha Chedygov
我非常感激 Carmack 对跨平台和开源的执着贡献。我只是陈述了大多数公司的想法。 - Ksempac
1
这是真的。你不会看到很多受欢迎的视频游戏移植到Linux上。 :( - Sasha Chedygov
跨平台不仅仅是跨操作系统。想想PS3、Xbox 360和Wii。 - JulianR
据说《模拟城市:社会》是用.NET编写的;我不记得它是用C#还是VB.NET编写的,但无论如何,图形相当不错。然而这个游戏非常糟糕...对《模拟城市》系列造成了极大的伤害。 - KSwift87
显示剩余2条评论

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