用C编写游戏引擎是否合理?[关闭]


53

尽管C ++似乎是国王,但据我所知,C仍广泛用于游戏中,尤其是在游戏机上。但是,今天用C编写整个游戏引擎会不合理吗?与C ++相比,C有什么优点?为什么有人可能想通过C ++使用C?


1
主机游戏使用C ++ FYI!
艾伦·沃尔夫

实际上,我认为C可以更容易地以一定的规模编写游戏,比如说成千上万的LOC,主要是因为它可以让您只关注比特和字节,而无需复杂的数据类型,并且与C ++相比,构建速度超级快。但是在达到一定规模(例如达到数十万个LOC)之后,我开始想要达到C ++的水平,在那里我实际上开始想要复杂的数据类型,更多的类型安全性,可能的异常,模板,并且在更大范围内扩展(例如数百万美元),以便将C ++以外的其他东西与C和C ++代码结合使用。

C还具有即使对于ABI而言也具有广泛可移植性的附加优点,因此,可以轻松地获取现有的C代码,然后开始使用其他语言(例如FFI)使用它。C ++在名称修改,无法安全地跨越模块边界,vtable代表在编译器之间不一样,标准库实现在供应商之间不同等方面有点尴尬。通常,我发现我编写的C库可以持续更长时间而无需更改,并且过时了,尽管用它写任何比例尺都需要更长的时间。

Answers:


49

但是,今天用C编写整个游戏引擎会不合理吗?

这是合理的,但问题是它能给您带来什么?您可能不需要C提供的极端可移植性,并且放弃C ++提供的所有功能实在可惜,除非您真的从哲学上反对它。

与C ++相比,C有什么优点?

更好的编译时间?

为什么有人可能想通过C ++使用C?

我认为这主要是审美选择。许多人喜欢C,因为它简单,最小并且感觉很干净。C ++具有很多不错的功能(仅名称空间就值得使用),但它又大又杂乱。


3
直到Id Tech 4
配镜师

9
@Josh:更容易调试!众所周知,C程序很难调试,主要是由于指针和内存管理。C ++程序(使用真正的C ++编程习惯用法时,往往会尽可能避免使用指针和内存管理),调试起来容易几个数量级。
BlueRaja-Danny Pflughoeft,2010年

14
C可以被凡人理解。C ++似乎具有很多功能和经验丰富的程序员,即使在每天使用它生活10年之后,他们仍会学习。
Jari Komppa

13
C ++是一门大语言,但是令人恐惧的声誉主要是由那些刚刚读了恐怖故事而又没有花时间去学习它的人传播的。有很多东西要学习,但是您会从中获得很多价值。C ++使您可以表达很多C根本无法做到的事情。
优厚的

2
@ BlueRaja-DannyPflughoeft #define malloc(x) my_malloc(x) #define free(x) my_free(x),您现在正在调试内存。使用C ++,您永远都不知道什么时候会分配什么,因为分配内存的方法有很多(新的,malloc,类构造函数等)
YoYoYonnY

59

我已经与已经交付了多种产品的纯C游戏引擎进行了广泛的合作,因此这是绝对可能的。这是我在C和C ++引擎中工作的个人经验:

  1. 使用纯C结构使您可以利用有关结构对齐的知识,然后可以使用此信息来构建对象持久性和序列化层。我使用的引擎具有一些简单的标头解析器,这些解析器会自动创建有关结构的元数据,并使某些类型的数据操作变得微不足道。解析任意C ++头文件在本质上是不可能的,并且一旦添加继承和虚函数,您就无法准确知道事物在内存中的位置
  2. 编译时间大大缩短,因为您可以使头文件保持紧凑并利用结构的前向声明。
  3. 可以改进调试,因为无需使用模板和继承就可以很容易地准确地确定某个对象是什么以及它在做什么。

使用受约束的C ++代码(避免使用模板和对序列化对象的继承),也可以轻松实现所有这些好处,但是CTO决定,如果不使用C ++更加令人困惑的元素,则可以更轻松地实现简单性可用。

我个人认为这有点极端,因为我确实错过了在for循环中明智地声明变量以及继承的许多完全合法用途的能力。但是,考虑到所有因素,最终并没有使我们付出太多生产力


5
确实没有什么可以阻止您在C中实现继承。而且,如果您使用C99,则可以在for循环中声明变量。
jsimmons 2010年

15
不同意第3点。使用C语言编写混乱且难以调试的代码与使用C ++语言一样容易。更好的调试不是C语言所固有的。
丹·奥尔森

7
在C ++中,甚至连干净的代码也很难理解-带有重载,模板,虚函数和异常,一眼就能看出确切的实际控制流程将变得更加困难。
Kylotan

6
@Dan:仅仅拥有更多东西,C ++就很难调试。你当然可以使用任何东西,在这种情况下变得易于调试为C限制自己-因为它变成C.

较少的东西实际上就是我喜欢C的原因。例如,在CI中,可以随便用a复制任何位和字节,memcpy因为类型系统不允许复制ctor和dtor之类的东西。我可以编写代码,知道我几乎不必在任何给定的代码行都回滚副作用,因为除非我明确地退出该函数,否则我不能隐式退出该函数。没有异常被抛出。所有这些使编写数据结构变得非常容易-在C ++中,仅编写符合标准的文件vector非常耗时,特别是如果您要使其成为标准文件……

18

我正在将用C ++和Lua编写的2D游戏引擎重写为C和Lua。到目前为止,经验非常好。显然,在C语言中进行向量和矩阵运算的效果不佳。但是除此之外,我发现作为C ++开发人员花了10年以上的经验使人耳目一新。

与C ++相比,C具有许多优点:

  1. 编译器将确保在静态初始化时不运行任何代码。这样就完全可以安全地静态分配全局数据,例如用作键的字符串。
  2. 透明度。在C语言中,赋值或分配或定义变量不会导致代码运行。C ++将自动为您生成副本构造函数,因此您对分配时执行的内容的控制较少。
  3. 由于没有弄乱函数名,很多调试可能更容易
  4. 在C中使用memcpy通常是可以的,但是在C ++中很容易引起麻烦,因为不会运行复制构造函数。鉴于memcpystd :: copy要快得多,因此很重要。

除此之外,进入C思维方式还有许多优点。在C ++中,我经常发现自己使事情变得过于笼统和抽象。在CI中,通常会删除诸如get-set方法之类的东西,并且通常会预先分配固定大小的数组,而不是使用动态数组。通常,我最终会在C语言中得到更短,更容易调试的代码。数据结构通常更平坦,更易于在调试器中查看。

公平地说,我永远不会只使用C来开发应用程序。我之所以将它与高级语言(例如Lua)结合使用的原因是,如果C语言不是那么强大,它可以很好地补充C语言。

Id软件使用CI编写了他们的大多数引擎,您可以看一下用C编写的《重返城堡》

我写了一些有关C vs C ++可伸缩性的经验,以及与普通数组相比STL向量的缺点。


11
仅供参考,在我检查过的每个实例中(我认为是darwin gcc和vc2008),如果两种类型均为POD,std :: copy只会编译为对memcpy的调用。
布拉夫

3
另外,RE:STL向量与纯数组,为什么不使用向量的漂亮部分,如果不喜欢它们,则使用普通的C指针而不是迭代器?您可以只做&myvector [N]。假设您的C代码以相同的方式进行内存分配,这就像两全其美。或者,在for循环中,签出BOOST_FOREACH。使得它甚至比C简单
BRaffle

1
感谢您提供有关std :: copy memcpy的提示。我不知道 几年前亚历山德列斯库(Alexandrescu)对待这种情况时并非如此。关于C ++迭代器。这主要是关于哲学的问题,我尝试编程C ++是为了与我一起工作的人们以及为了利用C ++功能而编程的意图。主要是为了指出一些S ++容器之类的C ++改进并不总是比旧的C方法更好。
Erik Engheim 2010年

7

正如其他人指出的那样,C ++带来了可以站起来的大肩膀(BOOST,STL等)的优点。最后,这是个人选择,但由于可用资源,我会选择C ++。如果您不希望使用C ++中的功能,请不要使用它们。


1
请注意,出于各种原因(性能保证,可调试性,线程安全性,控制性),有99%的商业和内部游戏引擎偏离了Boost和STL。
Kaj 2010年

42
99%的统计数据都已组成。
布拉夫

我觉得引用所有统计数据应该有点规则。
马特·詹森

3

我认为现在没有人专门使用C,通常将它与高级语言混合使用。

例如,用C进行编程比使用C ++进行编程有一些好处。C ++ 可以做很多用户看不见的事情,如果不注意的话会损害性能。C ++ 可以也很糟糕,当涉及到高速缓存使用,这也可以伤害你的表现。

因此,以类似C的方式而不是传统的C ++方式编写游戏的性能关键部分可能会带来一些好处。近年来,我从未听说过有人用C编写整个游戏。

在某些平台上,例如iPhone,使用C ++可以将可执行文件的大小增加一定的千字节(我忘记了多少,对不起),这就是一些iPhone开发人员选择混合使用C和Objective语言编写代码的原因-C。


3

我将为您提供更多的理由,说明为什么现在用C而不是C ++编写游戏引擎是不合理的:STL和BOOST。

我无法想象list当您可以依靠开箱即用的代码(而不必编写!)时,再编写一个实现是值得的。


1
大型工作室是否真的使用Boost?由于可移植性,甚至STL的使用仍在争论中。至少对于控制台引擎。
slicedlime

2
就我个人而言,我使用Boost.FunctionTypes进行c ++ / lua交互(请参阅gamedev.net/reference/programming/features/CPPLuaExport/…)和Boost随机数库,以生成统一的随机数(适用于粒子系统)。另外,Boost.Foreach整洁。顺便说一句,谁在乎大型工作室是否不使用BOOST?他们有能力从头开始编写自己的STL库,我没有。
洛里斯(Loris),2010年

1
是的,但也意识到C也有类似的库。
jsimmons 2010年

2
我相信,很多人在游戏中使用增强功能。但这对我们许多人来说并不是一个要求(甚至是理想的)。
丹·奥尔森

6
人民,您认为无关紧要的是:您知道还是不知道
o0'。

3

用C编写游戏引擎是合理的。它速度很快,可以移植到多个系统。例如,您可以使用Android(使用NDK)。您可以在iPhone上使用它(目标c只是c的扩展)。您也可以将其用于主要操作系统,例如Linux,Mac或Windows。如果您对c感到满意,建议您尝试一下!


2

当然是合理的。我个人不会这样做,而且我认识的大多数C爱好者实际上只是在.cpp文件中编写类似C的代码。但是这些语言与实际上无关紧要的地方足够相似。

至于为什么有人会选择这样做,我认为这主要取决于反C ++的哲学。就我个人而言,我仍然不认为这是选择C而不是“ C-style C ++”的好理由。typedef struct Crazyness是避免使用C的充分理由,还有很多其他原因。

不幸的是,当我们开始使用C和C ++时,它们都是非常糟糕的语言。这就是近年来人们试图在脚本中执行许多代码的原因之一。

如果您正在寻找使用C语言工作的人的例子,您可以忽略id,因为我记得他们早就放弃了C语言。不过,Cryptic Studios(《星际迷航》在线)使用C语言进行所有引擎开发。据我所知,是的,这更多是因为哲学,而不是任何明显的优势。


0

是的,没有。是的,几年前我已经做到了,但是我需要我的游戏在不带终端的播放器上的Unix(不是Linux)64位远程服务器上以3D模式运行。这是不平凡的。如果您想集成LUA,C可能很好,但是我最终使lua可以在C ++中工作,所以我会说是可以的,但不要这样做。


0

可能的好答案是“同时使用”吗?

据我所知,可以优化panda3d项目,使用某些cython或重新编码这些部分来消除瓶颈。

在大多数情况下,需要优化的部分是具有大量迭代和嵌套或大量数值计算的部分,因此,我的(疯狂的)猜测是,一种公平的折衷办法是同时使用两种语言,并使用C语言。对于包含许多底层编程的部分,因此对于需要速度的部分,您不能滥用C ++语言,对于其余的游戏,则不能滥用C ++。

理想情况下,您要牢记高级知识,着眼于引擎的快速部分,然后使用脚本语言或C ++,它将使用更少的嵌套/循环。

当然,除非您将引擎专用于一种特殊的游戏,否则您永远无法制造出适合开发人员所需的所有游戏的引擎...

但是,请不要接受我的建议,因为我既不是经验丰富的游戏开发人员,也不是经验丰富的开发人员...我认为C会迫使您编写快速的代码,同时为像游戏一样大的项目编写良好而快速的C ++代码是另一回事...



0

C代码通常是有效的C ++代码。

C ++的主要问题是错误地使用了它(Linus Torvalds讨厌它,因此,他在库的可移植性方面也遇到了其他问题,例如,他正在操作系统级别上工作,必须能够在每个随机变量上运行它芯片在那里)。

例如,与c ++ std :: vector <>(或类似容器)相比,使用cstyle array []几乎没有优势。

向量是类型安全的,并且可以进行边界检查(您可以使用get()或[]访问元素,即使您不使用数组检查的方法,您仍然可以查询大小,而不用指针四处移动)。

但是,载体可以慢一些,如果,例如,你不声明构造函数中的默认大小。另外,如果向向量中添加内容,则可能需要减慢其大小。C ++ 11还增加了许多优点,例如统一初始化(您现在可以使用相同的语法声明和初始化向量),并且有move构造函数可以使您避免复制。您甚至可以创建自己的自定义初始化程序(如果您出于某种原因想要使用malloc以外的其他方式)。

或者当然,如果您确实需要调整大小,那么向量仍然更易于使用,您不必弄乱malloc,手动复制内容等等。

C ++为您提供了面向对象的代码。编译时,它将同样高效,因为它实际上只是使用代码的人员的抽象。尽管诸如构造函数之类的东西可能会减慢对象的创建速度。但是您将需要构造函数设置默认值,否则您可以不使用构造函数来初始化对象(通过省略())。

但是面向对象使编程游戏变得更加容易。游戏经常处理对象。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.