10 ms·
C or C++ for my game engine?
- girvo 11y agoI agree wholeheartedly with most of this post, but ended up coming to a different conclusion to the author. I don't trust myself to write good, maintable and safe C, so instead my semi-toy game engine has been (and is being) authored in Nim instead, which I've found quite interesting. Writing safe wrappers over C-libraries is a challenge in and of itself!
- dikaiosune 11y agoIsn't Nim (and almost all of its standard library) garbage collected by default? I've been very intrigued by Nim but it seems that while it has nice native/C code generation, it opts into my least favorite element of "high-level" languages.
- girvo 11y agoIt is, yes, however it's a bit different to most other GC-based languages in that it's soft-realtime tracing GC. In addition, you can manage your memory completely manually if you like, and in-fact thats how you interface with C libraries, which I can say from experience works much nicer than I honestly expected going in to it. Excellent reference regarding Nim's GC and what it does differently here: http://nim-lang.org/docs/gc.html http://nim-lang.org/docs/gc.html
- seibelj 11y agoThank you for this very detailed and interesting write up.
- fizixer 11y ago> I have to choose between writing duplicated code, writing a code generator, or tedious macro stuff for generic code. Code-generation all the way. Use an expressive language like python/lua/tcl/lisp/scheme to work on a higher layer than C. Two-language programming (one GC scripting, the other C) beats the heck out of C++, in terms of best of both worlds: expressivity in higher layer, performance in lower layer. C++ has a dirty secret no one likes to talk about. Stroustrup himself was a two-language programmer. C++ was C with classes where the classes were built with unhygienic C macros. When he decided to show his work to "average joe programmers" of the world, he turned it into one language (it turned out he was not a very good language designer so the world has to live with it). If you're working with C++ you are Stroustrup's average-joe customer. If you're working with two-language programming you're Stroustrup himself (even better cz you're using a higher language way better than the C macro system)! Other than that. You want superpowers? give your text-editor your C parser (something similar to this [1]). Structured-editing can do amazing productivity gains in C. This is something I'm still looking into (using some vi/vi-clone, or emacs/emacs-clone, and pycparser) but I very excited about the possibilities. [1] https://www.jetbrains.com/mps/ https://www.jetbrains.com/mps/
- gnarbarian 11y agoScript it out in python then replace the hot spots with c!
- Franciscouzo 11y agoOr better yet, Lua!
- gnarbarian 11y agoWhy do you prefer lua?
- gaze 11y agoPassing through the pile of fun that is the c ffi
- microcolonel 11y agoI generally support this approach. I have liked working with C and chibi-scheme. Though I think depending on the size of your game logic, it may make little sense to even bother with a scripting language. There are real costs to building the abstractions needed in order to make a useful scripting environment.
- deleted 11y ago[deleted]
- deleted 11y ago[deleted]
- gone35 11y ago[1] https://www.jetbrains.com/mps/ https://www.jetbrains.com/mps/ Tried to visit that site, but all I get is this message: "Sorry, your browser is not fully supported. There may be some issues with pages layout in your current browser. Please use an alternate browser until we resolve the issues. Thank you." Since when is it OK to just refuse to serve a page if it's not 'the right' browser? Is this a thing now?
- 11y ago
- santaclaus 11y ago> When using OOP, like the idiomatic C++ coder does Huh? Sure, you can go OO architecture astronaut in C++, but if that isn't a good model for your problem, don't do it. I see more of a focus on generic programming, anymore, in C++.
- Apocryphon 11y agoHas anyone attempted using Objective-C for game development outside of iOS gaming? It'd be interesting using it as an OO language substitute for C++.
- kitsunesoba 11y agoI’m sure there’s been Mac games written in Objective-C, but there are certainly no cross-platform games written in it because vital bits of Objective-C aren’t actually part of Objective-C; instead, they’re part of the Foundation framework in OS X and iOS. You can compile Objective-C on whatever platform you like through GCC but you’re going to have to write your own memory management, allocation, etc among other things in order to do so. That said, you might be able to write a cross-platform game through open source Foundation/AppKit implementations like GNUStep and Cocotron, but keep in mind that they implement a version of Foundation that’s several versions behind now. The next closest thing is probably Swift alongside Apple’s FOSS reimplementation of Foundation for Swift, though I don’t know how well Swift works for development with OpenGL and such.
- gaze 11y agoNo. It has the speed of smalltalk and the type safety of C.
- iainmerrick 11y agoThat's a nice soundbite, but not really fair. Modern Smalltalk-style languages can be fast. Look at Javascript! And in Obj-C, you can drop down to plain C when you need the speed. It's possible to get your types mixed up when using non-generic collections, and that will throw an exception at runtime. No different from Go or Python. In terms of memory safety, it's a step up from C if you use ARC, as all your object lifetimes are managed automatically. You can still get memory corruption if you're careless with arrays, but it's not really an issue with objects.
- wmil 11y agoThere isn't much reason to. Without the Apple libraries and XCode support Objective-C isn't anything special.
- rootw0rm 11y agoI can sense the pitchforks coming out already! A quick disclaimer first of all: I LOVE C. Love love love it. I'm a reverser so it's my native tongue. I get as much joy from the actual creative process of coding and playing with pointers as I do from having a reliable working finished project. No offense, but I think you suffer from the same problem. You're in love with coding, so being forced to micro-manage things the 'C' way isn't a problem for you. But at some point in time you have to look back and justify the hours spent. You -will- be more productive by having the majority of your code in C++ 11. Things -will- be easier to maintain for yourself and others. I have written absolutely brilliant C code that I'm very proud of, but if it's been a while since I looked at the project I have to sit down for an hour and re-familiarize myself with how things work....and I'm the one who wrote it. Based on what you've written I can tell that you don't have the experience to justify writing the bulk of your code in C. Guys who inline ASM all day long can have a hard time doing that. I know it's harsh, but it's meant as helpful criticism. One other thing: You don't have to pick just C or just C++. If you have engines in your project that are clearly better in C and you enjoy doing it, more power to you....I encourage you to do that. However, it's very easy to get hung up on C and lost in your own C world of imagined optimizations. My advice: Start off with solid C++, move parts to C later on when testing justifies it and your amount of free time justifies it.
- microcolonel 11y agoI don't think you're addressing the concerns which made him choose C. In his case: debugging is complex, compilation is slow, name mangling is unreliable, global state is abound. He makes no mention of inline assembler, nor does he encourage premature optimization. He talks instead about a concrete problem he had: the typical performance of operations was not good enough, thus no single optimization would help much. He also mentions that the abstractions encouraged by C++ do not help you build data-oriented applications (e.g. games); using them properly actually hurts performance.
- amagumori 11y agomeh - imo, even if C++ is a ridiculously bloated beast, it has some things that are indispensable for game programming that C doesn't. vector math without operator overloading is gross. being able to have generic containers with templates is really useful, even if templates are gross. encapsulating functionality in classes is always useful, and you can get a lot of use out of inheritance without overusing it. these things are really codebase readability and maintainability concerns, and to me they're orthogonal to "data-oriented programming", things like optimizing for cache locality, SoA instead of AoS, not calling virtual methods in warm or hot paths, throwing away malloc and using purpose-built custom allocators, SIMD/AVXify all the things, etc. etc. it's a lot harder to handle the insane, byzantine complexity of a game engine in something as pared-down as C. with that said, i don't like C++ and i definitely don't think it's a beautiful language by any means. jonathan blow's new language, jai, is very interesting. purpose-built for game programming. check it out if you don't know about it yet. it's looking really promising for all types of high-performance, game-like projects.
- nine_k 11y agoI'd hazard to offer Rust :) Someone has to.
- Rusky 11y agoThe author does mention Rust: > New and hip GC'd languages don't care about the priorities efficient game engine code has. Safety-enforcing languages like Rust are going somewhat off already by definition, as they're focusing primarily on safety, which is not the focus for most game code. However, I disagree with this. Rust does enforce safety, but once you have a feel for how the borrow checker works (which isn't hard at all coming from C or C++), it fades into the background. The real benefits of Rust for games are the build system, the module system, affine/linear types, and all the various syntactic features like pattern matching and expression-based control structures that make it way less crufty to read and write than C or C++. Rust's biggest weakness for game dev (again) isn't the enforced safety, but the still-growing ecosystem. There's a few really good low-level libraries (Glium, for example), but if you stray beyond them it turns into a nightmare of writing your own FFI definitions and unsafe glue code.
- dllthomas 11y agoRight. The last ultra-performance-oriented work I did (in C) I'd have loved affine types and a borrow checker. Used right, these kinds of tools not only don't get in the way (as you note) but prove tremendously useful when you need to refactor.
- munchbunny 11y agoThe library thing is huge. If you're in C++ land you've got UE4 and a large number of open source graphics engines (Ogre3D), plus far more options in every category of engine (OpenAL, Box2D, and so on). If you're in .NET/Mono land you've got Unity and a plethora of engines built around Unity. It's ridiculous how much work these engines will save you, once you know how to use them, but ecosystem is key because these engines are HUGE.
- flohofwoe 11y agoCompletely agree, this is why most game developers use only a subset of C++ as "C with classes", and at the end of that thought process some are going back to C completely (I haven't made the jump yet though, but have been pondering this for at least 2 years). What I still like about C++: - user-provided code called when an "object" goes out of scope - operator overloading sometimes makes sense - simple template-meta-programming sometimes makes sense (but could be replaced with other sorts of code-generation) 3rd party libraries are usually a pain to integrate when they have a C++ interface, and usually simple when they are just a C header, and when they can simply be dropped in as source into the project. A good middle-ground is probably to build the building blocks in C, this way they are way better reusable then writing C++ code, also across languages, and tie the low-level buildings blocks together in whatever language one likes (even interpreted languages). [edit: formatting]
- krisdol 11y agoMost are not writing their own engines anymore. In this day of mobile and web gaming, indie developers everywhere, and game engines like Unity and UE4 being so accessible, I think more game developers are writing games in Java, JavaScript, C#, and other garbage collected languages -- not to mention "visual programming" of Unity and UE4. If you're writing a game engine in C/C++ today you're probably never going beyond the desktop Windows platform.
- taloft 11y agoPerformance will be back if VR gets adopted. At 90 fps, you have around 11 milliseconds to update your game state and render views for each eye. That is not much time. C#/unity and scripting languages will have a noticeable penalty compared to native C code. Bloated engines will likely suffer as well.
- dahart 11y ago> 5. realize that I shouldn't be using some parts of C++ (exceptions, stdlib) > 6. start to ponder if I really need even the good parts of C++ This reads like wisdom and maturity to me; unfortunate, but not surprising, that people are quick to judge. Last game studio I worked at, we wouldn't have given up C++, but there were frequent conversations about its pitfalls and complexity, and quite a few rules and conventions recommending against, out outright prohibiting some C++ practices, exceptions, for example. Before that, the last film studio I worked at, a bad experience with C++ led them to chuck it (before I got there) and go object oriented C. I learned their style of C and quite liked it. I missed operators and templates a bit, and it felt a little verbose, but I came to really appreciate the simplicity and explicitness. Sounds like it wasn't an easy choice, but on a solo project that large you have to prioritize what makes you feel the most productive in the long term, and there are always tradeoffs.
- na85 11y agoI don't use C++ for anything serious, can you explain what's wrong with exceptions and the std lib?
- dahart 11y agoI wouldn't say "wrong", this is a subjective issue, and some people like them. It's just that exceptions can be dangerous, in a sense, because a very innocuous looking line of code or function call can end up executing something you don't expect, or your function can bail out before you expect. It's similar to how inheritance and virtual functions hide (encapsulate) what's going on, but also obscure execution too. Usually the encapsulation is good, but when you need to know exactly what's going on, they can throw wrenches at you. It can be really hard to figure out all the possible errors that could be thrown, or code paths that could be taken in any given case. I don't know the specific reasons std lib was mentioned, that's a big topic. But generally in the context of a game engine, you need all custom memory management and I/O, so there isn't much place for std lib, depending on which std lib pieces and which platforms and which C++ you're talking about.
- spoiler 11y ago
- jeffdavis 11y agoI can't help but think the author would benefit from some of the philosophy of James Hague (a game programmer): http://prog21.dadgum.com/ http://prog21.dadgum.com/ Don't focus too much on technology, disconnected from what people (including you) might want to actually use. Otherwise you will not get the real inspirations -- even purely technical inspirations -- that come from something that you intend to use.
- crafn 11y agoI get where that comes from. I surely did have the disconnection some years back, but think I'm on a better track now. Thanks for the link.
- andrewchambers 11y agoI have recently started using myrddin (compiler here https://github.com/oridb/mc https://github.com/oridb/mc ) as a c replacement. It is still changing fast but I think it could be great for writing games in the future.
- shmerl 11y agoWhy not Rust for example? If I'd be making an engine, I'd tried that.
- dikaiosune 11y ago"Safety-enforcing languages like Rust are going somewhat off already by definition, as they're focusing primarily on safety, which is not the focus for most game code." I don't really agree with this assessment (I think rust's "safety guarantees" really amount to amazing compile time programmer assistance), but that's their stated reason.
- pjmlp 11y agoWhat many that issue that kind of statements forget, is that safety is also a means to keep the game experience clean. Exploiting buffer overflows, stack corruptions and friends is how we get to earn extra lifes, bypass hard levels, get extra ammunition and so on.
- dikaiosune 11y agoAre you saying those are good things or bad things in the context of games? As I commented elsewhere, it's not that I don't think that Rust's safety isn't important, but it's not the only worthwhile element of the language and I think it's good to recognize that its safety guarantees can eliminate many "non-safety" bugs in many programs.
- pjmlp 11y agoI am saying they are bad things, then again game developers aren't known for worrying 1s about safety anyway, specially if that implies 1ms less, even if that isn't an issue for the game being developed.
- shmerl 11y agoThe major benefit is simply avoiding all kind of crashes which plague many games.
- nly 11y agoA good article, but what disturbs me is that the author, while obviously aware of relatively good C++ and programming practices, has somehow arrived in a place where he discounts essentially all of C++s core competencies... like claiming RAII is "far from optimal", that exception safety is "a constant mental overhead", and that copy and move semantics involve writing "a lot of code". These are fairly outrageous claims, and it all smells of total burnout, and losing sight of the forest for the trees, to me. I feel if the author refocused on his C++ basics instead of bemoaning lots of peripheral crap (like OOP, and the unsuitability of the STL for game dev) he'd reconsider some joy in C++ again.
- crafn 11y ago>These are fairly outrageous claims, and it all smells of total burnout, and losing sight of the forest for the trees, to me. Maybe, I don't know. I have been a lot happier with C though, while still writing some C++ code during the year.
- greyman 11y agoInteresting, since I feel just the opposite. In C++, most of the time, I can write the precise intent of what the code should do, and I can also choose the level of abstractness, without compromising on performance! I think the main trick with C++ is to learn the best practices first, and only use those one thoroughly understood.
- lmm 11y agoI'm happy when I'm writing C. It's only when I look back on a week of coding and realise how little functionality I implemented that I realise it's a bad idea.
- cLeEOGPw 11y agoI think one of the main reasons why he did what he did is his motivation, or lack of it while working with C++. Whatever rational arguments would point out to C++ will be essentially meaningless if he is not happy writing with it. That's why discipline is so important in any work. Motivation can get you just so far. It is highly volatile and unreliable. I think it's safe to assume that the author soon will get tired of C and move to languages like python and write an article of how optimizations aren't that important compared to productivity and how critical parts can be written in C, etc. Great article for his perspective and some pros/cons of C/C++, but take it with a grain of salt.
- crafn 11y agoAuthor here. I'm positively surprised, constructive discussion on internet! There's been some discussion about using Rust. Rust is an interesting language, and has definitely potential substituting C and C++ in some domains. The main reason I'm not so interested in using it is for game development, is because it's more complicated than C (like C++), and the complications are a bit off from what I'd want (like in C++). Just a quick googling reveals that rust mangles names by default, and doesn't have reflection, so I'd probably be in for a lot of negative surprises. Add that with being indifferent about the absolute security, and soon my code is mostly inside unsafe blocks so that I don't have to spend time convincing the compiler my pointers are safe. Maybe. I haven't done much programming in Rust. There are some nice convenience features though, when comparing to C, but they seem to be rather minor things. It comes down to choosing between two non-ideal solutions. I value simplicity more than some, so favoring the simpler one feels more natural to me. Sure, when you need the safety then Rust seems like a decent choice.
- anp 11y agoOnly responding to one element of your comment -- but I think that Rust's safety features are over-marketed in my experience. The safety Rust offers is only part of a package that provides high-performance high-level abstractions over functionality that is normally very bit-twiddly in C. So far, my favorite thing about Rust is not its safety, but how easy it is to write good performance software using abstractions that are as convenient as Python (or another high-level language). The safety is just icing on the cake at that point (for me at least). EDIT: Re: pointers -- Rust is a lot easier to write if you just ignore pointers. Really. Either pass small structs by value or pass references (either immutable or mutable), and let the compiler handle the actual pointer manipulation.
- pjmlp 11y agoI think they are marketed exactly well. If it wasn't for the uptake of UNIX, we probably would never had to discuss about memory corruption in 2016, other than writing stuff like device drivers. There is now a whole generation that thinks C was the very first systems programming language, the compilers were as good on day 1 as they are today and it has became some kind of sacred cow. http://www.itsecdb.com/oval/definitions/product-47/0/Linux-Linux-Kernel.html?family=unix http://www.itsecdb.com/oval/definitions/product-47/0/Linux-L... Regarding memory corruption and games, it is how we get around to achieve game cheats.
- vskarine 11y agowhat are your thoughts on using D? I find it to be a better C++ and a step up from C.
- Qantourisc 11y agoA lot of games run on Mono/.net Java etc. IIRC these languages have far more overhead. (I could be wrong.) So unless you suspect you need >9000 fps OR you are going to be doing a LOT of processing / complex game you might not need to worry about it ?
- jcranmer 11y agoThe JVM can run pure Java code to within 2× of native code (although it has a pretty weak vectorizer, so if you're getting vectorized speedups in native code, Java won't get you that). However, calling a native function from Java is a really high overhead call. Which means that the core engine likely can run at essentially the same speed, but the graphics is going to be slower.
- tormeh 11y agoNote that this is the default, standardized behavior. If you're willing to use Oracle (and I think by extension OpenJDK)-specific features then there are some functions with "unsafe" in the name that allows you to hand over memory directly to native code, instead of copying it over. The default behaviour is to copy all memory passed in and out of the JVM, so as to avoid native+java+GC messing with the same memory area (potentially at the same time).
- animal531 11y agoSame problem writing the engine in C#. You often run into memory and GC problems that are a pain to work around.
- alkonaut 11y agoBoth CLR and JVM can be fast, it's not that. It's slower than C++ still, but not by much. In some benchmarks a Jit:ed lang can actually be faster. However, the real reason Java and C# apps are most often much slower than native apps is because idiomatic C# and Java is a lot more work to execute. If you want to write really high-performance Java or C# code, you have to make it allocation free on hot paths, you have to be very careful with what types are on the stack and which are on the heap, and you have to pay a lot of attention to data layout (In java that doesn't have structs especially, making lots and lots of types as SoA instead of collection of objects for example). The bottom line is: while you can make C# and Java code run really fast, it's very hard and non-idiomatic C# and Java code you end up with. It's so hard, that it's actually no easier than writing e.g. Rust or C++ code to do the same thing! And that is exactly the point where C# and Java no longer makes sense: if you can't use the idiomatic and ergonomic way of writing it, it has lost its value.
- rurban 11y agoI would look at one if those new type and memory safe languages which are more pleasant to work with and usually faster than C/C++, esp. with concurrency. Pony, felix, nim, Julia, Ocaml, elixir, rust.
- golergka 11y agoYou speak about perfomance a lot, but do you actually have it as an important requirement, or is it just fun problem to tackle as programmer? In modern game development, it's usually the latter — most hobby game projects don't have art assets detailed enough to be slow on platforms where your end-users actually will play your game. I make games in Unity/C#, and yes, of course it's slower than a custom C solution. But instead of spending time on writing my own containers and memory allocation, I spend time writing game logic. Instead of optimizing game to run from 100 to 150 FPS on my computer, I'd rather spend this productive time making 5 variants of the same game mechanic to find out which is more fun. Even if the game runs in just 30 FPS. Of course, I sometimes try to research low-level stuff, write my own renderer, or do a small experimental project in pure C, but then my goal is to research, not to write a game. I can hardly imagine a project, where the goal would be to develop a game, and not to research, where using C and having to spend so much time on this matters would be a good trade-off compared to working on actual game mechanics in higher-level language.
- tinco 11y agoUnity is written in C. That the game logic is written in C# is hardly relevant as you explain. In fact this guy might still embed C# at some point if he wishes for his logic to be less painful to write. The author states at the beginning that his goal is writing an engine and only after that write a game. You are right on all other points though, most people working on game engines simply never get to the making a game part. There's simply too much to do. I spent a couple years' working together with a friend every now and then on a game+game engine in C#. We did get past the game engine phase because it was kept simple (ECS + box2d and simple monogame 3d renderer) but we eventually gave up because even though game logic was progressing swiftly assets were just a pain in the ass. Most low level engineers (as we are/were) underestimate the work it requires to get a proper asset pipeline set up. You're never going to build a 3d game if you can't load cheap 3rd party assets with their animations and materials. And then the level designer which is basically just another game in your game. We went with UE4 as a change of pace and man is it librating not to have to worry about the limitations of your homebrew engine anymore. In UE4 literally anything is possible (you have the full source after all) and its always less work.
- jbb555 11y agoExcellent article. I'm not sure I agree with all the points, but none of them are stupid or necessarily wrong. It's a very constructive argument. I've been thinking for a while that the problem with C++ is that 100 decisions have been made both in the library & language and in "best practice" that all individually are good, but the combined effect has been unfortunate. I'm not quite getting from the article why you can't write in the C "subset" of C++ and add in a few of the more helpful parts of C++ though.
- loup-vaillant 11y ago> I'm not quite getting from the article why you can't write in the C "subset" of C++ and add in a few of the more helpful parts of C++ though. I think this is because of C++ name mangling, which prevents the creation of a quick and dirty reflection system. And maybe compilation times, which must be higher since the compiler has to deal with all of C++, even if you don't.
- jbb555 11y agoAre there any other sources of information on "modern C"? I'm thinking particualrly on how to handle memory allocations well and safely, and how to write clean containers and algorithms. It's been a long time since I wrote pure C and I'd like to try it again!
- andyjohnson0 11y agoThis reminded me of Banished [1], a game developed by a single developer who also wrote his own engine (though in C++). His development blog [2] goes into quite a lot of technical detail. [1] http://www.shiningrocksoftware.com/game/ http://www.shiningrocksoftware.com/game/ [2] http://www.shiningrocksoftware.com/ http://www.shiningrocksoftware.com/
- alkonaut 11y ago> are going somewhat off already by definition, as they're focusing primarily on safety, which is not the focus for most game code. Depends on what you consider safety to be. A game engine that doesn't deadlock and doesn't crash should definitely be high priority!
- hellofunk 11y agoAs soon as I saw this headline, I knew there would be dozens of comments. First of all, they are both great languages, no matter what anyone tries to tell you. I went through this same dilemma and, while I have great respect for C, I soon realized that my situation would be more productive with C++ and its tools immediately available. For one thing, a lot of important libraries that are common in games and graphics have C++ interfaces, so if you use C you are asking of yourself to exclude some great tools out there, or, go through significant steps to wrap some of them (which would still involve some C++ anyway).
- jongraehl 11y agoEvery one of his complaints has a good solution, albeit some not widely known. Except compile time, single source file or otherwise - the compiler is using lots of smarts and lots of library headers on your behalf. That said, author has done a good job explaining his thought process in taking the rewarding-at-every-step path, given he's not a C++-wrangling junkie.
- hellofunk 11y agoWow, I had to change the brightness and contrast setting on my monitor just to read this article. What is the strategy behind this darkish font against black background? I wish more websites geared towards a reading audience actually provided a nice reading experience.