Previous discussion: https://news.ycombinator.com/item?id=10870488
Why I Write Games in C (yes, C)
501–510 of 556 posts
Re: Why I Write Games in C (yes, C)
#502Earlier quoted context omitted.
But then what's left of RAII? What resource is there to allocate other than the memory itself? RAII means more than just "get memory to put this in".
Presuming GP includes unique_ptr, there's no real loss of RAII. In my opinion you might as well write trivial classes, but hey, to each his own.
Re: Why I Write Games in C (yes, C)
#503He dismisses C# without even knowing what options he has. The latest stuff Unity has been doing is heavily biased towards data driven design where almost everything is a struct. There are very few classes to be found that use any kind of polymorphism, and it is actively discouraged. You could easily treat Unity as a cross platform rendering engine and asset loading system, and then build your own engine on top of it.…
As a Unity dev this is really generous to Unity. After all it's extremely complex in a way the author would hate. That said, I'd love to see a pure C# engine on .NET core 3 that has access to Span . C# is set up as a great high level language with low level features as long as you're willing to do the work you would have done in C or C++.
I've built a non-trivial engine active from around 2010 to 2015 that targeted all iOS and Android devices. Our test fleet of devices was enormous because we'd run into silly issues that were always device specific. My favorite, one particular phone with one particular driver version for the GPU did not correctly implement the ES 2.0 standard for constant defined variables. It caused our games to crash, and because of the scale of mobile this affected hundreds of thousands of users.
At this point you could not pay me to build an engine, because for anything that isn't a toy you end up having to solve these problems yourself.
Treating Unity as a rendering engine and asset loading system is not immediately "easy", but it's a very far cry from "hard". Dismissing it or other options simply because of unfamiliarity or a shallow distaste for OOP is ignorant at best and actively misleading otherwise.
Re: Why I Write Games in C (yes, C)
#504Earlier quoted context omitted.
I work on an open-source music sequencer ( https://ossia.io ) and no later than two days ago I had a fair amount of mails with someone who wanted to know the best settings for his machine to not have any clicks during the show (which are the audio symptoms of "missed deadline"). I've met some users who did not care, but the overwhelming majority does, even for a single click in a 1-hour long concert.
If it's running in a consumer OS (not a RT one) and it counts on having enough CPU available to avoid missing the deadline, that's exactly what soft-realtime is. Compare your “not a single click in an hour [for quality reason]” to a “not a single missed deadline in 30 years of the life expectancy of a plane, on a fleet of a few thousands planes [for safety reasons]”. That's the difference of requirements between hard…
Re: Why I Write Games in C (yes, C)
#505Earlier quoted context omitted.
There is still the STL, there are still templates and data structures have a very well-defined lifetime.
Isn't the STL mostly classes? How is that not OO?
Re: Why I Write Games in C (yes, C)
#506Earlier quoted context omitted.
Writing game engines in C++ without using destructors is just foolish. If by OOP you mean virtual functions? Nobody uses that stuff much anymore, except Java refugees. (They use shared pointers, too.) But, anyplace you would use a function pointer in C, it's cleaner with a virtual function, and often faster.
> Writing game engines in C++ without using destructors is just foolish. Why? My understanding is that in modern game dev you're mostly traversing large arenas of structured memory, and you avoid freeing individual objects like the plague.
D3D11_MAPPED_SUBRESOURCE mapped;
context->Map( buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
// Write memory address pointed by mapped.pData
context->Unmap( buffer, 0 );
With C++ RAII, you can do something like that instead: MappedBuffer mapped{ buffer }
// Write memory address pointed by mapped.pData.
// No need to do anything else, the destructor of MappedBuffer will unmap.Re: Why I Write Games in C (yes, C)
#507Earlier quoted context omitted.
The last time I encountered GC issues in gamedev, we were seeing 100ms GC pauses (that's 6 dropped frames at 60fps!) every 30 seconds or so. We had poor insight into why, and what we could glean of "why" was that it was a widespread problem with how our designers were prototyping stuff in JS (more specifically, they were writing it as regular JS, instead of jumping through hoops to try and relieve GC pressure through…
> The problem isn't GC per se. In other words, the problem is GC, full stop.
UI solutions often/usually use some kind of GCed language for scripting. But the scale and scope of what UIs are dealing with are small enough that we don't see 100ms GC spikes.
Our tools and editors leverage GCed languages a lot - python, C#, lua, you name it - and as long as their logic isn't spilling into the core per-frame per-entity loops, the result is usually tollerable if not outright perfectly fine. We can afford enough RAM for our dev machines that some excess uncollected data isn't a problem.
And with the right devs you can ship a Unity title without GC related hitching. https://docs.unity3d.com/Manual/UnderstandingAutomaticMemory... references GC pauses in the 5-7ms range for heap sizes in the 200KB-1MB range for the iPhone 3 [1]. That's monstrously expensive - 1/3rd of my frame budget in one go at 60fps, when I frequently go after spikes as small as 1ms for optimization when they cause me to miss vsync - but possibly managable, especially if the game is more GPU-bound than CPU-bound. It certainly helps that Unity actually has some decent tools for figuring out what's going on with your GC, and that C# has value types you can use to reduce GC pressure for bulk data much more easily.
[1] Okay, these numbers are pretty clearly well out of date if we're talking about the iPhone 3, so take those numbers with a giant grain of salt, but at the same time they sound waaay more accurate than the <1ms for 18GB numbers I'm hearing elsewhere in the thread, based on more recent personal experience.
Re: Why I Write Games in C (yes, C)
#508Earlier quoted context omitted.
Also, the C++ committee is very serious about not paying for what you don't use. You can rest assured that there's no unused, hidden C++ bloat that is chipping away at your frame budget. This is not meant to be a strawman against the complexity cost argument, it's just a related feature of C++ that I thought might be worth explicitly pointing out in case anyone is misinterpreting. Also, if anyone has a credible dispu…
You are describing 'zero cost abstractions'. Except that they are anything but zero cost. Game developers and low level programmers shy away from them because of their impact in compile and build times, debug build performance and stack trace bloat, increased cognitive load, reduced refactoring ability. Even std::unique_ptr has runtime costs in release builds that a raw pointer does not. In game development performan…
No, that's a different (and orthogonal) concept. The point is that in C++ "you don't pay for what you don't use" - whether it's a cheap or an expensive abstraction, if you don't use it then its overhead won't affect your code's performance.
However, many of the C++ abstractions are zero-cost in many common cases.
> Game developers and low level programmers shy away from them
No, they don't. They shy away from abstractions which are too expensive; or whose scope of optimization doesn't fit the game's use; or which don't combine well with out-of-standard-library code used in the game etc.
But game developers use _lots_ of C++ abstractions; and fancy non-C-like C++ features.
Re: Why I Write Games in C (yes, C)
#509Earlier quoted context omitted.
How would I create the pointer to int in the unique_ptr case without initializing the int? I tried this: https://gcc.godbolt.org/z/SfVxzU I expect there is a way, just I don't know it.
See the docs : https://en.cppreference.com/w/cpp/memory/unique_ptr/make_uni... For C++ ()` by `std::unique_ptr (new int)` (which with all explicit uses of `new` can end up not being safe in some cases (in that case, only if you've not enough memory to allocate an int which should not really be a common occurence...) For C++ >= 20 you get std::make_unique_default_init which does that properly.
Re: Why I Write Games in C (yes, C)
#510Earlier quoted context omitted.
> Even std::unique_ptr has runtime costs in release builds that a raw pointer does not. O RLY ? https://gcc.godbolt.org/z/QhbUjI
How would I create the pointer to int in the unique_ptr case without initializing the int? I tried this: https://gcc.godbolt.org/z/SfVxzU I expect there is a way, just I don't know it.