当前位置: 华文星空 > 知识

为什么游戏引擎大多选择使用 C++ 而不是 C 开发?

2015-03-08知识

谢邀,根据知乎的风格,先问是不是,再问原因。

如果想进一步和我交流,可以点击下面的名片咨询:

首先,就游戏引擎来说,使用 C++ 开发的和使用 C 开发的,大致可以说是平分秋色,这大致有三方面的原因:

1. 历史原因

C 语言诞生比 C++ 早,C 语言诞生原因是因为 Unix 操作系统,而 Unix 操作系统的诞生原因则是由于「玩游戏需求」,以下来自 wiki 百科的 C 语言诞生历史:

1964 年,由美国通用电气公司和麻省理工学院发起了一个合资项目,该项目旨在开发一套能运行在 GE-645 等大型主机之上的多用户、多任务的分时操作系统,简称 MULTICS。
1965 年,贝尔实验室派出开发人员 KenThompson 等也加入了该项目,虽然项目期间发布了一些版本的 MULTICS 产品,但由于运行性能较差,1969 年该项目以失败告终。
由于 KenThompson 酷爱游戏及游戏编程,他在项目 MULTICS 期间编写了一款名叫「星际旅行」(Startravel)的游戏,并运行在该 MULTICS 系统上,但运行速度非常慢,且耗费昂贵。
1969 年 MULTICS 项目宣告失败后,KenThompson 没有放弃其游戏的梦想,他在贝尔实验室的库房中,找到一台闲置的 PDP-7 裸机,但由于缺少操作系统,无法在该 PDP-7 上运行其游戏。在 DennisRitchie 的帮助下,他使用汇编语言为该 PDP-7 编写了一个操作系统雏形,并把其游戏成功运行在了该操作系统之上。该操作系统体现出了很多优势,受 MULTICS 项目开发经验的启发, DennisRitchie 和 KenThompson 在该游戏操作系统雏形的基础上,进一步完善和开发新功能,最终于 1970 年开发出了一款新的多用户、多任务操作系统,称为 UNIX 操作系统。
也就是说,1969—1970 年,美国贝尔实验室的 KenThompson 和 DennisRitchie 等使用汇编语言编写了第一个版本的 UNIX 操作系统。
由于 UNIX 操作系统良好的性能,在其发布初期,就得到迅速的推广和应用。1973 年,KenThompson 和 DennisRitchie 在做系统内核移植开发时,感觉使用汇编语言很难实现。后来决定使用一种称为 BCPL(BasicCombinedProgrammingLanguage) 的语言进行开发,在开发过程中,他们在 BCPL 的基础上做了进一步的改进,推出了 B 语言(取 BCPL 第一个字母)。
后来发现使用 B 语言开发的 UNIX 内核,还是无法达到他们的预期要求,于是在 B 语言的基础上,做了进一步的改进,设计出了具有丰富的数据类型,并支持大量运算符的编程语言。改进后的语言较B语言有质的飞跃,取名为 C 语言,并使用 C 语言成功重新编写了 UNIX内核。
至此,使用 C 语言编写内核的 UNIX 版本已相当稳定,且具有良好的可移植性,为 UNIX 的进一步推广和普及奠定了坚实的基础,也展现了 C 语言与 UNIX 的完美结合及 C 语言在编写系统软件时得天独厚的优势。
由此可见,C 语言的起源与 UNIX 的改进是密不可分的,也体现了 C 语言在编写系统软件时的优势。

通过上文我们可以知道: C 语言诞生于 1969 年至 1973 年间,而 C++ 诞生于 20 世纪 80 年代。

比雅尼·斯特劳斯特鲁普博士在贝尔实验室工作期间发明并实现了C++。起初,这种语言被称作「C with classes」(「包含‘类’的 C 语言」),作为 C 语言的增强版出现。随后,C++不断增加新特性。虚函数(virtual function)、运算符重载(operator overloading)、多继承(multiple inheritance)、标准模板库(standard template library, STL)、异常处理(exception)、运行时类型信息(runtime type information)、名字空间(namespace)等概念逐渐纳入标准。1998年,国际标准组织(ISO)颁布了C++程序设计语言的第一个国际标准ISO/IEC 14882:1998,目前最新标准为 ISO/IEC 14882:2020。根据【C++编程思想】(Thinking in C++)一书,C++ 与 C 的代码执行效率往往相差在±5%之间。

那在有 C 语言而没有 C++ 的年代里,在这二者之间只能用 C 语言编写游戏引擎,同时也培养和沉淀了一大批精通 C 的高手,他们很多转到游戏行业,编写了很多游戏引擎。

2. 开发效率与性能问题

先说性能问题。

对于早期版本的 C++ 来说,确实可以看成 C with classes(今天的 C++ 版本已经不能简单这么认为了)。实现同样的功能,C 语言背后可以直接对应着直白的机器码,而对于 C++ 却不是,C++ 编译器为开发者的 C++ 代码插入了大量自己的代码。有人就说, C++ 相比较 C 语言的最本质的区别就是析构函数 (这句话请认真体会)。

那么如果对于一些追求性能的游戏引擎,肯定就不能接受 C++ 相比较 C 语言增加的性能损耗。例如,那个年代风靡一时的雷神(Quake III),你可以看看它的源码,源码下载地址:

链接: https:// pan.baidu.com/s/10fjHP2 EbuyjsF22dadvJKA 提取码: 6mkt
Quake III
Quake III

关于雷神的开发故事,有一本叫【Doom 启示录】的书,这本书忠实详尽地讲述了两个玩家是如何走上游戏之路,如何制作出迄今为止影响力最大的游戏作品--DOOM和Quake,以及他们为何在最辉煌的时候分道扬镳。本书是国内第一部游戏领域的传记。与所有传记一样,不同的读者能从中得到不同的体验:或是那游戏制作的背景内幕、光环之中的趣闻轶事、年少创业的梦想豪情、奋斗途上的汗水艰辛,亦或是那成名之后的势易情迁,独辟蹊径的商业模式、天下为公的黑客精神、众说纷纭的暴力问题…

【Doom 启示录】高清版 pdf 下载地址:

链接: https:// pan.baidu.com/s/1Z5Q7qX 3hb_YmAMKf9epMXw 提取码: he5h

关于雷神的引擎的源码还流传着一个有趣的故事:

我一个同学在魔兽世界项目组做开发,他和我说,魔兽世界的源码也是使用 C 开发。

魔兽世界
魔兽世界

其实不仅是游戏引擎,对于追求性能的软件项目,例如 Redis、Nginx 等,都优先使用 C,而不是 C++。

再说开发效率问题。

C++ 相比较 C,支持面向对象特性。严格来说,面向对象是一种思想,对于高手来说,使用 C 语言也能写出面向对象的代码来。但是对于普通人来说,C++ 很好地支持面向对象特性(支持 class 关键字),面向对象的基本思想是开发的代码要像现实生活一样,尽量把物事抽象成一个个对象类型,这样可以大大提高开发效率。对于大多数游戏引擎来说,相比较 C 语言,C++ 损耗的性能是可以接受的,使用 C++ 可以大幅度提高团队开发效率,因此会选择 C++。

例如,开源版本的魔兽世界代码(World of Warcraft):

链接: https:// pan.baidu.com/s/1qbyPVN elNGmNMry1gLJwnw 提取码: rr72

大型联机对战游戏——英雄之刃(类似于腾讯的英雄联盟)均属于此类:

链接: https:// pan.baidu.com/s/1TgZTpq TwTgf2QEnfEpoyLg 提取码: gge3
登录界面
进入后台配置的对战服务器
设置自己的昵称
支持新手教学、人机对战和联网对战
部署在我的云主机上后,和女朋友一起对战的效果图
对战马上开始了~~

服务器端有非常多的模块,代码质量非常高,各个服务均使用 C++ 编写,游戏主要服务关系图如下:

英雄之刃架构图
英雄之刃各个服务说明

再比如国产游戏——仙剑奇侠传(英译名:Chinese Paladin 或 Legend of Sword and Fairy,由上海软星开发):

仙剑奇侠传源码及编译部署教程下载地址:

链接: https:// pan.baidu.com/s/1ZAshHk MRTbPQyAoSznddew
提取码: y41g

3. 技术传承和开发人员技术栈问题

和其他项目一样,有些一些项目开始使用的是 C 开发,那么后来的开发者或者维护者,除了一个重大原因,不然也会继续使用 C 开发,C++ 项目也一样,这就是我说的技术传承。

另外,一个原因是,一些开发人员或者团队核心负责人对 C 或者 C++ 更熟悉一些,可能就会选择相应的语言去开发,这是由游戏引擎的核心开发人员或者技术团队的技术栈决定的。

给想从事游戏开发的同学一些建议

如果你不是对游戏开发特别感兴趣,建议谨慎地选择游戏行业!

如果你不是对游戏开发特别感兴趣,建议谨慎地选择 游戏 行业!

如果你不是对游戏开发特别感兴趣,建议谨慎地选择 游戏 行业!

重要的话说三遍,如果你还是想学习游戏开发,下面是一些做好游戏开发的建议:

1. 先学好 C++。

这类书很多,找一本适合自己的即可。不建议看【C++ Primer】这样的大部头,掌握 C++ 常用语法就可以了。当然 C++ 原理性的东西还是需要了解一下,推荐看下【 深度探索C++对象模型 】。

深度探索C++对象模型
链接: https:// pan.baidu.com/s/1Pc-IWg jk9VJ5MrUV1gsxbw 提取码: 511b

2. 学好网络编程,做到熟练使用常见操作系统的 Socket API。

推荐如下两本书:

  • 尹圣雨的【TCP/IP网络编程】(适合网络编程零基础的同学)
  • 游双的 【Linux 高性能服务器编程】(适合有一定网络编程基础的同学)
  • 链接: https:// pan.baidu.com/s/1Ef0raB frYYiFpl6nqLNIKg 提取码: yter
    链接: https:// pan.baidu.com/s/1sJpxJT rV0ErKXWVG0v045A 提取码: gqgp

    看完这两本书,你还能学到一些 C++ 服务器程序框架、结构等一些套路( 上文推荐的游戏源码都是不错的学习资料 )。

    3. 学一些游戏开发的知识

    如各种动画原理、帧同步技术等。

    最后分享一份我精心整理的 C++ 进阶书单:

    好啦,就写这么多啦。

    原创不易,如果觉得有用,请给 @张小方 点个赞~~