<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Kylotan's Gamedev Thoughts]]></title><description><![CDATA[Thoughts on game development.]]></description><link>https://gamedev.ebonyfortress.com/</link><image><url>https://gamedev.ebonyfortress.com/favicon.png</url><title>Kylotan&apos;s Gamedev Thoughts</title><link>https://gamedev.ebonyfortress.com/</link></image><generator>Ghost 5.81</generator><lastBuildDate>Mon, 03 Nov 2025 06:13:24 GMT</lastBuildDate><atom:link href="https://gamedev.ebonyfortress.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Why is networked multiplayer so difficult to implement?]]></title><description><![CDATA[<p>It&apos;s often said that &quot;networked games are hard to make&quot;, but why is that? In an age of game engines with built-in networking capabilities, why is this still considered a problem? Why is networking different from other features that have been massively simplified by modern engines,</p>]]></description><link>https://gamedev.ebonyfortress.com/why-is-networked-multiplayer-so-difficult-to-implement/</link><guid isPermaLink="false">6750a734e1fe622363cf2ae1</guid><dc:creator><![CDATA[Ben Sizer]]></dc:creator><pubDate>Fri, 06 Dec 2024 21:22:07 GMT</pubDate><content:encoded><![CDATA[<p>It&apos;s often said that &quot;networked games are hard to make&quot;, but why is that? In an age of game engines with built-in networking capabilities, why is this still considered a problem? Why is networking different from other features that have been massively simplified by modern engines, such as rendering, physics, and audio? Let&apos;s find out.</p><h1 id="player-expectations">Player Expectations</h1><p>Imagine you&apos;re playing a split screen cart racer game at home on the couch with a friend. The race starts, you push the stick forward, and your cart immediately starts pulling away. The game is <em>responsive</em> to your input. But you take the first corner too slowly, and your friend speeds past you. You both see the overtaking manouevre, your race position drops to 2nd, and theirs switches to 1st. The game is <em>consistent</em> for all players. You and your friend control your vehicles with split-second reflexes, until eventually one of you crosses the finish line just a moment before the other. The game plays in <em>real-time</em>.</p><p>These are the three key expectations that we have of most (not all!) video games:</p><ul><li>They will be <em>responsive</em> to our inputs, acting quickly to take the action that we have asked the game to take.</li><li>They will be <em>consistent</em>, meaning that every player experiences the same game state, even only seeing different parts of it and from different angles, and maybe even at slightly different times.</li><li>The game runs in <em>real-time</em>, so that we have a constant input-process-output loop that allows us to respond to the challenges set by the game and our opponents.</li></ul><h1 id="information-moves-slowly">Information moves slowly</h1><p>This works well when everyone is sat in front of the same machine. Within the tiny duration of a single rendered &apos;frame&apos; of the game - maybe 17 milliseconds for a 60Hz game - the software is able to query all the game pads, apply the input in each case to the specific player carts, perform any AI routines for non-player drivers, run the physics simulation to move all the carts, calculate any game-specific logic (such as on-track collectables, boosts, etc), create all the visuals and sounds, and send them to the appropriate output devices. </p><p>The fact that this can be done literally faster than the blink of an eye is a technological marvel, and it&apos;s made possible by all the hard work being done within a single console or computer where everything is connected and can send billions of bits of information around the computer every second.</p><p>But what if we put those players in front of separate computers, miles apart from each other, connected only by The Internet? You&apos;d be right in thinking that they&apos;re still technically &apos;connected&apos;, but the problem is, these connections are <em>slow</em> - glacially so, compared to the insides of a computer. Internet bandwidth continues to go up and up over time, but that is mostly about making the virtual pipes &apos;wider&apos; so that more data can travel at once. The actual speed at which any one given message travels has not increased much, and cannot get much quicker. Network traffic - and indeed, all information - is limited by the speed of light, and that is not changing any time soon.</p><p>We see people talking about 20ms or 30ms being a good &apos;ping&apos; for online gaming, and that means it takes 20ms to get a message - even an absolutely tiny one - to the recipient and back. But if it takes 20ms to get a reply, that&apos;s too long for the 17ms frame times we mentioned above, so we can&apos;t process the input in the same frame it was generated. Even if we accepted a 33ms frame duration (for a 30Hz game) it still means that the response to your input would arrive about two-thirds of the way through the frame time, leaving little time left to do the actual calculations and rendering.</p><p>This led to one of the earliest lessons learned by online game developers. The simplest way to implement networked multiplayer would have been to run the game on a server, and have each player&apos;s computer run a much simpler program (sometimes called a &apos;thin client&apos;) that only handles input and rendering, along with the network messages required to send the input to the server and to get the rendering data back from that server. This is the model used by online text games such as <a href="https://en.wikipedia.org/wiki/Multi-user_dungeon?ref=gamedev.ebonyfortress.com">MUDs</a>.</p><p>However, those text games do not run at 30 or 60 frames per second, and are not concerned with complex physics and rendering either. For modern action game developers, even with messages travelling at near to light speed, it still took too long to get them across the internet to allow the usual input-process-output loop within a single frame duration. This meant that simply could not work for a typical action-oriented game. A different approach was needed.</p><h1 id="shared-simulations">Shared simulations</h1><p>The answer was to have the &apos;client&apos; - that is, the program running on the player&apos;s computer, rather than on some server somewhere - to run the actual game, rather than just handling the input and output. This allows it to do all the usual calculations that a game normally has to make, without waiting 20ms or longer to get the necessary information.</p><p>The interesting thing is that while this was new for developers of racing games and shooting games, the strategy gaming world had already been doing this. A classic article named &quot;<a href="https://www.gamedeveloper.com/programming/1500-archers-on-a-28-8-network-programming-in-age-of-empires-and-beyond?ref=gamedev.ebonyfortress.com">1500 Archers on a 28.8</a>&quot; refers to how Age of Empires was able to have massive battles playing across the internet back in an age when a computer could not even send 28 kilobytes of data per second. The trick they used was to have each player run the whole game separately, and exchange network messages to ensure they all play out the same way, i.e. &apos;in sync&apos;. In their words:</p><blockquote>the expectation was to run the exact same simulation on each machine, passing each an identical set of commands that were issued by the users at the same time. The PCs would basically synchronize their game watches in best war-movie tradition, allow players to issue commands, and then execute in exactly the same way at the same time and have identical games.</blockquote><p>Problem solved! Or was it?</p><p>Keeping the simulations perfectly synchronised required some very careful programming, including working to a schedule of &quot;communication turns&quot;, each 200ms long. The idea here is that each of those turns could contain orders from each player, about which units they wanted to move and to where, and they could be sent out to all players and processed at the same time. However, for them to all be processed at the same time meant that all players had to wait a little while for everyone else&apos;s orders for that turn to arrive. The end result was several hundred milliseconds of latency between a player clicking to give an order, and seeing that order start to play out on their screen. In terms of our earlier expectations, this was <em>real-time</em> (in that the game world keeps marching on as we watch it) and it was <em>consistent</em> (in that all players were seeing that same world) but it was not especially <em>responsive</em>, at least not in a way that you would need from a shooter or racing game.</p><h1 id="the-core-of-the-problem">The Core of the Problem</h1><p>This starts to show us that the concept of information taking time to travel has unavoidable implications for our games. We essentially have these 3 ideas - responsiveness, consistency, and the need for each player to run the game in real-time - and it turns out that it&apos;s basically impossible to achieve all three simultaneously without any compromises. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://gamedev.ebonyfortress.com/content/images/2024/12/hard-multiplayer-triangle.png" class="kg-image" alt="Diagram showing a triangle with &apos;responsive&apos;, &apos;real-time&apos;, and &apos;consistent&apos; at the three corners." loading="lazy" width="1366" height="903" srcset="https://gamedev.ebonyfortress.com/content/images/size/w600/2024/12/hard-multiplayer-triangle.png 600w, https://gamedev.ebonyfortress.com/content/images/size/w1000/2024/12/hard-multiplayer-triangle.png 1000w, https://gamedev.ebonyfortress.com/content/images/2024/12/hard-multiplayer-triangle.png 1366w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The triangle of trade-offs made by most multiplayer games.</span></figcaption></figure><ul><li>A real-time game that is instantly responsive to local player input is making changes for each player that will take some time to reach the other players, meaning the simulations can&apos;t be kept consistent - events could happen in different orders or an event that made sense on one player&apos;s machine might not make sense on another player&apos;s by the time that information arrives there.</li><li>A real-time game that guarantees consistency must wait for consensus about the result of any action before it advances, whether that consensus is in the form of synchronised input (as with the RTS example) or in the form of authoritative game state broadcast out from a server. This means the simulations cannot be instantly responsive to local inputs.</li><li>A game that is responsive and yet also needs to be consistent must allow the input made by one player to reach and be applied by other players before the game can proceed, to ensure that actions taken by the other players don&apos;t somehow contradict the action we already permitted to happen. This means it cannot run in real-time.</li></ul><p>Each of these permutations has its place. We saw above how real-time strategy games (at least in the early days of the internet) would choose to be real-time and consistent at the expense of responsiveness. Compare that to a turn-based strategy game, anything from Magic: The Gathering to online chess. By giving up the real-time requirement, and only moving the game on when a player submits their turn, they can be responsive and instantly show the results of a player&apos;s move locally.</p><p>There are also online games that are real-time and responsive but less concerned about consistency. Many RPGs - especially the &apos;massively multiplayer&apos; variety - are like this. It rarely matters if players are slightly out of position or playing slightly different animations as it has little effect on the actual gameplay, which is usually resolved by game rules on the server that do not have to be responsive. Many MMORPG players have seen enemies hit by a spell when they appeared to be safely outside the area of effect, or had their character die even though they just drank a healing potion, because the server had resolved the death before it received the input about the potion. While frustrating at times, it&apos;s a reasonable technical tradeoff that the genre can make.</p><p>Another category that makes concessions on consistency is that of physics-based games like Fall Guys, which inevitably end up processing client-side physics slightly differently for all players. This results in discrepancies between player positions that are usually minor, but occasionally visible and game-changing. It also includes some racing games which extrapolate vehicle positions to give the impression of zero network latency, but which means cars can &apos;teleport&apos; when that extrapolated position turns out to be wrong due to player input or collisions. Sometimes it even means revising the rankings at the end of a tightly-contested race.</p><p>In practice, it&apos;s rare that any game totally commits to two of the three values while fully sacrificing the third. It&apos;s more realistic to compromise on all three to a lesser or greater extent, or even to make different trade-offs for different features.</p><h1 id="predicting-the-future">Predicting the Future</h1><p>So, we know that we have to compromise on at least one of our three core expectations, but we&apos;ll obviously want to mitigate that as far as possible. Just what sort of mitigation would a game need, in each case?</p><p>With real time strategy games, they tend to &apos;fake&apos; responsiveness by playing visual and audio cues to let you know immediately that your order has been accepted by the system, even if that order doesn&apos;t <em>really</em> start being executed until quite some time later.</p><p>Similarly, with the games that compromise on consistency, they still attempt to minimise the discrepancies, often by having a central server which acts as a tie-breaker, instructing clients to blend or teleport any out-of-position players back towards the spot that the server thinks they should be at.</p><p>What about games like our cart racer, or most shooters, or indeed fighting games? We find ourselves in a position where the genre dictates the requirement for the game to be real-time, and the competitive nature means consistency is important. But these are fast-paced action games where responsiveness is essential too. How do we solve that contradiction?</p><p>The usual answer is that such games live in a twilight zone where they essentially fake responsiveness and consistency, in such a way that it <em>seems</em> like the player is experiencing both, while arguably experiencing neither. This is done in the following way:</p><ul><li>Each player&apos;s inputs are immediately processed locally to give the appearance of responsiveness, while also being sent to a server or to the other clients;</li><li>When they arrive on the server or other clients, the inputs are processed, and the results are sent back to the original player;</li><li>Upon receiving the results, the original player&apos;s client checks to see if they are consistent with what happened locally (usually a few frames earlier), and if not, has to make corrections to bring the client&apos;s simulation in line with what the &apos;real&apos; state should be.</li></ul><p>The first step, where inputs are applied locally without waiting to see the exact effect, is often called &quot;client prediction&quot;. It might be better to think of it as client <em>assumption</em>, because the input is applied locally on the assumption that things will play out exactly as the local simulation shows. Often, that is exactly what happens. But, when a response comes from the network and disproves the assumption, a correction needs to be made before the game proceeds, or the inconsistency between the simulations will grow to the point where the game is unplayable. </p><p>So, how are those corrections made? </p><h1 id="reconciliation">Reconciliation</h1><p>Some sources refer to this as &quot;server reconciliation&quot;, the idea being that a client has to reconcile its idea with what it assumed would happen with the actual events that the server has told the client about. However, the broader concept doesn&apos;t actually require a server, as it can apply in a peer-to-peer game as well.</p><p>This is arguably the most complex part of the whole process, for two reasons. Firstly, it potentially has significant effects on how the whole game is implemented because it can become necessary to store past world states, to store past inputs, to be able to do arbitrary resimulation, maybe to be able to blend entity states (or rendered states), and so on. Because the correction is usually responding to something that happened a few frames ago (since it takes time to send the inputs across the internet and get a response), it&apos;s not as simple as just overwriting some data with the &apos;correct&apos; values - the local effects of the client prediction, which have been building upon the incorrect values, also have to be taken into account.</p><p>Secondly, much of this is constrained by the rules of the game and a player&apos;s specific expectations for the genre, because there is not necessarily a single correct way of resolving an inconsistency.</p><p>For example, a modern fighting game is likely to &quot;rollback&quot; and resimulate the whole game every frame, starting from the most recent verified state and re-applying the player&apos;s input since then. The players expect extremely precise hit calculations and will not tolerate being hit when their screen clearly shows them out of range of their opponent. As a result, most fighting games historically operated what was known as &apos;delay-based netcode&apos;, not too dissimilar to the real-time strategy example above, giving full consistency at the price of reduced responsiveness. In recent years this has given way to &apos;rollback netcode&apos; which gives that responsiveness back, at the price of a little visual consistency when corrections have to be made, plus the extra CPU power needed to be able to perform several simulation steps within a single rendering frame.</p><p>First-person shooter games have been doing the rollback-and-resimulate approach for much longer, since at least the late 1990s, because that was the only way to get the shared simulations working in a responsive way, once the &apos;thin client&apos; approach was abandoned. Unlike fighting games, they don&apos;t necessarily need to do the resimulation every frame, because direct contact between entities is very rare and the exact positioning only really matters when resolving shots fired or projectile trajectories. Similarly, even in cases of resimulation, it&apos;s not always necessary to resimulate every single entity as most will be unaffected. (However, determining whether this is true or not is a hard problem, and sometimes it&apos;s better just to err on the side of a complete resimulation to be on the safe side.)</p><p>In most cases, this process of performing a rollback and a resimulation means consistency - every client ends up back in the same state as all the others, excluding the local prediction of course. But that&apos;s not the end of the story.</p><h1 id="arbitrary-decision-making">Arbitrary decision-making</h1><p>The first person perspective used for these games, in conjunction with the &apos;prediction&apos; aspect, means that there is often a very visible lack of consistency, with the classic example being where Player 1 has quickly ducked behind cover, but the information about that movement hasn&apos;t reached the Player 2 yet, who has just pulled the trigger to shoot Player 1 who was right in the crosshairs. Should the game award the kill, in a way that Player 2 would think fair? Or should the game say the shot missed, in a way that Player 1 would think fair? Games choose to handle this differently - the Overwatch developers chose to &quot;<a href="https://www.youtube.com/watch?v=vTH2ZPgYujQ&amp;ref=gamedev.ebonyfortress.com">favor the shooter</a>&quot; and explained this in their video. This is controversial to some, but is not a new concept - Valve were doing it in their Source engine <a href="https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking?ref=gamedev.ebonyfortress.com">over two decades ago</a>.</p><p>Other types of game can be more lenient and don&apos;t need to attempt the rollback-and-resimulate approach. It was mentioned above that RPGs might be real-time and responsive but less concerned about consistency, and one effect of this is that their approach to applying corrections might just be to teleport a character back into position, or to blend its position over time. Positional blending is also popular with some racing games (though some with simpler physics models might also opt for the rollback approach if practical), and can be almost invisible to the player due to everything already being in rapid motion. But since such corrections take time to blend the entity towards the expected position, it trades off even more consistency during the blending period than if a resimulation had happened.</p><p>A hybrid approach is also not uncommon - some games might perform the rollback-and-resimulate to calculate the &apos;official&apos; corrected position of an object, but apply a slow blend towards that position when rendering the object. This looks better than an abrupt correction, at the price of potentially visible glitches if the rendered position is clearly inconsistent with the gameplay (e.g. characters temporarily intersecting visually, despite their collision volumes being correctly separate).</p><p>Finally, any game which runs a physics model on each client has to make a decision about how the input received from the network should affect the outcome from the local physics simulation. It&apos;s not uncommon for the network to send information that positions entities in a way that causes overlaps, causing a powerful (and unwanted) repulsion force, or for it to end up causing instability as a physics constraint that is usually stably solved in one iteration of the physics engine instead gets unstably iterated four times a second across the internet.</p><h1 id="what-about-the-rest-of-the-netcode">What about the rest of the netcode?</h1><p>The interesting thing about everything covered above is how very little of it is about the low level technical implementation, or the things that programmers tend to talk about. Writing the code to have the player clients communicating with each other across the network is deep and complex, potentially involving any or all of the following:</p><ul><li>socket programming</li><li>event loops</li><li>reliable vs unreliable messaging</li><li>ordered vs unordered messaging</li><li>congestion avoidance and management</li><li>latency measurement</li><li>clock synchronisation</li><li>packet fragmentation and reassembly</li><li>message serialization</li><li>state snapshots or actor replication</li><li>remote procedure calls (RPCs)</li><li>...and more!</li></ul><p>The good news is that modern engines and frameworks have done a lot to make the above easier, which is why they&apos;re not mentioned above.</p><p>The bad news is that a developer will usually still need to understand a fair bit about some of these areas, unless they are lucky enough to be working with a genre that has a networking framework designed specifically for the type of game they are making. And chances are, they will still need to consider some aspects of the real-time/responsiveness/consistency trade-offs if they come to implement new features or attempt to improve the player experience.</p><p>So while it&apos;s true to say that making a networked multiplayer game is easier than ever, it is still far from easy. To those attempting it, good luck!</p>]]></content:encoded></item><item><title><![CDATA[How to write good bug reports for game developers]]></title><description><![CDATA[Every game in development has bugs! The quality of the corresponding bug report makes a huge impact on whether the bugs get fixed, and when they do, how effectively.

This is what you can do to ensure that your bug reports are as effective as possible.]]></description><link>https://gamedev.ebonyfortress.com/how-to-write-good-bug-reports/</link><guid isPermaLink="false">6601e80d21f3b30e65de1525</guid><category><![CDATA[production]]></category><category><![CDATA[quality-assurance]]></category><dc:creator><![CDATA[Ben Sizer]]></dc:creator><pubDate>Sat, 09 Oct 2021 09:33:37 GMT</pubDate><media:content url="https://gamedev.ebonyfortress.com/content/images/2024/03/jon-butterworth-MUfcZGjckFk-unsplash-740px.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://gamedev.ebonyfortress.com/content/images/2024/03/jon-butterworth-MUfcZGjckFk-unsplash-740px.jpg" alt="How to write good bug reports for game developers"><p>Every game in development has bugs! And when discovered, someone has to describe the issue in the hope that it will get implemented or addressed, and the quality of that description makes a huge impact on whether this actually happens, and when it does, how effectively.</p><p>So what can <em>you</em> do to ensure that your bug reports are as effective as possible? I&apos;ll give you my personal perspective on what I want to see in a report when I&apos;m the programmer asked to take a look at it. You won&apos;t always be able to do all of this, and that&apos;s okay. But the more you do, the better the report will be.</p><p>And the subtext in a lot of this is that good bug reporting is not just about what bug reporters need to do - it&apos;s what programmers need to provide to the team in order to make these reports effective. Read on to learn more!</p><h2 id="overview">Overview</h2><p>Ultimately any good bug report covers 3 key areas - and in fact this is a good template for almost <em>any</em> request for technical help:</p><ol><li>what you did</li><li>what you saw</li><li>what you had expected or wanted to happen</li></ol><p>These aren&apos;t necessarily three separate sections of the report, and trying to write the report in this strict order is often too awkward. Instead, think of them more as three questions you need to have answered, or three areas you need to have covered.</p><p>Let&apos;s go through each one.</p><h2 id="what-you-did">What You Did</h2><h3 id="configuration">Configuration</h3><p>By this, we mean &apos;what setup or configuration did you have when you saw this&apos;. What is relevant will depend on your project&apos;s situation but it could include the following:</p><ul><li><strong>platform </strong>- is this on Windows, Mac, XBox, Android, iOS? Which version?</li><li><strong>hardware </strong>- what graphics card are you using? How much RAM do you have? What&apos;s your screen resolution - and how many monitors? Were you using mouse and keyboard or a gamepad? If it&apos;s a mobile device, which model? And which screen orientation?</li><li><strong>version </strong>- which version of the game were you running? Is there a build number, or date? Did it come from a specific branch in source control?</li></ul><p>Ideally you don&apos;t want to be manually typing this out every time. It may be possible to use a 3rd party tool like <a href="https://support.microsoft.com/en-gb/windows/open-and-run-dxdiag-exe-dad7792c-2ad5-f6cd-5a37-bf92228dfd85?ref=gamedev.ebonyfortress.com">dxdiag</a> to gather most of the information, and then to copy and paste that in to each report as necessary. If you&apos;re using a bug database like JIRA, try and configure it to use sensible defaults and copy+paste in the rest.</p><h3 id="state">State</h3><p>What state was the game in when this happened? If possible, you want to share enough of the state so that someone else can try and reproduce the problem from the same starting point as you. This could be a save game file which someone can load up and experience the bug for themselves, or an exported character, or some other aspect of exported game state that can be loaded in later.</p><p><em>If you don&apos;t have any functionality like this, ask your engineers to provide this - it will help everyone!</em></p><p>Then, describe the in-game situation where the problem occurs, which might include:</p><ul><li>application state (main menu, connecting to servers, loading, play, pause menu, etc)</li><li>&apos;macro&apos; gameplay state (which level or map, in or out of combat, whether a special mode such as a cutscene or a conversation is active, which windows are open)</li><li>&apos;micro&apos; game state (character world location, character level and stats, currently equipped items, objects selected, buildings constructed)</li></ul><p>What is relevant varies from game to game but the more information you can provide, the better. Programmers don&apos;t want to have to keep coming back and asking for more details because it holds things up.</p><p>Many games output some sort of log file that captures much of the above in text form. This can be attached to the bug report to answer a lot of these questions automatically. It&apos;s also good to get into the habit of checking the end of the log file before you attach it to see if there is any obvious error message in there which could be usefully pasted into the issue description. Often the cause of the bug is right there in the log files, and with some game engines it&apos;ll even highlight the exact line of code or the object that has the problem.</p><p><em>If you don&apos;t have your game generating log files, ask your programmers to set them up. </em>It&apos;s likely that they already have some sort of internal logging system for their own use, in which case they just need to extend it to produce a file which you can send with bug reports.</p><h3 id="steps-to-reproduce">Steps to reproduce</h3><p>The final part of what you did is more obvious - this is where you provide the full instructions to reproduce the problem - &quot;repro steps&quot; for short.</p><p>Ideally these steps are <em>comprehensive</em> enough so that someone with only minimal familiarity with the codebase, such as a junior programmer or an external contractor, can still understand what to do. Bugs often get assigned to new starters as an onboarding exercise or outsourced to 3rd party studios, so a good bug report takes this into account.</p><p>Another ideal to aim for is a <em>minimal</em> test case - how can the problem be reproduced in as few steps as possible? Every step that can be removed will not only speed up the debugging work, but will also make it clearer which aspects are irrelevant to the problem.</p><p>For example, if you played through 3 rounds of a tournament and the game crashed at the start of round 4, is it possible that the same round would crash if you went straight into that one from the start? If you can try that round as the first one and it crashes, then the problem is likely to be specific to that round - but if not, the problem could be related to going through multiple rounds.</p><p>This is another area where programmers will usually have to provide tools such as debug commands or cheat codes so that specific parts of the game can be tested in isolation. These not only save time for bug reporters but for anyone developing or testing the game.</p><p>Finally, you want the <em>scope</em> of the test case to be appropriate. Often a hasty bug report implicates a very specific situation or object when in fact the problem turns out to be much more general. </p><p>Some examples:</p><ul><li>If the long sword is broken, try the short sword - is that broken too? If not, you have a long sword bug, If so, maybe it&apos;s all swords, or all weapons.</li><li>If there&apos;s a visual glitch on your NVIDIA machine, does it occur on AMD machines too? How about with integrated graphics? You might need to rope in a colleague to help you check this sort of situation.</li><li>If something is broken on the Dec 12th build, did the same thing work in the Dec 11th build? Can you find when exactly it broke? Or <em>any</em> build where it works? (<em>Again, if you don&apos;t have access to old builds, ask for a process to be set up where you do have this.</em>)</li></ul><p>By finding the most closely-fitting scope for the bug report, you potentially save a lot of time when it comes to digging through the code and data to locate the exact problem. So, try some similar-but-different cases and adjust the report to include your findings.</p><h2 id="what-you-saw">What You Saw</h2><h3 id="description">Description</h3><p>First, describe the situation in plain text. Use project-specific terms but avoid jargon or trendy terms gamers may know but game developers may not! Sometimes, even designers and programmers on the same team have a different name for the same concept or feature - a project glossary can help with this, so consider setting one up. </p><p>The aim is that anyone on the team should be able to read this description and understand the problem.</p><h3 id="visuals">Visuals</h3><p>Next, if you can demonstrate the issue with screenshots and attach them to the ticket, great. The Windows Snipping tool lets you quickly mark up a screenshot with arrows and circles to highlight the areas of interest. And if you can record and upload a video of the problem, even better. <a href="https://obsproject.com/?ref=gamedev.ebonyfortress.com">OBS</a> will let you capture and export videos but the Windows Game Bar will do, or the AMD or NVIDIA streaming and capture software.</p><p>If you&apos;re wondering why the plain text description is still important when the problem is entirely evident from the videos or screenshots, there are a few reasons:</p><ul><li>Not everyone who looks at the bug report will have time to watch the videos or study the screen shots. A producer or team lead might want to just read the description to quickly understand who to assign the bug to.</li><li>Screenshots and videos are not easily searchable. It&apos;s common to search through bug databases to see which issues are related or even potential duplicates of each other, and visual media doesn&apos;t help with that.</li><li>Junior team members or people new to a particular part of the game may not fully understand what they are seeing in the video, or may not know why what they&apos;re seeing is considered a bug. The text can make this explicit for them.</li></ul><h3 id="supporting-evidence">Supporting Evidence</h3><p>Often there will be some other documentation or evidence that you can provide which will potentially be a big help in diagnosing or fixing the problem. These include:</p><ul><li>pop-up message boxes with error messages</li><li>console logs</li><li>application log files</li><li>error messages appearing elsewhere (e.g. debug text on-screen)</li><li>crash dump files</li><li>call stacks / backtraces</li></ul><p>If your game uses an engine that allows you to run the game &apos;in&apos; the engine, like Unity or Unreal do, it is a good idea to try and reproduce bugs in the editor, as this can often reveal extra diagnostic information that may be hidden in the final builds.</p><h3 id="metadata">Metadata</h3><p>Once you&apos;ve detailed what you&apos;ve seen, often there is something interesting to say <em>about</em> what you&apos;ve seen too, drawing on your experience with the project.</p><p>A &apos;repro rate&apos; is a useful thing to record - when you follow the steps to reproduce this, how often does it actually happen? Some bugs don&apos;t happen all the time, despite following the same repro steps. This is useful information to record, not just for the programmer who can know that it might be dependent on some other factors that are not yet understood, but also for a producer who can adjust the priority of bug fixes relative to how often they occur in practice. It&apos;s also a helpful guide to QA themselves - if a repro rate is low, perhaps there&apos;s a way to dig deeper and narrow down the cause so that a 100% rate can be achieved?</p><p>Another useful consideration is whether this bug is like a previous bug. You can search the bug database for keywords to find potential candidates, and if found, you can link the issues together so that the knowledge is shared, potentially making it easier to find the root cause. You don&apos;t have to necessarily work out whether two similar bugs are strictly duplicates of each other - just add the link in the database and let the coders figure it out.</p><h2 id="what-you-had-actually-expected">What You Had Actually Expected</h2><p>This is the part that confuses some people and which seems like a weird thing to ask for, but which is very important on larger and more complex projects. <em>Here, you need to make clear how your expectations are different from what you actually saw.</em></p><h3 id="reference-the-specification">Reference the specification</h3><p>The main reason for this is that while most bugs are clearly a case of &quot;this is doing the Wrong Thing&quot;, sometimes what you might think of as a bug is not strictly a bug, and is actually one of these:</p><ul><li>the intended behaviour, where a designer wanted it that way, for some reason that is not apparent</li><li>behaviour the design team don&apos;t care about, and isn&apos;t necessarily wrong or right</li><li>a situation that was never anticipated or specified at all, and needs to be addressed with a feature request rather than a bug report</li></ul><p>So this is your chance to use both your expertise of games and your knowledge of the project to explain the situation. Why did you expect this behaviour? Is there a specification or design doc that shows unambiguously that this is wrong? If so, quote it and link it in the bug report. </p><p>This is a key reason why developers should <strong>not</strong> skimp on design documentation. Not only does a feature specification tell the implementor how to make the feature, but it provides a baseline that QA can test against when seeing if the feature is implemented correctly. And, for our purposes here, it provides a justification for logging a bug plus also a baseline to measure whether the resulting bugfix has correctly resolved a problem or not.</p><h3 id="reference-external-or-implicit-standards">Reference external or implicit standards</h3><p>Sometimes there are also external benchmarks or standards you will need to adhere to, for example age ratings (e.g. <a href="https://pegi.info/?ref=gamedev.ebonyfortress.com">PEGI</a>), technical platform requirements (especially on consoles), accessibility laws, etc. These can also be linked to when filing bugs, to make it clear what a fix would need to take into account.</p><p>But sometimes, you don&apos;t have a specification, and you can&apos;t get a ruling from a designer or producer - but you still think it&apos;s worth addressing. What then?</p><p>If it&apos;s a personal feeling that &quot;this shouldn&apos;t be like this&quot;, you can try and justify it by <em>de facto</em> standards, such as comparison to other parts of the game (<em>&quot;this doesn&apos;t happen in the similar situation on level 3, so it shouldn&apos;t in level 4&quot;</em>) or at least compared to standards in other games (<em>&quot;in similar games in our genre, double-clicking this icon normally restores the counter to zero&quot;</em>).</p><p>A final justification - and some might say the most important one - is the impact on the player, since a player expects to not be frustrated by a game. What will a typical player feel if they hit this issue? Given that bugs can run the gamut from &apos;minor visual glitch, unlikely to be noticed by many&apos;, all the way through to &apos;accidentally overcharges the user $1000 when buying an in-app purchase&apos;, the level of impact can be the most decisive factor in whether this issue needs to be addressed immediately or can be kicked into the long grass to be fixed later - or never. If the game is already live you can sometimes include quotes from players or links to comments they&apos;ve made, and this can help the team to assess the priority of the bug and sometimes even to gather more test data.</p><h3 id="make-expectations-clear">Make expectations clear</h3><p>One last important thing to remember is that, from the information above, <strong>it needs to be clear what the result of a fix for the issue would look like</strong>. If there&apos;s agreement that there is a problem and work needs to be done to resolve it, the developer needs to know what the &apos;definition of done&apos; for that work is, and QA need that information to be able to assess the fix.</p><p>Coders are often a surly bunch and having their well-intentioned bug fix re-opened because the initial information was lacking only makes them surlier! So make sure that they&apos;re fixing the right thing in the first place. This is another reason why written design specifications are important and why the team needs to be cognizant of the difference between a missing feature and a bug. Being asked to repeatedly fix something which was never technically broken but which was never adequately specified in the first place is a real morale-killer for programmers. </p><h2 id="what-not-to-do">What Not To Do</h2><p>Generally, more information is always better! But unless you&apos;ve been asked for the following, don&apos;t provide them:</p><ul><li>Estimated fix duration or difficulty - unless you will be doing the work, don&apos;t feel tempted to estimate the size of the task. It will be inaccurate and could give a false impression to producers regarding how much time is needed to clear bugs.</li><li>Who you think should fix it - often it&apos;s possible to guess who the best person for the job is, but assigning it to them is best done by whoever schedules tasks. It&apos;s fine to mention topic experts in the text so the information is there when it&apos;s assigned, of course.</li></ul><p>Finally, don&apos;t re-open a past bug unless you&apos;re 100% sure it is <em>exactly</em> the same problem and caused by the same circumstances. There is a tendency for bugs with broad descriptions (e.g. <em>&quot;Game crashes to desktop&quot;</em>, <em>&quot;Equipping item doesn&apos;t work&quot;</em>) to get repeatedly re-opened as there can be several different problems or situations that can cause similar outcomes. But a re-opened bug implies that a previous fix has stopped working, which may not be the case if the problem has a new cause. Again, it is bad for developer morale to keep having your bug re-opened when your fix was actually fine, and it can also slow down diagnosis of the real problem because attention is diverted towards the previous fix rather than the new circumstances.</p><p>Instead, create a new bug, and link it to the previous one that you think might be related. This captures the relevant information in the system for the person allocating the tasks and the person performing the task, without prematurely implicating prior fixes or second-guessing the actual fix required.</p><h2 id="in-closing">In Closing</h2><p>There was a lot covered above, and it might seem like following all the advice will make reporting a bug an onerous task, which in turn could lead to fewer reports and therefore a worse game. This is a legitimate concern as you want everyone to feel confident to log what they see and to be contributing to the quality of the game without it becoming a drain on their time.</p><p>So the important thing is to get into a position where you can do most or all of the above effectively and efficiently. Ideally this means having:</p><ul><li>Automated gathering of system specs, config files, build numbers, log files, etc</li><li>Comprehensive debug tools and functionality that allow bugs to be reproduced quickly and easily</li><li>Tools, scripts, or documentation on how to export a save game and load it on a different machine</li><li>Access to good screen capture tools for stills and video, ideally with annotation capabilities</li><li>Written specifications that describe how the game should act, look, and feel</li></ul><p>With that in place, you should be well on your way to logging some effective bug reports that make a real difference to finishing the game on time and under budget!</p>]]></content:encoded></item><item><title><![CDATA[Tweakable game settings]]></title><description><![CDATA[An overview of the various ways in which a game can be engineered to allow key values and attributes to be amended quickly and easily, including at run-time.]]></description><link>https://gamedev.ebonyfortress.com/tweakable-game-settings/</link><guid isPermaLink="false">6601e80d21f3b30e65de1524</guid><category><![CDATA[programming]]></category><dc:creator><![CDATA[Ben Sizer]]></dc:creator><pubDate>Sun, 29 Aug 2021 15:17:46 GMT</pubDate><content:encoded><![CDATA[<p>In any complex game there are often hundreds of settings and values which influence the way the game plays. Being able to change these rapidly and easily makes for much faster development and can facilitate testing and bug-fixing, especially if you have team members who are less comfortable changing the code. And in a live game like an MMO, if done well they can allow you to fix problems without deploying patches or even restarting servers.</p><p>Let&apos;s have a look at how we can do this, starting with the worst case scenario and then presenting some options to improve the &apos;tweakability&apos; of the values.</p><p>Examples are in C#-like pseudocode with the Unity engine in mind but should generalise to most programming languages.</p><h2 id="worst-casemagic-numbers-in-code">Worst case - magic numbers in code</h2><p>Let&apos;s imagine we have a simple RPG-like game where the player can attack a monster and deal some amount of damage to it. Let&apos;s also imagine that we have an magician in the game who can cast a shield spell on monsters, meaning they take less damage from attacks. A very simple implementation could look like this:</p><pre><code class="language-C#">public float CalculateMeleeDamage()
{
    // Calculate the normal amount of damage for this weapon
    float damage_dealt = current_weapon.BaseDamage();

    // Decrease it if the monster is shielded
    if (monster.HasShieldSpell)
    {
        damage_dealt *= 0.85f;
    }
    
    return damage_dealt;
}</code></pre><p>The best thing about this code is that it was quick and easy to write! However, it has an obvious disadvantage - the hard-coded &apos;magic number&apos; of 0.85. Writing the literal value inline is fine when the code is as simple as this, but this function is likely to get more and more complex as functionality is added, and it may no longer be clear why there is a 0.85 in there. Worse, if we need to perform damage calculations in multiple places we could end up with this value in several places in the code, leading to subtle bugs if we ever change it in one place but forget to change it in the other.</p><h2 id="constants-in-code">Constants in code</h2><p>The simple improvement here is to make it a named constant - this will make the algorithm more readable in future and also allows a programmer to change the value in a single place, even if it is used by more than one routine. </p><pre><code class="language-C#">private const float ShieldSpellDamageMultiplier = 0.85f;

public float CalculateMeleeDamage()
{
    // Calculate the normal amount of damage for this weapon
    float damage_dealt = current_weapon.BaseDamage();

    // Decrease it if the monster is shielded
    if (monster.HasShieldSpell)
    {
        damage_dealt *= ShieldSpellDamageMultiplier;
    }
    
    return damage_dealt;
}</code></pre><p>This is a simple fix, but still has limitations. To change the value, the programmer needs to stop the program, rebuild it, and run it again. That might not be the most convenient thing if you were trying out different multipliers to see which one gave the best game balance. What can we do?</p><h2 id="statics-in-code">Statics in code</h2><p>By converting the constant value to a static value, we gain the ability to change it in the debugger. This lets a programmer tweak the value during a session by running the game in the debugger, setting a breakpoint, and then altering the value in the debugger at runtime.</p><pre><code class="language-C#">private static float ShieldSpellDamageMultiplier = 0.85f;

public float CalculateMeleeDamage()
{
    ...as above...
}</code></pre><p>The only change here is literally one word on line 1, but for a programmer this could potentially save them a lot of time in future.</p><p>But what if it&apos;s not a programmer who wants to change the value, but a designer, or any other team member who doesn&apos;t have a debugger handy (or isn&apos;t comfortable using one)?</p><h2 id="editor-properties">Editor Properties</h2><p>In an engine like Unity, it is relatively easy to expose a value like this in the editor so that it can be easily changed by anyone on the development team. A very naive implementation might look like this, assuming the code below is part of a MonoBehaviour or ScriptableObject:</p><pre><code class="language-C#">[SerializeField]
[Range(0.0f, 1.0f)]
private float ShieldSpellDamageMultiplier = 0.85f;

public float CalculateMeleeDamage()
{
    ...as above...
}</code></pre><p>Here we&apos;re also using the capability to restrict the range of the value in the editor and displaying it as a convenient slider, like so:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://gamedev.ebonyfortress.com/content/images/2021/08/image.png" class="kg-image" alt loading="lazy" width="342" height="72"><figcaption><span style="white-space: pre-wrap;">Sample output from a property exposed to the Unity Editor Inspector</span></figcaption></figure><p>In Unreal Engine 4 you can achieve a similar effect with a UPROPERTY, in Godot you can export a variable, and so on. With this capability anyone on the development team has the ability to edit these variables and tweak them.</p><p>But it&apos;s not always obvious where to find the variable you need, especially if you have hundreds of objects/scenes/prefabs/etc, each with their own set of values.</p>
<p>Even if you fix that - perhaps by having a central object that stores all the tweakable values - it&apos;s still only developers who can do this, because it requires access to the editor (or the ability to edit the sometimes-esoteric serialization format that the data is stored in). It&apos;s not ideal for QA who might be working with the built executables.</p>
<p>Can we do better?</p>
<h2 id="settingsconfiguration-files">Settings/configuration files</h2><p>The next step is to consider loading values like this from the game settings, so that not only can they be changed in the debugger, but they can be set before runtime by editing a simple human-readable file.</p><figure class="kg-card kg-code-card"><pre><code class="language-.ini">[CombatValues]
ShieldSpellDamageMultiplier = 0.85</code></pre><figcaption><p><span style="white-space: pre-wrap;">Part of the .ini file</span></p></figcaption></figure><pre><code class="language-C#">static float ShieldSpellDamageMultiplier = 0.85f;

public void LoadSettings()
{
    var settingsFile = new SettingsFile(&quot;gamesettings.ini&quot;);
    if (settingsFile.HasSection(&quot;CombatValues&quot;)
    {
        var combatValuesSection = settingsFile.GetSection(&quot;CombatValues&quot;);
        if (combatValuesSection.HasValue(&quot;ShieldSpellDamageMultiplier&quot;))
        {
            ShieldSpellDamageMultiplier =
                combatValuesSection.GetFloatValue(&quot;ShieldSpellDamageMultiplier&quot;);
        }
    }
}

public float CalculateMeleeDamage()
{
    ...as above...
}</code></pre><p>This example (using a fictitious .INI loading library) will load in the gamesettings.ini file and looks for a CombatValues section, and inside there it looks for the ShieldSpellDamageMultiplier value. If the value is not found, it will continue to use the default as set in code, but if it <em>is</em> found, the value in the file will override it. Depending on personal preference you might want to use a different format such as JSON, YAML, or XML - each will allow you to set up some named variables grouped conveniently into sections.</p><p>(In practice, you probably wouldn&apos;t have each part of your code opening the settings file itself - you&apos;d open it in one place and then pass it to whichever objects needed to configure themselves from that file.)</p><p>So now you have a system where programmers can set defaults in code and any developer can override the values in the settings file. All they have to do is edit the file and restart the program. Better still, you might even be able to set it up so that the program can re-read the settings file during play at the press of a button, allowing for some very quick testing and iteration! </p><p>Not only is this good for developers in the course of them iterating on features, but it also allows balance changes to be done simply by deploying a new configuration file, without needing to recompile the executable. And it allows for easy implementation of &apos;<a href="https://www.martinfowler.com/articles/feature-toggles.html?ref=gamedev.ebonyfortress.com">feature flags</a>&apos;, by putting boolean values into the configuration and checking those values in code to decide which path to take. This is useful when testing experimental features, doing A/B tests, or perhaps just leaving your options open to disable something later.</p><p>But we can still do a bit better. This approach requires us to know the exact variable names that we expect to see in the settings files. (The alternative of simply putting <em>all</em> variables in the settings from the start gets unwieldy quickly as the file will need to change frequently and developers with locally-modified copies will find themselves merging it on a regular basis.) It also has no simple protection against us inserting erroneous values.</p><h2 id="in-game-console">In-game console</h2><p>What would be ideal is to be able to tweak these values directly from inside the game. It&apos;s still useful to load them from a settings file but for transient changes it helps to be able to change them directly in-game without using an external editor.</p><p>A common approach is to add a &quot;debug console&quot; which looks like a chat or terminal window where you enter commands and see results in text form. For our purposes we might want a &quot;SET&quot; command which allows us to change values.</p><pre><code class="language-C#">// Globally-shared set of configurable values
Dictionary&lt;string, float&gt; FloatValues = new Dictionary&lt;string, float&gt;();

void ProcessConsoleCommand(string command)
{
    // Split the command text up at each space
    string[] commandWords = command.Split(&apos; &apos;);

    if (commandWords[0] == &quot;SET&quot;)
    {
        string variableName = commandWords[1];
        string variableValueString = commandWords[2];
        if (float.TryParse(variableValue, out float variableValue))
        {
            FloatValues[variableName] = variableValue;
            ShowDebugConsoleOutput($&quot;Set {variableName} to {variableValue}.&quot;);
        }
    }
    ... etc ...
}
 

public float CalculateMeleeDamage()
{
    // Pull this value from the shared values collection
    float ShieldSpellDamageMultiplier =
        FloatValues[&quot;ShieldSpellDamageMultiplier&quot;];
    
    ... rest of the code unchanged ...
}</code></pre><p>In this example we would allow the user to type something like <code>SET ShieldSpellDamageMultiplier 0.5</code> into the debug console and the appropriate entry in the FloatValues dictionary would be set, meaning other parts of the code can immediately see that new value.</p><p>Obviously you&apos;re not limited to float values - you can have separate dictionaries for strings, bools, and so on, or keep everything in one dictionary with a variant type. An even cleaner way to handle it might be to have your game systems register relevant values with the debug console and for the console to tell the system when to update them, but implementation is left as an exercise for the reader!</p><p>Often we can go one further and integrate a scripting language like Lua into the game and expose it to the console. This means that rather than hardcoding commands like &quot;SET&quot; and being restricted to rigid syntax, we can write more complex expressions, and add more commands easily. This can be a lot of effort but is worthwhile, especially if the scripting language can be used in other ways (testing, automation, in-game scripted events, etc).</p><p>Still, this might be too complex for your needs. And even if you do have a debug console, it&apos;s not necessarily the most friendly user experience for non-technical users. Adding auto-complete and a way to see a list of valid commands can help, but it only goes so far.</p><h2 id="in-game-ui">In-game UI</h2><p>What might be better is to have a debug UI which exposes these values in a more visual form. This means no more remembering the syntax, quicker editing of values, and the ability to group and display the tweakable aspects in a way that suits you.</p><p>The classic approach here is to use a so-called &apos;immediate-mode&apos; GUI library. Immediate mode UI is a poor choice for your game&apos;s main user interface because it ties the visuals tightly to the code, and is not suited to interfaces which are complex, need custom graphics, or have animations. However, they are very quick for programmers to implement and as such make a perfect way of implementing debug user interfaces.</p><p>In Unity <a href="https://docs.unity3d.com/Manual/GUIScriptingGuide.html?ref=gamedev.ebonyfortress.com">the old IMGUI system</a> is adequate for this task, and provides a quick way to not only tweak in-game values but to limit those tweaks to reasonable ranges.</p><pre><code class="language-C#">private float ShieldSpellDamageMultiplier = 0.85f;

void OnGUI () 
{
    var windowPositionRect = new Rect (25, 25, 250, 200);
    GUI.Window(1, windowPositionRect,
               ShowTweakableValuesWindow, &quot;Tweakable Values&quot;);
}

private void ShowTweakableValuesWindow(int id)
{
    // Show label
    var labelPositionRect = new Rect (25, 25, 200, 75);
    GUI.Label (labelPositionRect, &quot;Shield Spell Damage Multiplier&quot;);

    // Show slider
    var sliderPositionRect = new Rect (25, 50, 200, 75);
    const float MinValue = 0.0f;
    const float MaxValue = 1.0f;		
    ShieldSpellDamageMultiplier =
        GUI.HorizontalSlider(
            sliderPositionRect,
            ShieldSpellDamageMultiplier,
            MinValue, 
            MaxValue);

    // Show value
    var valuePositionRect = new Rect (175, 70, 200, 75);
    GUI.Label (valuePositionRect, ShieldSpellDamageMultiplier.ToString());
}</code></pre><p>This gives output a bit like this:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://gamedev.ebonyfortress.com/content/images/2021/08/image-1.png" class="kg-image" alt loading="lazy" width="292" height="236"><figcaption><span style="white-space: pre-wrap;">Example of the Unity IMGUI system</span></figcaption></figure><p>With this sort of capability, backed up by the ability to change defaults via configuration files, we make our game about as convenient as possible to tweak in real-time, making development quick and easier. And even after the game is shipped, we can still test and deploy some rapid changes merely by altering the configuration file. For most games this will be enough.</p><p>But what if you have an online multiplayer game, and you have not only a game client to think about, but a game server too? Often you&apos;ll need to make changes to the game servers, but taking the servers down for a code change causes downtime that annoys and loses players. You can load values in from your settings file but even if you have a live reload facility it&apos;s not usually the case that your team will have direct access to the settings files once deployed.</p><p>You can even have a way to log into the game and perform debug commands from a trusted account, if you are confident about being able to correctly authenticate and authorize such an account, but this is harder to make secure and awkward in that it requires someone to log directly into the game.</p><h2 id="in-game-web-server">In-game web server</h2><p>A better way might be for the game to expose the various tweakable values via a HTTP API. This allows you to create a simple UI in HTML and Javascript which connects to the game server and requests the changes directly. </p><p>This might sound like a huge undertaking but these days is quite easy to set up. Most languages come with rudimentary HTTP server functionality built in, and this is enough to implement a simple web interface that lets you change variables while the game is running. Not only that, you can implement commands (as with the debug console) that allow arbitrary actions while the program is running, such as respawning enemies, toggling a player&apos;s invulnerability mode for testing, etc.</p><p>And why stop there - you could extend the interface to provide any diagnostic information you care about such as frame rates, player locations, bandwidth usage, etc., and render them out conveniently in the browser using HTML or Javascript.</p><p>The code for this is a little longer but still very manageable - usually it&apos;s just a few lines to set up a HTTP server and then a function to handle requests by examining the URL and query string, and then to return a rudimentary response.  This is a Unity code example but the only Unity-specific parts are the <code>MonoBehaviour</code> and the <code>Debug.Log</code> calls.</p><figure class="kg-card kg-code-card"><pre><code class="language-C#">using UnityEngine;
using System;
using System.Net;

public class HTTPServer : MonoBehaviour
{
    private float ShieldSpellDamageMultiplier = 0.85f;
    
    HttpListener listener = new HttpListener();
    
    // Start is called before the first frame update
    void Start()
    {
        // Set the listening addresses
        listener.Prefixes.Add(&quot;http://127.0.0.1:8888/&quot;);
        listener.Prefixes.Add(&quot;http://localhost:8888/&quot;);

        listener.Start();       
        
        listener.BeginGetContext(new AsyncCallback(ListenerCallback), this);
    }
    
    private static void ListenerCallback(IAsyncResult result)
    {
        try
        {
            Debug.Log(&quot;Handling HTTP request.&quot;);
            
            // Get the data from the request
            var thisObject = (HTTPServer) result.AsyncState;
            HttpListener listener = thisObject.listener;
            HttpListenerContext context = listener.EndGetContext(result);
            HttpListenerRequest request = context.Request;
            HttpListenerResponse response = context.Response;
            
            // Set up the context again for next time
            listener.BeginGetContext(
                new AsyncCallback(ListenerCallback), thisObject);
            
            // Perform the required action
            var endpoint = context.Request.Url.LocalPath;
            if (endpoint == &quot;/set&quot;)
            {
                // Retrieve the value from the request and 
                // store it in the variable.
                string newValue =
                    request.QueryString.Get(&quot;ShieldSpellDamageMultiplier&quot;);
                thisObject.ShieldSpellDamageMultiplier =
                    float.Parse(newValue);
            }
            else
            {
                // Assume a &apos;get&apos; operation, which is covered 
                // by the default response below
            }
            
            // Construct a response, showing the new value
            string responseString = &quot;&lt;html&gt;&lt;body&gt;&quot; +
                &quot;ShieldSpellDamageMultiplier=&quot; +
                thisObject.ShieldSpellDamageMultiplier.ToString() +
                &quot;&lt;/body&gt;&lt;/html&gt;&quot;;
            byte[] buffer =
                System.Text.Encoding.UTF8.GetBytes(responseString);
            response.ContentLength64 = buffer.Length;
            System.IO.Stream output = response.OutputStream;
            output.Write(buffer,0,buffer.Length);
            output.Close();
            
            Debug.Log(&quot;Completed HTTP request.&quot;);
        }
        catch (Exception e)
        {
            // Catch and log errors thrown from listeners,
            // as Unity silently suppresses them
            Debug.LogError(e);
            throw;
        }
    }
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">Unity example of a rudimentary HTTP server</span></p></figcaption></figure><p>This is not production-quality code - you&apos;d want to have different endpoints for different functionality, look up values dynamically, add validation and error-checking, etc. It is also more common to return data in JSON format rather than HTML so that Javascript can process it effectively. But, this gives an indication of how you can start building such a system. If you add this script to a GameObject in a Unity scene and run the game, you can connect to <a href="http://127.0.0.1:8888/?ref=gamedev.ebonyfortress.com"><code>http://127.0.0.1:8888/</code></a> in a web browser and see the current value of <code>ShieldSpellDamageMultiplier</code>. And if you enter <a href="http://127.0.0.1:8888/set?ShieldSpellDamageMultiplier=0.7&amp;ref=gamedev.ebonyfortress.com"><code>http://127.0.0.1:8888/set?ShieldSpellDamageMultiplier=0.7</code></a> into your browser instead, it will change the value in-game.</p><h2 id="summary">Summary</h2><p>Today&apos;s game engines and programming languages give us a variety of ways to change values during play and get to quickly test things without needing to recompile the game or even to restart it. Hopefully with the ideas above you can implement one or more of these into your game today and start to reap the benefits immediately.</p>]]></content:encoded></item><item><title><![CDATA[Agile For Gamedev - A Poor Fit]]></title><description><![CDATA[<p>The <a href="https://www.bloomberg.com/news/articles/2021-01-16/cyberpunk-2077-what-caused-the-video-game-s-disastrous-rollout?ref=gamedev.ebonyfortress.com">release of Cyberpunk 2077 in a poor state</a> last year led to a lot of debate on how game development projects should be managed. Staff were overworked, deadlines were missed, features were cut, and the game came out with serious bugs. Despite throwing more money and time at the</p>]]></description><link>https://gamedev.ebonyfortress.com/agile-considered-fragile/</link><guid isPermaLink="false">6601e80d21f3b30e65de1516</guid><category><![CDATA[production]]></category><category><![CDATA[industry]]></category><dc:creator><![CDATA[Ben Sizer]]></dc:creator><pubDate>Wed, 04 Aug 2021 18:08:04 GMT</pubDate><content:encoded><![CDATA[<p>The <a href="https://www.bloomberg.com/news/articles/2021-01-16/cyberpunk-2077-what-caused-the-video-game-s-disastrous-rollout?ref=gamedev.ebonyfortress.com">release of Cyberpunk 2077 in a poor state</a> last year led to a lot of debate on how game development projects should be managed. Staff were overworked, deadlines were missed, features were cut, and the game came out with serious bugs. Despite throwing more money and time at the problem, and cutting the scope, quality was still low. Calling the launch a failure would not be strictly true - the game has sold many millions of copies and <a href="https://www.polygon.com/2020/12/11/22170468/cyberpunk-2077-sales-revenue-cd-projekt?ref=gamedev.ebonyfortress.com">apparently covered its costs</a> - but everyone knows the industry needs to do better than this.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://gamedev.ebonyfortress.com/content/images/2021/08/project-triangle.png" class="kg-image" alt="Triangular diagram showing the trade-off between scope, cost, and time" loading="lazy" width="1206" height="1029" srcset="https://gamedev.ebonyfortress.com/content/images/size/w600/2021/08/project-triangle.png 600w, https://gamedev.ebonyfortress.com/content/images/size/w1000/2021/08/project-triangle.png 1000w, https://gamedev.ebonyfortress.com/content/images/2021/08/project-triangle.png 1206w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The classic trade-off - quality is constrained by scope, cost, and time</span></figcaption></figure><p>Anyone who&apos;s followed game development for a while will know there&apos;s nothing new here. &apos;<a href="https://arstechnica.com/gaming/2011/05/the-death-march-the-problem-of-crunch-time-in-game-development/?ref=gamedev.ebonyfortress.com">Crunch time</a>&apos; has been a staple of game development for as long as the industry has had major projects, and was already common knowledge when the famous <a href="https://ea-spouse.livejournal.com/274.html?ref=gamedev.ebonyfortress.com">&apos;EA Spouse&apos; blog entry</a> was posted 17 years ago. Despite faster computers, better tools, more powerful languages, and growing experience, things don&apos;t seem to have improved much in game development. </p><p>And yet in the rest of the software development world, things have changed a lot. Perhaps the biggest change in development practices has been the move towards <em>agile development</em>. Agile means <a href="https://marketoonist.com/2021/01/were-going-agile.html?ref=gamedev.ebonyfortress.com">many things to many people</a> but the core principles are basically that you involve the customer and/or the user more, in a collaborative and iterative process that discovers requirements as you go and responds to change. It is supposed to lead to a more manageable project.</p><p><a href="https://www.youtube.com/watch?v=E-jGEtqB4wU&amp;ref=gamedev.ebonyfortress.com">One commentator claimed</a> that Cyberpunk failed primarily because they did not follow agile project management processes, and particularly did not practice the specific act of &apos;Continuous Delivery&apos;, where the software is being &apos;delivered&apos; on a regular basis (e.g. daily) to be assessed. It&apos;s reasonable to say that &quot;bad software engineering&quot; played a part in the problem. However, the claims that this is a failure to adhere to agile principles don&apos;t add up. The developers CD Projekt Red - like most major game developers and quite a lot of smaller ones - do in fact employ people to perform continuous delivery and &apos;devops thinking&apos;. It just didn&apos;t really make a difference.</p><p>I mentioned in my <a href="https://gamedev.ebonyfortress.com/introduction/">introduction post</a> that I think iterative, &apos;agile&apos; development can actually cause problems for game development projects, despite being the overwhelmingly dominant paradigm. Why?</p><h2 id="the-myth-of-people-over-processes">The myth of people over processes</h2><p>&apos;Agile&apos; is a vague term and therefore any criticism of it is often batted away by resorting to some variant of the No True Scotsman fallacy. And there&apos;s some merit to that, because while <a href="https://agilemanifesto.org/?ref=gamedev.ebonyfortress.com">the Agile manifesto</a> talks about <em>&quot;individuals and interactions over processes and tools&quot;</em>, what we actually got are Scrum and Sprints and Standups and Epics and Kanban and so on - a variety of ways in which management seeks to have the benefits of Agile without giving up its array of tools and processes to impose some sort of structure on it.</p><p>The promise was that we could follow the Agile principles and thereby <em>enable</em> agility among the development team. The reality is that developers work under a new set of constraints and agility is <em>demanded</em> of them.</p><h2 id="how-agile-helps-most-software">How Agile helps most software</h2><p>Maybe it&apos;s a price worth paying? For most software, there&apos;s a good argument that Agile makes sense, especially the principle <em>&quot;Welcome changing requirements, even late in development&quot;</em>. In the world of traditional software development where a program or system is being written for a client, this principle solves a big problem: programmers have to make software that meets the needs of non-technical users and customers. As Patricia Aas <a href="https://twitter.com/pati_gallardo/status/1327702212684951552?ref=gamedev.ebonyfortress.com">said</a>, <em>&quot;The users rarely know how to express what they need. You don&#x2019;t have the context needed to understand what they say. Only once you&#x2019;ve built something do you have sufficient understanding to ask the right questions&quot;</em>. It&apos;s inevitable that the first draft will need extensive reworking, so Agile development embraces this reality - produce that draft as early as possible and have both sides work together in a process of gradual improvement based on early and frequent feedback.</p><p>All very sensible. But the explicit assumption here is that users or customers <em>can&apos;t</em> adequately express what they need, or provide any sort of detailed specification of the software, therefore this is the only reasonable route that remains. And the implicit assumption that follows is tied to the cost/scope/time triangle above - i.e. changing requirements will mean that some functionality will either fall out of scope or increase the project time and cost, and that the customer can simply select their chosen trade-off.</p><p>Do these assumptions hold true in a game development context?</p><h2 id="effective-up-front-design-is-possible">Effective up-front design is possible</h2><p>The first assumption <strong>should </strong>be untrue. Game development is rarely performed only by programmers delivering a program for a non-technical outside client. Usually it includes a whole game design team, who shape the vision for the product in conjunction with a publisher or management. Even if you consider the customer to be the publisher rather than the design team, it&apos;s still the case that a game development team has designers on staff whose role is to be experts in analysing, designing, and planning video games.</p><p>In particular, a designer should be able to take a particular feature and break that down into clear deliverables with relatively unambiguous specifications, such that a sufficiently competent software engineer is able to implement something very much like that at the first attempt. The need for iteration to discover requirements and solicit feedback should be greatly reduced by the presence of this team of domain experts.</p><p>This role played by a &apos;semi-technical&apos; design team has parallels in other industries - for example, the work done by an architect when designing buildings. By coordinating both with the client and with the teams responsible for the eventual &apos;construction&apos;, they can formulate a fairly comprehensive plan that delivers on the eventual user&apos;s requirements while staying within all constraints and creating a plan for engineers to follow.</p><p>One snag is that the games industry has, on the whole, failed to train designers to fill this role, and instead focuses them on content creation (mapping the world, writing lore, placing spawn points, specifying items, assigning character attributes, etc) and creative direction (choosing and maintaining design &apos;pillars&apos;, identifying references in other games, selecting key features, communicating the overall vision to artists and programmers, etc). Too often, there&apos;s a void in the middle where the actual <em>design</em> would be. It&apos;s like having city planners and construction workers, but no architects.</p><p>One game I worked on (which will remain nameless) revolved heavily around combat. Senior designers had specified that there would be various weapon types and damage types. Other designers were tasked with implementing these via scripts. It was only after many months and several bug reports that anyone realised that there was no combat or damage <strong>system </strong>specified anywhere - just various disparate scripts attached to weapons that applied the damage in inconsistent ways. Eventually someone was forced to come up with a coherent system, the necessary engineering work happened, and the various weapons were re-implemented that way.</p><p>Problems like this are incredibly wasteful from a project management point of view because time is expensive! Although software is much easier to change than, say, a building, it is not <em>free </em>to do so. Worse, this process causes &apos;technical debt&apos; since programmers may cut corners to find the quickest route to implementation if they know there&apos;s a good chance the designers will request future amendments anyway. To quote <a href="https://www.youtube.com/watch?v=E-jGEtqB4wU&amp;lc=UgwnT_LonvoOL96J01h4AaABAg&amp;ref=gamedev.ebonyfortress.com">one commenter</a> on the Continuous Delivery video above, <em>&quot;All delay problems, all software quality problems were coming from basically one source: constant changes by game designers&quot;</em>. I wouldn&apos;t go that far, as there are many problems in game development that software engineers have entirely inflicted upon themselves, but the impact of designer changes on the timeliness and quality of game software is severe.</p><p>So while the statement &quot;<em>the users rarely know how to express what they need&quot;</em> is true in many industries, it&apos;s not in ours<em>.</em> For example, we know that a combat-oriented game needs a combat system, and we can know what aspects make up a combat system. It&apos;s our job as game developers to understand these concepts.</p><p>You can&apos;t avoid an iteration or feedback loop entirely. Even the best plans have flaws, or a change gets forced upon you for technical or business reasons. You need to be adaptable and you can&apos;t eliminate change, but planning and foresight can reduce it and save you time. A changeable plan is better than no plan.</p><p>In particular, the cost of design time is usually much lower than the cost of programmer time, so you want the changes to happen as close to the design end as possible. Iterating mentally and verbally will always be cheaper than iterating in documents or spreadsheets. Iterating in documents will always be cheaper than iterating in designer prototypes. Iterating in designer prototypes will always be cheaper than iterating in engineer prototypes, which in turn are cheaper than iterating during production. Changes in production should be the last resort.</p><p>Sadly, this focus on agility has emphasised responding to change, and de-emphasised the need to plan things in advance. So it&apos;s no surprise that Cyberpunk 2077&apos;s development saw people say &quot;we&apos;ll figure it out along the way&quot; and that poor planning is blamed for many of the problems. This is endemic to the industry.</p><h2 id="the-project-is-rarely-as-agile-as-the-methodology">The project is rarely as agile as the methodology</h2><p>So, to the second assumption - just how flexible are the corners of that project management triangle above?</p><p>In an Agile project, the idea is that stakeholders regularly evaluate the state of the software, provide feedback, and adjust priorities. As change requests are made and new requirements emerge, less important features might get delayed or shelved entirely, and if development is otherwise going well, the budget might increase to accommodate these features later. The nature of the process assumes that new requirements are going to be discovered during development and therefore either some old requirements fall out of scope or the budget stretches to include the new ones as well.</p><p>This is somewhat at odds with the way that many game development projects work. Typically, the publisher is promised a certain set of features, often delivered in a fairly well-defined order, in return for funding to pay for a team to deliver them over a known timescale. These &apos;<a href="https://en.wikipedia.org/wiki/Video_game_development?ref=gamedev.ebonyfortress.com#Milestones">milestones</a>&apos; during development might correspond to broad phases - e.g. preproduction, pre-alpha, alpha, beta, etc - or they may be broken down further still, for example to require a monthly deliverable, each with certain features delivered to an agreed level of completeness.</p><p>The milestone system means that even though the project is delivered frequently over several iterations (just as agile proponents would want) it&apos;s largely decided ahead of time what gets delivered and when. This reduces risk for the publisher and gives them a very clear overview of the project&apos;s progress. However, from the developer&apos;s point of view, this incurs a lot of the dangers of a traditional model where you need to hit a fixed deadline with fixed resources, but with much of the overhead of an Agile model where the software must be ready for continuous delivery and evaluation at all times. The worst of both worlds?</p><p>It&apos;s easy to blame publishers for not being willing to be more flexible. But historically <a href="https://www.cnet.com/news/why-most-video-games-arent-profitable/?ref=gamedev.ebonyfortress.com">most games have not been profitable</a>. It is a risky business where a handful of weaker releases might get subsidised by 1 or 2 hits, and survival as a publisher - and therefore, survival as a game developer funded by that publisher - can revolve around whether the publisher is able to keep costs down. And the publisher, unlike most customers who are buying software, can&apos;t just decide to cut their losses and accept the current state of the software when things start to overrun, because they need a playable and polished game for retail purposes. The Agile principle of &quot;deliver working software frequently&quot; can only go so far.</p><p>One of my favourite games, <em>Deus Ex: Mankind Divided</em>, saw the publisher come in for <a href="https://www.youtube.com/watch?v=oVbj4GuuZTA&amp;ref=gamedev.ebonyfortress.com">serious criticism from YouTuber Jimquisition</a> over publisher &apos;meddling&apos; and &apos;cash-grabs&apos;. Yet we also know the game was <a href="https://www.ign.com/articles/2015/11/18/deus-ex-mankind-divided-has-been-delayed?ref=gamedev.ebonyfortress.com">delayed at least once</a> and even when it shipped, was criticized for being &apos;cut short&apos;. Given that sales <a href="https://www.psu.com/news/deus-ex-mankind-divided-sales-fall-short-of-human-revolution/?ref=gamedev.ebonyfortress.com">were disappointing</a>, and that development was already over budget, it&apos;s not hard to see why the publisher may have insisted on a reduction in scope and some controversial revenue-generating features given that they probably suspected they were going to lose money on this. Granting the developers an extension of an extra year or two to make the game they truly wanted to make would have made a better product but probably a greater financial loss too. When <a href="https://www.gamepressure.com/newsroom/former-playstation-exec-aaa-game-development-cost-is-unsustainabl/zf1f08?ref=gamedev.ebonyfortress.com">development can cost several million dollars a month</a>, there has to be a deadline.</p><p>All this adds to the stress on engineers. Each bit of work thrown away because a designer wanted to &apos;iterate on it&apos; rather than specify it in more detail is time not available to hit these milestones. A related issue (which I want to talk about more in future) is where designers or project managers trickle out features to engineers sequentially over time. What the designer might gain from leaving the subsequent specifications to a later date is often more than lost on the engineering side as key systems have to be reworked to accommodate the new requirement, which often could have been done properly from the start in less time.</p><p>The last problem I want to mention is that games are relatively complex systems, even ignoring the software engineering aspect. It&apos;s rarely easy to reduce the scope of a game without there being significant knock-on effects. Imagine a crafting system where players create their own items. Disabling that is only the start of the process, because any other system that assumed players had access to crafted items will now need re-assessing - will players get those items elsewhere? Do we need to add more merchants into the game? Do defeated enemies need to drop more loot? Does the inventory management need change now that there are fewer items to consider? It&apos;s rarely as simple as merely dropping a few features to hit a launch date.</p><h2 id="what-should-we-do">What should we do?</h2><p>Would I agree with those who say we should <a href="https://ronjeffries.com/articles/018-01ff/abandon-1/?ref=gamedev.ebonyfortress.com">abandon agile development entirely</a>? Probably not, although the Agile term carries both too much baggage and too little clarity, so it is essentially meaningless now. Still, much of the philosophy is common sense and has clear benefits, and some degree of <em>agility</em> is beneficial. </p><p>So, my specific recommendations are:</p><p>1) We need to be less pessimistic about what can be effectively planned in advance. We don&apos;t need &apos;Big Design Up Front&apos; or hundred-page documents before development starts. But we should be front-loading much more product design, doing more work on (digital) paper first, and when we do hand things off to engineers, do it with clear specifications from designers rather than an expectation that the work will be re-done based on feedback later. Less &apos;Find the Fun&apos;, and more &apos;Design The Fun&apos;.</p><p>2) We need to rein in the heavy-handed project management aspects that crept into Agile development that obstruct developers, and get back to the original promise of a &apos;light touch&apos; that allows engineers to be more effective. Replace the micro-management of tasks with clearer instructions to engineers and sufficient information for them to be able to carry them out well. (In return developers probably have to get better at estimating task durations, but that&apos;s for another day.) A good project manager or producer is worth their weight in gold, but that gold is too easily spent on admin and bureaucracy to &apos;manage upwards&apos; while impeding actual work.</p><p>3) The games industry needs to refocus the design discipline on game system development and the production of good feature specifications. This might need more support from both academia and industry veterans to ensure that we have the effective tools and vocabulary for this, since few of the theories or concepts discussed in the past appear to have gained traction.</p><h2 id="conclusion">Conclusion</h2><p>Game software development has some unique constraints that other software development often lacks - but it also employs designers who, if effective, can not just improve the product but significantly aid in planning the project. As such, Agile development - at least in the form that it usually ends up taking - is not ideal for games, and an approach that borrows from more traditional &quot;plan-first&quot; methods is likely to be better, especially if the industry learns to play to its strengths.</p>]]></content:encoded></item><item><title><![CDATA[Introduction]]></title><description><![CDATA[<p>I&apos;ve been developing games in some form for thirty years, starting with BASIC on the Amstrad CPC 464 in my early teens, working on <a href="https://en.wikipedia.org/wiki/MUD?ref=gamedev.ebonyfortress.com">MUDs</a> as a hobby during university, before getting a job as a software engineer and eventually landing in the video games industry about fifteen</p>]]></description><link>https://gamedev.ebonyfortress.com/introduction/</link><guid isPermaLink="false">6601e80d21f3b30e65de1515</guid><category><![CDATA[meta]]></category><dc:creator><![CDATA[Ben Sizer]]></dc:creator><pubDate>Fri, 01 Jan 2021 14:48:17 GMT</pubDate><content:encoded><![CDATA[<p>I&apos;ve been developing games in some form for thirty years, starting with BASIC on the Amstrad CPC 464 in my early teens, working on <a href="https://en.wikipedia.org/wiki/MUD?ref=gamedev.ebonyfortress.com">MUDs</a> as a hobby during university, before getting a job as a software engineer and eventually landing in the video games industry about fifteen years ago. In my time so far in that industry just one of those projects, <a href="https://fallguys.com/?ref=gamedev.ebonyfortress.com">Fall Guys</a>, was a well-known success. And while I learned a lot during that development cycle, I&apos;ve arguably learned a lot more from previous projects that underperformed or didn&apos;t ship at all. As Tolstoy said, <em>&quot;each unhappy family is unhappy in its own way&quot;</em>, and perhaps the same can be said for game development teams.</p><p>I believe that video game development has only 2 major problems. Unfortunately, the first is that we&apos;re not very good at writing software, and the second is that we&apos;re not very good at designing games! It&apos;s only through the dedication and hard work of the developers, combined with the public&apos;s insatiable appetite (and thus, funding) for new games that we&apos;re somehow able to keep cranking out new ones despite all the odds.</p><p>Elaborating on these two points is the primary purpose of this blog, so for now I&apos;ll just provide an overview and set the stage for what to expect from future entries.</p><p>Over the years, software development has followed a curious course. The continual advance of free or cheap third-party libraries of software means that developers can deliver more and more functionality while writing less and less code. Many modern apps are mostly existing components bolted together with a thin layer of application-specific &apos;glue&apos; code. But while this paves the way for increasing numbers of creators able to make useful and entertaining applications, it comes at a cost - fragile software that breaks in ways that the creator does not understand, insecure software that leaks personal data or exposes security flaws, inefficient software that uses more of your computing resources in order to save the original programmer time. This is going to get worse before it gets better - a wave of self-taught programmers are using these components to achieve great things with unmaintainable code, many embracing a culture that dismisses fusty old software engineering formalisms in favour of the &quot;move fast and break things&quot; ethos popularised by the world of tech startups.</p><p>The games industry has been spared the worst of this, but not all of it. The dominance of the two major games engines (Unity and Unreal) is a similarly two-edged sword, allowing developers to achieve great success with less training or rigour. And while the games industry was never a bastion of perfect code, poor software engineering practices are arguably increasing now that more developers are self-taught and engines isolate them from their errors in ways that previously could not be ignored. As with non-game applications, we&apos;re seeing an explosion of new programs that do more than ever before but which are increasingly fragile.</p><p>Game design has a different problem. It&apos;s a far older craft and most of what we know about games and play in general can be transferred to the digital medium. We may not have developed the same sort of &apos;game components&apos; that can be bolted together, but at least there is this rich history of past games - digital or otherwise - plus our understanding of related media such as cinema and prose, which can guide and inform us as we make new works.</p><p>But if this is so, and we have decades if not centuries of game and narrative design to draw upon for designing video games - why are we so bad at it? As veteran game designer Daniel Cook said recently, <a href="https://twitter.com/danctheduck/status/1344357310399877120?ref=gamedev.ebonyfortress.com"><em>&quot;an expert game designer is 20x more effective than a newbie. They are correct 20% of the time instead of 1%&quot;</em></a>. We tend to assume that good games are discovered through a process of iteration rather than designed explicitly, and this is the accepted wisdom - at least in video game design, where the themes of iterative and &apos;Agile&apos; development processes are applied to the design of the game as well as the software implementing that game. But I would argue that not only is this excessively iterative approach unnecessary, but it&apos;s inefficient, ill-suited to game development, and actually <em>adds</em> to the trouble we have when trying to successfully complete a video game project.</p><p>I think it&apos;s no coincidence that many - perhaps most? - game designers I&apos;ve met were not really &apos;designing games&apos; in the sense that someone making a card game or board game might design a game. Instead, they were usually creating and tweaking content for systems that already existed, often without ever choosing that system or planning its parameters. But if we were to take a more systems-oriented view of game design, as designer and author Raph Koster does by temporarily setting aside the aesthetics and considering the core <a href="https://www.raphkoster.com/2014/01/06/how-i-analyze-a-game/?ref=gamedev.ebonyfortress.com"><em>&quot;mechanics, inputs and processes, rules and tokens and actions&quot;</em></a>, we should be able to use our experience to structure a game that effectively delivers something close to our final intent earlier on, reducing the amount of subsequent iteration time needing to be spent on it. The aesthetics are still essential, but to some extent these two strands can be managed separately, with the interface between the two arguably being easier to manage when there is less iteration and therefore less of a moving target.</p><p>Thankfully, I think both of these issues - how we approach software development (especially for games) and how we approach game design (especially for software) are both fixable. I don&apos;t have all the answers, but in the spirit of Thomas Edison, I do know a lot of ways that <em>don&apos;t</em> work, and I hope to share various suggestions based on those experiences over the weeks and months ahead.</p>]]></content:encoded></item></channel></rss>