<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: 🏎️Tim Beaudet🚀</title>
    <description>The latest articles on Forem by 🏎️Tim Beaudet🚀 (@timbeaudet).</description>
    <link>https://forem.com/timbeaudet</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F269397%2F95771320-fcb6-44ad-b3c2-4deec467d247.png</url>
      <title>Forem: 🏎️Tim Beaudet🚀</title>
      <link>https://forem.com/timbeaudet</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/timbeaudet"/>
    <language>en</language>
    <item>
      <title>Type Safety Saved My Life; Real World Code Maintenance</title>
      <dc:creator>🏎️Tim Beaudet🚀</dc:creator>
      <pubDate>Wed, 26 Mar 2025 12:26:55 +0000</pubDate>
      <link>https://forem.com/timbeaudet/type-safety-custom-iterators-and-runtime-structures-in-the-real-world-5e71</link>
      <guid>https://forem.com/timbeaudet/type-safety-custom-iterators-and-runtime-structures-in-the-real-world-5e71</guid>
      <description>&lt;p&gt;&lt;a href="https://www.twitch.tv/timbeaudet" rel="noopener noreferrer"&gt;I develop indie games live&lt;/a&gt; and decided to build my own prefab system, similar to that in Unity. This was the most difficult and technical challenge I’ve encountered in my career of building games. But the system saves time for designers with flexible and reusable objects, like an extremely powerful copy and paste mechanism.&lt;/p&gt;

&lt;p&gt;Today I present an overview of the data structures and objects used to create the prefab system. The article will explore creating custom iterators to make range-based loops, how type safety prevents mix-ups between different Keys (UUIDs), and how I approach json-like objects in C++. Finally I’ll share a decision I was unhappy with, and would approach differently with the hindsight I have today. Grab a barrel of your favorite beverage and get ready to learn something new!&lt;/p&gt;

&lt;h2&gt;
  
  
  Clusters of Nodes
&lt;/h2&gt;

&lt;p&gt;I didn’t want Track Builder to be a generic editor, you know the typical scene-graph / object hierarchy. I &lt;strong&gt;thought&lt;/strong&gt; I could make a better workflow specific to designing a racetrack without it, but as features were added the flow became clunky and was working about as well as my first car. Using Unity for the Eggcelerate! series convinced me to build a prefab system. &lt;a href="https://dev.to/timbeaudet/prefab-system-easy-in-unity-i-built-mine-the-hard-way-4g2l"&gt;Read the introduction article&lt;/a&gt; to discover more about the system and why I built it.&lt;/p&gt;

&lt;p&gt;The game engine has no entity-component system (ECS) built in, or at least didn’t when I started working on the prefab system. I dive more into this at the end of the article but it led to design decisions that I later regretted. To get started my “entities” are called “Nodes” and they basically have a name, a position and maybe a parent node. Any other behaviors or attributes are defined by the components that are attached to the node.&lt;/p&gt;

&lt;p&gt;TrackBuilder holds the nodes in a &lt;code&gt;NodeCluster&lt;/code&gt; which contains;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class NodeCluster; //Forward-declaration for PrefabTable
using ComponentContainer = std::vector&amp;lt;Component&amp;gt;;
using NodeHierarchyTable = std::unordered_map&amp;lt;NodeKey, Node&amp;gt;;
using NodeComponentsTable = std::unordered_map&amp;lt;NodeKey, ComponentContainer&amp;gt;;
using PrefabTable = std::unordered_map&amp;lt;ResourceKey, NodeCluster&amp;gt;;

class NodeCluster {
public:
    NodeHierarchyTable mNodeHierarchy;
    NodeComponentsTable mNodeComponents;
    DataResourceTable mResourceTable;
    PrefabTable mPrefabTable;
    ResourceKey mResourceKey;
    NodeKey mRootNodeKey;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a terrible time to mention the C++ standard does not require all containers to work with forward declared types. GCC 11 did not like the PrefabTable declaration above as I &lt;a href="https://www.reddit.com/r/cpp/comments/1gj0j1a/been_using_c_for_long_enough_til/" rel="noopener noreferrer"&gt;shared on reddit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There is actually a lot of complexity to unpack in the above sample, it’s basically trees of trees of trees all the way down. A prefab is simply a NodeCluster as you can see from the PrefabTable declaration above. A NodeCluster also represents the full racetrack or level structure and when a Node inside (any) cluster has a valid PrefabKey it copies the properties from the prefab it points to unless that property was overridden.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If you don’t understand, don’t worry - I wrote this entire system with a barely functioning understanding of it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An instance of a prefab is the node that actually exists that points towards the prefab to copy from. This instance can exist inside another prefab, like I can have a &lt;code&gt;grandstand.pfab&lt;/code&gt; that contains two nodes; a &lt;code&gt;flag&lt;/code&gt; and a &lt;code&gt;spectator&lt;/code&gt;, where that spectator is an instance of the &lt;code&gt;spectator.pfab&lt;/code&gt;. The grandstand of course could be an instance in another prefab itself and quickly you begin to see the complexity explode. When the designer changes the shirt color in the &lt;code&gt;spectator.pfab&lt;/code&gt;, everything else has to update &lt;em&gt;unless&lt;/em&gt; it was overridden elsewhere in the chain.&lt;/p&gt;

&lt;p&gt;If you didn’t understand that, don’t worry - I wrote this whole system and I barely have a functioning understanding of it. Explaining it is near impossible, too many edge cases, expanding problem area and the limited terminology for recursive depth does not help.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Type-Safe UUIDs to Prevent Accidents
&lt;/h2&gt;

&lt;p&gt;From the overview you can see the role ‘Keys’ are playing in this system to uniquely identify different elements. All keys are UUIDs but they shouldn’t intermingle or mix. We don’t want to confuse a &lt;code&gt;NodeKey&lt;/code&gt; for a &lt;code&gt;ResourceKey&lt;/code&gt; or such. By leveraging type-safety the compiler can protect us! The term ‘Key’ is used for aesthetics and my coding-standards, &lt;code&gt;ComponentKey&lt;/code&gt; feels much better than &lt;code&gt;ComponentID&lt;/code&gt;. &lt;a href="https://github.com/r-lyeh-archived/sole" rel="noopener noreferrer"&gt;sole::uuid&lt;/a&gt; was used to avoid implementing UUID specific details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using NodeKey = sole::uuid;
using ComponentKey = sole::uuid;
using ResourceKey = sole::uuid;
// continued for other Key types
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anyway, the above doesn’t offer any protection from writing code that mixes the different key types. Forgive this simplistic example, but you might see how it could accidentally occur in a more complex codebase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void FindNode(NodeKey&amp;amp; nodeKey) { /* do stuff */ }

// Later, somewhere in code:
{
    ComponentKey key = ComponentKey::uuid4();
    FindNode(key);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since building a wrapper around external code is a reasonable idea, we can combine that with a template to create additional type-safety protection that ensures a &lt;code&gt;NodeKey&lt;/code&gt; is different from a &lt;code&gt;ComponentKey&lt;/code&gt; even if both are UUIDs under the hood like so;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;template&amp;lt;typename Type&amp;gt; class MyUUID {
public:
    //wrapper API here
private:
    sole::uuid id
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And change our type aliases to;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum class NodeKeyType { };
using NodeKey = MyUUID&amp;lt;NodeKeyType&amp;gt;;

enum class ComponentKeyType { };
using ComponentKey = MyUUID&amp;lt;ComponentKeyType&amp;gt;;

enum class ResourceKeyType { };
using ResourceKey = MyUUID&amp;lt;ResourceKeyType&amp;gt;;

// continued for other Key types
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will make the prior example fail to compile, since the &lt;code&gt;NodeKey&lt;/code&gt; and &lt;code&gt;ComponentKey&lt;/code&gt; types are different. I enjoy the compiler telling me when I’m doing unexpected things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Iterators for Maintainable Tree Recursion
&lt;/h2&gt;

&lt;p&gt;Speaking of compiler assistance, while I am not a fan of syntactic-sugar for sugars sake, I am all for it improving maintainability! As a reader of a pretty technical article you probably already know what recursion is. Just in-case you played games during that lecture, like I definitely was, recursion is where a function calls itself, possibly many times over. A quick example;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int CalculateSum(int number) {
    if (0 == number) { return 0; } //The end case
    return number + CalculateSum(number - 1); // Recursive case
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is very useful for recursing trees, like the &lt;code&gt;NodeHierarchy&lt;/code&gt;. A naive and quick way to &lt;code&gt;RescurseTree()&lt;/code&gt; in a generic manner is to use a function callback that gets called for each node. The following differs from my &lt;code&gt;Node&lt;/code&gt; contents but fits the common tree better.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void RecurseTree(Node&amp;amp; node, std::function&amp;lt;void(Node&amp;amp;)&amp;gt; callback) {
    callback(node);
    for (Node&amp;amp; child : node.mChildren) {
        RecurseTree(child, callback);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following shows how it would be used, although isolated from any other code like this example makes it a little easier to digest. Try placing it in a particularly busy area and you might see how it can mislead a future maintainer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RecurseTree(rootNode, [](Node&amp;amp; node) {
    if (true == node.IsPrefabInstance()) {
        return;
    }

    node.DoSomething();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code works, but it is hard to read. For instance what happens at the return? It acts just like a continue would in a typical loop, it does not actually return since it is contained within the callback lambda. Maybe just my personal preference, using &lt;code&gt;continue&lt;/code&gt; like you can in a typical loop would be much cleaner. Worse, this can’t even break out of the loop early without requiring the callback to return a value for &lt;code&gt;RecurseTree()&lt;/code&gt; to check.&lt;/p&gt;

&lt;p&gt;For this reason I spent some time untangling iterators to make a much nicer recursion that actually supports &lt;code&gt;continue&lt;/code&gt; and &lt;code&gt;break&lt;/code&gt; properly. This was somewhat syntactic sugar, and I delayed the process longer than I should have, but it actually significantly helps writing and reading of the code. Even a slight improvement in the maintainability is a powerful lever in a system as complex as the prefabs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (Node&amp;amp; node : RecurseTree(rootNode)) {
    if (true == node.IsPrefabInstance()) {
        continue;
    }

    node.DoSomething();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference is small, especially when singled out like these examples. I didn’t have to write a lambda function or worry about how &lt;code&gt;continue&lt;/code&gt; or &lt;code&gt;break&lt;/code&gt; might work; it just does. The downside, if there is any, was the complexity moved from code managing the nodes into &lt;code&gt;RecurseTree()&lt;/code&gt;. The following is the approach I took;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct RangedBasedTree {
    typedef std::vector&amp;lt;std::reference_wrapper&amp;lt;Node&amp;gt;&amp;gt; ContainerType;
    ContainerType mRecursedNodes;

    RangedBasedTree(const Node&amp;amp; node) {
        RecurseTree(node, [this](Node&amp;amp; node) {
            mRecursedNodes.emplace_back(node);
        });
    }

    typename ContainerType::iterator begin(void) {
        return mRecursedNodes.begin();
    }

    typename ContainerType::iterator end(void) {
        return mRecursedNodes.end();
    }
};

RangedBasedTree RecurseTree(Node&amp;amp; node) {
    return RangedBasedTree(node);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’ll leave supporting const correctness as an exercise for you, as a hint it may involve templating the &lt;code&gt;RangedBasedTree&lt;/code&gt; while using &lt;code&gt;std::conditional&lt;/code&gt; and &lt;code&gt;std::is_const&lt;/code&gt;… Instead let’s dive into how the custom properties for components are stored when the types are unknown at compile time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structures Defined at Runtime
&lt;/h2&gt;

&lt;p&gt;A very long time ago I read an article or perhaps one of Steve Meyers C++ books, I wish I remembered, and was inspired to create a semi type-safe but dynamically defined structure type, the &lt;code&gt;DynamicStructure&lt;/code&gt;. The best way I have of describing this is using ‘json’ like objects in C++ code. Sure you don’t know the exact types at compile time, hence semi type-safe, but my implementation can throw exceptions when types mismatch or try implicit conversion.&lt;/p&gt;

&lt;p&gt;Over the years I typically use the &lt;code&gt;DynamicStructure&lt;/code&gt; for loading files like json, yaml etc, handling data from network requests and most recently holding the properties for a &lt;code&gt;Component&lt;/code&gt; in the prefab system. Components have a type and definition but they are unknown to Track Builder, since components can be customized to a game.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class DynamicStructure {
public:
    using String = std::string;
    using Array = std::vector&amp;lt;DynamicStructure&amp;gt;;
    using Struct = std::unordered_map&amp;lt;String, DynamicStructure&amp;gt;;

private:
    enum DynamicStructureValueType : uint8_t {
        kNil, kInteger, kFloat, kBoolean, kString, kArray, kStructure
    };

    DynamicStructureValueType mValueType;
    union { //unnamed anonymous union for access like this-&amp;gt;mFloat;
        char mRawBytes[8];

        int64_t mInteger;
        bool mBoolean;
        float mFloat;

        String* mString;
        Array* mArray;
        Struct* mStructure;
    };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obviously the above sample is missing a ton of details like the whole public API, how constructors work and everything else, but I am fairly certain it shows enough to implement your own version from here. The real magic is in the union, although you must remember only to access the active member, which &lt;code&gt;mValueType&lt;/code&gt; helps with.&lt;/p&gt;

&lt;p&gt;Bringing this back to the Node / Component system, as stated earlier Track Builder can’t know the properties of a &lt;code&gt;Component&lt;/code&gt; at compile time because those types can be defined by the game. These definitions are a json file. Someone more ambitious could probably add metadata in game-code with pre-build steps to generate the ComponentDefinitions file, but creating and maintaining a json file is much less effort.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "version":2,
    "components":[
        {
            "display_name": "Hammer Obstacle",
            "type_key":"510fa5af-b454-41a3-9780-2c578a3cf645",
            "properties":[
                { "name":"timeout", "type":"float", "default":5.0 },
                { "name":"shockwave", "type":"boolean", "default":false },
                { "name":"shockwave_radius", "type":"float", "default":15.0 },
                { "name":"damage", "type":"integer", "default":25 }
            ]
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This component gets attached to hammers that crash down on cars, causing damage and perhaps a shockwave that does partial damage. Since TrackBuilder did not know any of this, at compile time, the properties are stored in a &lt;code&gt;DynamicStructure&lt;/code&gt; and “just works”.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Not to Store a Node Hierarchy
&lt;/h2&gt;

&lt;p&gt;Not everything just works when we tackle big projects, and one of the major pain-points when working through the prefab system was how I organized the data. Specifically the duplication of a Node/Component (editor data) vs the Node/Component (in-engine). This entire series only explores the data side. While building the system, past-me built around an assumption that the engine would not be or have an ECS.&lt;/p&gt;

&lt;p&gt;To be fair at the time the engine really didn’t have that support. Past-me figured we could get the benefits of working with ‘nodes’ and ‘components’ in the editor &lt;strong&gt;without&lt;/strong&gt; further requirements. Past-me also hoped to dump the memory block to disk to save/load without any processing or dynamic resizing. As these decisions were made, the &lt;code&gt;NodeHierarchy&lt;/code&gt; was a flattened structure, simply a &lt;code&gt;std::vector&amp;lt;Node&amp;gt;&lt;/code&gt;, to which all benefits later dissolved.&lt;/p&gt;

&lt;p&gt;Considering Components had custom properties this was all a very very silly idea, and portions of this have been refactored, but the legacy of cruft is thick and created functions like;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NodeKeyContainer GetChildren(const NodeKey&amp;amp; nodeKey,
    const NodeHierarchyTable&amp;amp; nodes)
{
    NodeKeyContainer children;
    for (const auto&amp;amp; nodeIterator : nodeHierarchy)
    {
        if (nodeIterator.second.mParentNodeKey == nodeKey)
        {
            children.push_back(nodeIterator.second.mNodeKey);
        }
    }
    return children;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is just one of the many examples that leave room for improvement but requires a substantial refactor, all stemming back to the idea of this flattened hierarchy for saving/loading. The code should not be iterating the entire node hierarchy to get the children, and yet, it does. Perhaps I’m just leaving room for future optimizations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.twitch.tv/timbeaudet" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fplecdscf02epov3iav3n.png" alt="Image description" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This article was a journey through data organization, custom iterators to simplify recursion, type safe UUIDs to prevent mix-ups and design choices I would make differently with hindsight. Especially regarding the flattened structure of the &lt;code&gt;NodeHierarchy&lt;/code&gt;. Writing complex systems is much easier with test-driven development which will be the next article in this series. Until then you can &lt;a href="https://www.twitch.tv/timbeaudet" rel="noopener noreferrer"&gt;watch me make games live&lt;/a&gt; where I build racing games, tackle technical challenges, and share my experience. To catch the next article &lt;a href="https://dev.to/timbeaudet"&gt;Follow HERE&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>cpp</category>
      <category>gamedev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Prefab System: Easy in Unity, I Built Mine the Hard Way</title>
      <dc:creator>🏎️Tim Beaudet🚀</dc:creator>
      <pubDate>Wed, 26 Mar 2025 12:26:37 +0000</pubDate>
      <link>https://forem.com/timbeaudet/prefab-system-easy-in-unity-i-built-mine-the-hard-way-4g2l</link>
      <guid>https://forem.com/timbeaudet/prefab-system-easy-in-unity-i-built-mine-the-hard-way-4g2l</guid>
      <description>&lt;p&gt;I have tackled one of the most challenging pieces of tech encountered in my 20 years of making games; a prefab system for a custom level editor I call Track Builder. This was &lt;a href="https://www.twitch.tv/timbeaudet" rel="noopener noreferrer"&gt;programmed live on stream&lt;/a&gt; showing every step of the process. I share my experiences so you can feel the pains and triumphant moments while learning a few things along the way. Grab a cup of your favorite beverage and enjoy.&lt;/p&gt;

&lt;p&gt;The articles in this series will cover a lot of technical ground including bits like;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leveraging the compiler to prevent mixing different types of UUIDs.&lt;/li&gt;
&lt;li&gt;Creating custom iterators for more maintainable code.&lt;/li&gt;
&lt;li&gt;A newbie’s experience at test driven development.&lt;/li&gt;
&lt;li&gt;Saving and loading while keeping backwards compatibility.&lt;/li&gt;
&lt;li&gt;Unexpected issues when using the system for the first time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2nbxfzgw6s9a72y02riq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2nbxfzgw6s9a72y02riq.png" alt="Image description" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What IS a Prefab System?
&lt;/h2&gt;

&lt;p&gt;Before we get started I’d like to ensure we both have the same idea of what a prefab system is. If you’re a game developer and have used prefabs in Unity, feel free to skip down to why. Many modern game engines notably Unity/Godot/Unreal allow game developers to design levels using a hierarchy of objects. Complex objects can be built from many other objects, like a cup can be a child object of a table which is a child object of a room and...&lt;/p&gt;

&lt;p&gt;Unity allows you to save these objects to a separate file known as a prefab which can be considered like an extremely powerful copy and paste mechanism. Imagine you created an object to represent a wheel, containing a mesh or two for the rim &amp;amp; tire, material details and so on. By saving this object as a prefab you can place instances of the prefab for each wheel of the car, or even an 18-wheeler! Now when you change a property in the prefab all 4 (or 18) wheels are instantly modified. This can be a huge time saver.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Prefabs can be considered like an extremely powerful copy and paste mechanism.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The best part is, prefabs can be built from other prefabs, and the properties can be overridden for specific instances when desired. If I’ve lost you, let’s say when you created the prefab there was a property to describe the tire pressure and you set this value to a typical 35 psi (2.4 bar). The developer has the option to select the front-left tire and modify it to a lower 20 psi (1.4 bar) which will override any default the prefab sets. Any time the prefab changes the other three tires updates, but the front-left will remain 20 psi (1.4 bar).&lt;/p&gt;

&lt;p&gt;This barely scratches the surface of this amazing system, but I hope your imagination can see the wild range of possibilities. Suffice to say this system can give developers a huge lever to help save time with development. But first I already hear the number one question many people have; if Unity or other engines are supporting this why not use one?&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Why WRITE a Custom Prefab System
&lt;/h2&gt;

&lt;p&gt;There is a valid observation that it would be easier and faster to simply use Unity, Godot, Unreal or . With each of them, including Godot, you give up a little control and ownership. Granted, these may not be as important to you as they are to me. I want to create games, specifically racing games. These engines will certainly allow me to do that, they are after all generic engines.&lt;/p&gt;

&lt;p&gt;I don’t say generic in a derogatory manner, this is THE selling point! Allowing someone with an idea and basic skills to build amazing things. It’s like a tool box with a hammer and wrenches that can tackle any project equally. With Track Builder I’m aiming to have a nail gun and impact driver for racetracks and vehicles with perhaps a few generic tools sneaking in. The intent is faster development of racing games even if that makes it more difficult to build a shooting game.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Why not retrofit Godot or build on top of a FOSS prefab solution?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you found yourself thinking that a prefab system is quite generic, you would be correct! It was not a feature when Track Builder was first conceived. Only as I developed Eggcelerate! series in Unity did I see the potential and consider prefabs a good addition. It still took years before I tried toying with the feature.&lt;/p&gt;

&lt;p&gt;One really good question that was asked is “Why not retrofit Godot or build on top of a FOSS prefab solution?” As far as options I’m not sure a “prefab” framework exists, although there are entity-component frameworks like EnTT and perhaps I could have looked deeper into those options, but also I started my engine (Turtle Brains) in 2012 with bits of code having history back to 2004… It was a different time, and Godot definitely did not exist, being first publicly released in 2014.&lt;/p&gt;

&lt;p&gt;Trying to combine the prefab/scenes of Godot would be a massive headache. While EnTT might provide a thing or two, that I wouldn’t need to implement, it isn’t always beneficial to grab things off a shelf. Especially for essentially a design pattern. I fully understand if writing my own engine/editor is silly in your eyes, and I won’t try convincing anyone to write their own. I have my goals &amp;amp; reasons and respect that others have different views.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. A Very Brief History of TrackBuilder
&lt;/h2&gt;

&lt;p&gt;I’ve been making games since Y2K, when engines/tools weren’t quite what they are today. “Back in my day…” if you will. I started my current tech stack in 2012 and have participated in MANY game-jams using it. This helped me &lt;a href="https://www.patreon.com/posts/make-your-games-25152436" rel="noopener noreferrer"&gt;avoid the trap&lt;/a&gt; of endlessly working on a game engine that doesn’t actually build games. I’ve been trapped there before. By adding features for and then testing the new features in actual games (during game jams or otherwise) a feedback loop is created where games drive feature development. The engine becomes more than a tech demo. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“In 50 hours Track Builder could efficiently throw track segments together, launch the game for testing, auto-save, undo/redo support and placement/movement of simplistic objects.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In 2018 I began taking my dream of being an indie developer seriously, and after a rocky start, Turbo Boom! was conceptualized. While the game about racing with explosives is currently on hold I mention it because this is the project which brought Track Builder to life. In a mere 50 hours it became a basic editor that allowed a designer, aka me, to very efficiently throw track segments together, launch the game for testing, auto-save, undo/redo support and placement/movement of simplistic objects. Yes, auto-save and undo/redo support were in the very first iteration!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I aim to spend 10-15% of the project timeline improving the tech-stack, engine or tools.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With each game I aim to spend 10-15% of the project timeline improving the tech-stack, engine or tools. Overall I’ve been quite close to this target, and through the years I added more features to Track Builder like; box select, multi-edit, a (hacky) vegetation brush, prototyped decal placement and a spline editor/generator! These were all separate modes and Track Builder was quickly becoming cumbersome to use.&lt;/p&gt;

&lt;p&gt;By this time I had also worked with Unity to create the three games in the Eggcelerate! series and could see fairly clearly how prefabs would simultaneously refactor away the modes and create common ground for future work. Removing tons of code without removing features! In total less than 200 hours of effort went into Track Builder before starting the prefab system. The prefab system took much much longer to get the basics working.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.twitch.tv/timbeaudet" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdv9zf8b8ms937xe6v5e7.png" alt="Image description" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://www.twitch.tv/timbeaudet" rel="noopener noreferrer"&gt;watch me make games live&lt;/a&gt; almost every day and co-work alongside an inclusive, safe-for-work and chill community. When you are ready for a more technical dive, including tricks used to make code more maintainable with custom iterators and type safe UUIDs, continue with the next article to &lt;a href="https://dev.to/timbeaudet/type-safety-custom-iterators-and-runtime-structures-in-the-real-world-5e71"&gt;read about Type Safety, Custom Iterators, and Runtime Structures in the Real World.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>gamedev</category>
      <category>tooling</category>
      <category>cpp</category>
    </item>
    <item>
      <title>Game Development Essentials (Checkout my Toolbox)</title>
      <dc:creator>🏎️Tim Beaudet🚀</dc:creator>
      <pubDate>Mon, 18 Sep 2023 13:47:08 +0000</pubDate>
      <link>https://forem.com/timbeaudet/game-development-essentials-checkout-my-toolbox-59i0</link>
      <guid>https://forem.com/timbeaudet/game-development-essentials-checkout-my-toolbox-59i0</guid>
      <description>&lt;p&gt;I’ve been developing games for about 20 years and while tools sometimes come and go these are the ones I’ve been using regularly in the last year or so.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visual Studio&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Reading, writing, and debugging any C++ code for my games and custom engine. Also sometimes used for C# when creating with Unity. It is still the best debugging experience in C++, and profiling tools are easy to find hotspots to optimize.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visual Studio Code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Almost all other text editing for data, supporting scripts, web development and even tracking todo tasks with todo+ extension. Also used to attach to my local Linux box through ssh for building games on Linux and deploying website changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Premake &amp;amp; Custom Build Scripts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A custom build “system” that utilizes premake5 to create Visual Studio, XCode and make files and can build projects nightly to generate an email report of any failures. This helps me keep API breaks in my engine known and intentional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Git&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Keep track of the source-code for any project worked on for longer than 48 hours. Keeps all projects backed-up on multiple machines and locations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SVN&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Slowly moving most projects to Git for source-control to have advantage of better branching. However I still like many SVN features such as linear revision numbers and checking out a &lt;em&gt;specific&lt;/em&gt; sub-directory. Also keeps projects backed-up on multiple machines and locations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Twitch Stream&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The pressure of someone &lt;a href="https://www.twitch.tv/timbeaudet"&gt;watching me work&lt;/a&gt; keeps me laser focused. Staying focused is perhaps the most useful ‘tool’ in the toolbox today. Viewers also help with problem solving by rubber ducking, or even chat challenging your assumptions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Track Builder (Custom)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A level editing tool built specifically to develop racetracks. Spline based, tiled segments or placed objects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vim&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For small and simple edits on my local server, game servers and web servers. I’m not crazy efficient with it, but it gets the job done and I no longer get stuck trying to exit!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RenderDoc&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a great little tool for finding rendering issues with my engine, though it often requires fiddling around aimlessly until I find out what assumption went wrong. A must have for OpenGL rendering issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blender&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For the milkshakes of course. Also for practicing and building my art skills to create the visuals for my games directly as I envision them!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adobe Photoshop&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Used for various art requirements including game content, promotional images, and brainstorming with a virtual whiteboard for problem solving.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adobe Premiere&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For editing game trailers &amp;amp; YouTube videos, it was the editor that worked best for me after trying many of them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OBS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For capturing game footage for trailers, clips and other promotional content. Also used for live streaming 😮to Twitch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google Docs / Sheets&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For planning, documenting and brainstorming stuffs. Tracking my entire ad&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local Linux Box&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ssh into this because no monitors, but I use it as a file-server, for Linux builds, website deployment and running the nightly builds on Linux.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steam / Steamworks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Market research, play-testing games and finding player expectations, as well as managing my own game releases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Honorable Mentions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chrome: For all websites, tools and multiple profiles for personal vs company.&lt;/li&gt;
&lt;li&gt;Discord: Community management &amp;amp; communication with contractors.&lt;/li&gt;
&lt;li&gt;Thunderbird: For dealing with emails and custom filtering rules.&lt;/li&gt;
&lt;li&gt;PicPick: For snapping screenshots with direct FTP uploading.&lt;/li&gt;
&lt;li&gt;Moosend: For managing the mailing lists and campaigns.&lt;/li&gt;
&lt;li&gt;KeyMailer: For finding streamers/influencers to play &amp;amp; promote my games.&lt;/li&gt;
&lt;li&gt;Mortality Extension: Shows countdown (on newtab) for important deadlines.&lt;/li&gt;
&lt;li&gt;Github: For my knowledge base and public or open source projects.&lt;/li&gt;
&lt;li&gt;Gitea: To run a github-like server for my internal and commercial projects.&lt;/li&gt;
&lt;li&gt;Adobe Acrobat: To write up contracts and get them signed.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gamedev</category>
      <category>programming</category>
      <category>development</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Crafting Games: Building a Custom Editor with Undo/Redo Support</title>
      <dc:creator>🏎️Tim Beaudet🚀</dc:creator>
      <pubDate>Tue, 12 Sep 2023 12:17:32 +0000</pubDate>
      <link>https://forem.com/timbeaudet/crafting-games-building-a-custom-editor-with-undoredo-support-500i</link>
      <guid>https://forem.com/timbeaudet/crafting-games-building-a-custom-editor-with-undoredo-support-500i</guid>
      <description>&lt;p&gt;Recently I’ve added Spline Based Editing to my level editor for building racetracks. This speeds up the process significantly because the designer, &lt;em&gt;me&lt;/em&gt;, can drag a few nodes around the world and generate a smooth racetrack. The editor automatically creates the racetrack surface from a simple segment mesh that is input.&lt;/p&gt;

&lt;p&gt;I did take a few shortcuts by using the CatmullRom to create the control points/handles for the underlying BezierCurve. This ensures the curve will pass directly through all the points, but doesn’t allow the designer complete control over the curve. It shouldn’t be the end of the world to add these later, &lt;em&gt;famous last words.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Any &lt;em&gt;good&lt;/em&gt; tool will support Undo/Redo and Track Builder (my editor) is built to be a &lt;em&gt;good&lt;/em&gt; tool! Track Builder has been in development, &lt;em&gt;adding a feature here and there&lt;/em&gt;, since 2019. Undo/Redo support was built in from the start using a command-based system. Each action the user can take is a small object that modifies the state of the editor/data, like: class &lt;code&gt;AddNewOjectCommand&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This keeps a very small memory footprint and allows for the possibility of real-time collaboration features. 🤣 That will &lt;strong&gt;never&lt;/strong&gt; happen! But commands do become a pain to deal with for add and delete type actions since object lifetimes are difficult. State-based undo/redo support is a little easier, tracking each state change by copying the previous state before making changes. This uses more memory, but that’s cheap these days!&lt;/p&gt;

&lt;h2&gt;
  
  
  Protip:
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;You can actually combine the command-based with state-based undo/redo support and if your (&lt;em&gt;partial)&lt;/em&gt; state is small, it might not even use much memory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For splines the state is actually quite small, just a handful of positions, so I created a generic &lt;code&gt;ChangeSplineCommand()&lt;/code&gt; which took in the state of the spline before and after the change. This let me mix the command-based system with a bit of state-based undo/redo and get the support with minimal effort!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Not Use  Game Engine?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a great question and as an independent developer it is one that should be very carefully considered. I have weighed the benefits carefully and although speed and ease of development may be improved with a major engine, it doesn't fit my long-term goals.&lt;/p&gt;

&lt;p&gt;With a custom built engine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I have full ownership of the engine.&lt;/li&gt;
&lt;li&gt;I can design a workflow to meet my expectations.&lt;/li&gt;
&lt;li&gt;I am responsible for, and capable of, fixing bugs.

&lt;ul&gt;
&lt;li&gt;Don’t need to design/work around issues.&lt;/li&gt;
&lt;li&gt;OpenSource doesn’t always pull your fix/patches.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Having complete control over EXACTLY HOW things work.

&lt;ul&gt;
&lt;li&gt;No guessing, no undesired shortcuts, etc&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This week I’m adding functionality to create decals, the plan is to add them into the editor first as cuboids and stub out the architecture in the game engine. I plan to hire this out because …&lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://www.twitch.tv/timbeaudet"&gt;watch the development process&lt;/a&gt; of building custom editors this week and get inspired for your own tools to create games faster!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>learning</category>
    </item>
    <item>
      <title>Post-mortem of Alakajam 10</title>
      <dc:creator>🏎️Tim Beaudet🚀</dc:creator>
      <pubDate>Tue, 29 Sep 2020 11:14:54 +0000</pubDate>
      <link>https://forem.com/timbeaudet/post-mortem-of-alakajam-10-4bd6</link>
      <guid>https://forem.com/timbeaudet/post-mortem-of-alakajam-10-4bd6</guid>
      <description>&lt;p&gt;In the middle of September, game developers all over the world put their lives on hold to build a game in 48 hours during the 10th Alakajam. I was among the many and aimed to test out the custom physics engine that I barely started a few weeks before the jam. It was going to be rough. It was going to throw punches. I was going to get beaten by my own creation! My game development journey is &lt;a href="https://www.twitch.tv/timbeaudet"&gt;streamed live on twitch&lt;/a&gt;, and I was going to bring my best.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zLcyQQ37--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ceu1z37y9mja98v1mnu9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zLcyQQ37--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ceu1z37y9mja98v1mnu9.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Friday Evening:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Other game developers have already been developing their projects for a few hours while I was still work-working away. I did have the chance to mull over theme ideas, but having played a lot of Fall Guys recently I figured an obstacle course “running” game would be a great test for the physics engine. The theme was not a single but choose one or more of three themes; Maps, Chaos and/or Ships. So my idea was simple; an obstacle course on the docks where the player boards a ship.&lt;/p&gt;

&lt;p&gt;The first few hours was spent hooking the game up with my custom Track Builder tool. While this tool is focused on making race tracks it can also create more generic worlds too, and would be used to create the level. The art of the game was also created in this first hour or so with some boxes and spheres created and colored in Blender, while not the most detailed or amazing art - I do think it looks pretty good for what little effort was put in.&lt;/p&gt;

&lt;p&gt;I got started on the physics by taking the objects loaded from Track Builder and converting them into RigidBodies for the physics system. I was trying something new and allowing objects to be scaled in Track Builder, but I knew the physics system would not support scaling so during load I had to remove the scale from each box/sphere before shoving it into the physical world. The physics engine delivered the first punch by containing only spheres and static-boxes, so the player object was forced to be a sphere.&lt;/p&gt;

&lt;p&gt;The remainder of the evening was spent fighting with camera and player controls, neither of which went to plan. Instead of prolonging a pointless fight with these issues I went to bed to get rested for the following day of development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Saturday Morning:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While trying to fall asleep I had a breakthrough in how to get the camera to do what I wanted and how the player movement might work out. In less than an hour I had this behaving as desired and was able to start playing around. That is until the physics engine dealt another blow. With the player moving it became apparent there were issues with oriented boxes as the dynamic sphere phased through them.&lt;/p&gt;

&lt;p&gt;During the development of the physics engine, prior to the jam, I had created both visual and unit tests of intersecting the boxes and spheres and found no issues. After an hour of digging into the issue the solution was to avoid the problem by not using oriented boxes that were scaled. Which limited a bit how the level could be designed.&lt;br&gt;
The first obstacles added were doors/gates that slide up and down and the player had to get the timing correct. Later in the weekend I concluded this obstacle had very little interest because there was nothing rushing the player to get through. While adding all of this to the level I found I was getting annoyed with Track Builder which was dropping the scale of aligned-boxes when duplicating objects.&lt;/p&gt;

&lt;p&gt;During the 15 minutes of digging into code for Track Builder to support duplicating scaled objects without rotation I had a hunch that I did it wrong back when loading the level into the physical world. With a bit of google’s help I got it solved and fixed the issue with oriented boxes being scaled! Double victory, ramps were possible once again!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EVGsCWyx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cwo1on00nqgb9829gion.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EVGsCWyx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cwo1on00nqgb9829gion.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Saturday Afternoon:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What shipping docks would be complete without having cannons firing into the harbour? Originally this obstacle was going to be falling crates that push the player around - but that didn’t test anything new on the physics system. Shooting cannonballs from cannons would prove how dynamic spheres worked in action. I did note an issue with the cannonballs behaving in a “sticky” manner where gravity seemed to affect one less as it resolved collision with the other.&lt;/p&gt;

&lt;p&gt;This was clearly something to work around but the theory is the collision response separating the balls from intersecting is overriding the forces of gravity. During this I also had to test removing RigidBodies from the physics world, except that function did not exist. Well it did but some funny guy named it “DisposeOfBody()”. That got promptly deprecated and replaced by RemoveBody(). &lt;/p&gt;

&lt;p&gt;After programming in a language for more than 15 years you would think I’d be competent at a task as easy as removing elements from a container. Instead I fell directly into the trap of expecting std::remove() to remove the bodies from the container. In C++ this is not what happens for various reasons. Instead C++ requires the use of the “erase remove idiom” to actually destroy the items removed.&lt;/p&gt;

&lt;p&gt;I only discovered this trap because I made the cannons fire at incredible rates of speed compared to how slow the cannonballs got destroyed. That said the physics engine defended well for not having any bounding-volume hierarchies or any broad-phase tests. Using O(n²) for the intersection tests with over 500 cannonballs and lots of boxes, aligned and oriented, in the level. Future work is planned to ensure each cannonball only tests things near it instead of everything in the physics world, but for now, it worked better than expected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Saturday Evening:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another mini-game was started that combined two games from Fall Guys, the memory game and tip-toe. The player was expected to memorize the path across as all the tiles looked identical but many would fall without having collision. This was to tie in with the theme of “Maps” a little by requiring the player to map out the safe path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sunday Morning:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First efforts of the morning were to improve the memory mapping game and create a second, easier, version of it where the tiles would remain fallen. Also got the tiles shaking to warn the player it is unsafe to move onto. This prompted the addition of checkpoints because it would be obnoxious to cross the tiles of doom only to fall into the drink and restart everything again. So safety points were added to the level that would respawn the player at that location again.&lt;/p&gt;

&lt;p&gt;With three obstacle sets and the jam deadline approaching it was time to focus on a finish objective. I quickly modeled a very poor ship and treasure chest for the player to reach and put a victory trigger around it to show their time and how many times they fell into the harbour.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--utaISAIj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bqv2qtq6u20dok3ykfuw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--utaISAIj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bqv2qtq6u20dok3ykfuw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Went Well!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The physics system worked great, it behaved and performed well, exceeding all expectations. The obstacle course idea was simple to execute and could shrink or grow as necessary for time constraints. The art, although just colored primitive shapes, came out better than imagined and  creating the water effect was quite simple using the ocean generator in Blender.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What was learned?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The major issue with “the physics engine” faced during the event was due to removing the scale while putting objects into the physics world and wasn’t actually the physics engine.&lt;/p&gt;

&lt;p&gt;During Alakajam 10 I was keeping a list of each pain point as it was discovered. This list grew to 35 items and I was able to quickly knock out more than 30 of them in preparation for the next jam this weekend. LudumDare 47 starts on Friday and I will be using it to test the physics engine again. I will of course be streaming my developments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.twitch.tv/timbeaudet"&gt;Follow me on twitch&lt;/a&gt; to see a game get developed from idea to release.&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>game</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Learning From Unity After 15 Years of GameDev with Custom Engines</title>
      <dc:creator>🏎️Tim Beaudet🚀</dc:creator>
      <pubDate>Mon, 18 May 2020 13:00:09 +0000</pubDate>
      <link>https://forem.com/timbeaudet/learning-from-unity-after-15-years-of-gamedev-with-custom-engines-414o</link>
      <guid>https://forem.com/timbeaudet/learning-from-unity-after-15-years-of-gamedev-with-custom-engines-414o</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Y-oDUT73W8k"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I started developing custom engines 15 years ago as tools like Unity did not really exist back then and it was pretty rare or expensive for projects to use a third-party engine. For the month of April I took a different approach and jumped into Unity to explore work-flows and different tools. I also wanted to explore the idea of releasing an asset pack to focus on improving my art skills and try increasing the income of my game development adventure.&lt;/p&gt;

&lt;p&gt;The art pack never happened because I shifted gears in the middle of April since my LudumDare game was a lot of fun. Before LudumDare I had created a very small infinite-runner-like game to dip my toes into Unity, then I ported some portions of Turbo Boom! just to keep investigating without wasting time designing a new game. During LudumDare 46 I created Eggcelerate! and was rated 12th. I continued a post-jam version which you can &lt;a href="https://timbeaudet.itch.io/eggcelerate"&gt;grab now on itch.io&lt;/a&gt;, or &lt;a href="https://www.youtube.com/watch?v=BF9f5PckXhI"&gt;check out the trailer&lt;/a&gt;. It is eggcellent and filled with rotten yolks.&lt;/p&gt;

&lt;p&gt;Eggcelerate! took 3 weeks to create and supported the exploration of more tools and work-flows in Unity. I didn’t get the chance to explore everything, like particles, shaders, and other special effects however I got the basics. I wrote down many work-flow improvements and ideas for editor tools along with some pain points I’d like to avoid in my own tools. I will return to share a post-mortem that will discuss the art lessons I had while doing the art for Eggcelerate!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From my notes I found 5 major items from Unity that could improve my work-flow and engine tools.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Camera Gizmo
&lt;/h3&gt;

&lt;p&gt;One of the first things I will be adding to my editor is the camera gizmo. This allows changing to or from orthographic mode and alignment with a world axis. While orthographic mode tends to break my brain, it is super useful when placing certain items with an aligned view; say looking top-down to place the checkpoints along the racetrack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vertex Snapping
&lt;/h3&gt;

&lt;p&gt;I also found vertex snapping to be super useful as well. Just press and hold V, select a vertex from one of the selected items and then drag toward a vertex in the world for automatic placement. However I did notice Unity got extremely slow with this when I had added some corn-fields in my world. While that definitely increased the number of vertices; my dragging wasn’t anywhere near their location and I would have expected some broad phase collision to have reduced this lag. This one will definitely take an effort to get right and will be useful in more situations than the specialized implementation of my segmented track editor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Editor for Bounding Volumes
&lt;/h3&gt;

&lt;p&gt;If it were easier my first task would be adding the bounding volume editor. My present work-flow is to adjust numbers in C++ or JSON data and recompiling or hot-loading until the debug display matches expectations. Dragging this around is far faster, though takes more infrastructure than I presently have available. It is perhaps the most valuable of the additions which would make collision volumes easier to create.&lt;/p&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;p&gt;My framework has a concept of entities, though not completely component-based. I went with a behavior system that allows for code-reuse and sharing. Only one behavior is active on an entity at a given time and can be popped off a stack. After playing with Unity I believe it would be in my best interest to add a more typical component-based system to my entities for more code sharing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wild-and-Free Mindset
&lt;/h3&gt;

&lt;p&gt;A significant improvement to the work-flow I had in Eggcelerate! was just not caring about things. This is certainly a balancing act and too little care will lead to significant development issues. In the prototyping stage the speed of development outweighs almost everything. While I do prototype my projects early on, it isn’t as quick or nimble. I suspect this comes from many reasons, but changing into Unity flipped my brain into a wild and free mode that I haven’t experienced for a while.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I was primarily focused on features that would be desirable yet some Unity tools rubbed me the wrong way and I would like to avoid them in my own tools. Some of this is just the nature of tool development and others might be personal preference.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Having Bad Defaults
&lt;/h3&gt;

&lt;p&gt;This will be hard to avoid in practice, but having good defaults go a long way to making a smoother experience. I found many defaults in Unity to get in the way. Having an AudioClip set to “Play on Awake” for instance was extremely frustrating and at one point led me down a rabbit hole to try fixing a bug where a sound was playing when it shouldn’t.&lt;/p&gt;

&lt;h3&gt;
  
  
  User Experience
&lt;/h3&gt;

&lt;p&gt;It was annoying that the keys to translate, rotate, scale and such were mapped to qwerty keys, but R didn’t rotate, and T didn’t translate. I’ve heard this is the same in Unreal and other engines, though it hurt my brain. I had to constantly press all the buttons to find the widget I desired; just moving the order of two of the most common tools could reduce that guess-work significantly. The big picture here is to keep the user in mind when developing tools. I can see qwerty being useful to users with experience from other engines with similar hotkeys, but as a tool developer we must ask are we just following a convention without purpose, or could it be better?&lt;/p&gt;

&lt;h3&gt;
  
  
  Load Times
&lt;/h3&gt;

&lt;p&gt;Unity took ages to start especially so once asset packs were added to the project and I didn’t consider those to be very heavy. This isn’t a massive issue as exporting and processing items will always take time, but it was all at once and felt disruptive, perhaps more so from a streamer perspective. This was also faster than all the times I would need to rebuild my engine libraries. It would be useful if my editor did not take forever to load a project. &lt;/p&gt;

&lt;h3&gt;
  
  
  Play Mode Crashing
&lt;/h3&gt;

&lt;p&gt;Near the end of the month Unity started crashing on me and in the logs it seemed to come from a bad SSL certificate; that is the best guess I have from my experiences and I saw other developers commenting on it. This wasn’t very fun, nor did it seem useful to me as a developer having opted out of analytics…&lt;/p&gt;

&lt;p&gt;One thing I missed from my own editor was the ability to hold shift and drag and object to create a duplicate. This works so much smoother, in my experience, than pressing CTRL-D just hold shift, drag, drag, drag and you now have three extra copies of the object.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;While that stuff could be smoother there are a few reasons to choose Unity over building a custom engine. If you are building your own or thinking about doing so, make sure to consider the following:&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Time is Money
&lt;/h3&gt;

&lt;p&gt;The most obvious benefits of using Unity is not investing a substantial amount of time and effort in creating your own engine, adding support for all the platforms, and dealing with inevitable bugs that would otherwise be worked out. This can be huge financial savings as time and money are strongly related from the business perspective.&lt;/p&gt;

&lt;h3&gt;
  
  
  Great for Prototypes
&lt;/h3&gt;

&lt;p&gt;Unity is GREAT at prototyping games and this was a driving force behind it for years. I will almost certainly be using it in my adventure for future prototyping needs because of the mindset shift I mentioned earlier where it allows me to be a lot more wild and free. It also contains many things my engine does not which would let me test more ideas faster. After finding an idea I like I can then move into my engine and do what is necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Importing from Other Tools
&lt;/h3&gt;

&lt;p&gt;The import process from Blender to Unity was extremely smooth, I assume the same for other tools. Just add the .blend to the Assets directory and automagically the mesh objects inside are converted to fbx and Unity formats. This means just hitting save will automatically update the contents in-engine.  My custom engine supports hot-loading of mesh assets but I need to both save the blend file normally, and export it. My exporter does support batch exporting already so the friction has been reduced, but processing the blend file directly is a very interesting thought. This is likely far too much effort for a solo-developer given the actual value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mass of Information
&lt;/h3&gt;

&lt;p&gt;Another advantage to using Unity is the mass of information available. When you want to solve a common problem, like perhaps a chase camera, it is quite easy to google and find what you need. Sometimes the asset store will have a full solution ready to go, though I didn’t use any in my exploration. This is not a huge advantage, but when prototyping it certainly sped things up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generic Use Case
&lt;/h3&gt;

&lt;p&gt;Unity is good for generic use, it can make first-person shooters, platformers, role-playing games and everything in between. However I am remaining focused on racing games, and a custom engine will allow me to specialize the tools to fit those needs. This specialization will allow for faster development times in the specific case of racing games, though it may reduce the ability to make other game genres.&lt;/p&gt;

&lt;p&gt;After a month of exploring Unity my thoughts have changed slightly. I was expecting to never touch it again but instead will likely use it for prototyping new ideas and during game jams. For long term projects the lack of low-level problem solving and code architecture would cause me to burn out.  I will continue to use my own engine for many reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I am specializing in racing games and can specialize my engine for those needs.&lt;/li&gt;
&lt;li&gt;I enjoy code architecture, watching a structure grow and interact with other portions.&lt;/li&gt;
&lt;li&gt;I enjoy having complete control over how something works.&lt;/li&gt;
&lt;li&gt;Avoid issues with poor documentation, kinda, and API breaking updates.&lt;/li&gt;
&lt;li&gt;Finally I started 15 years ago when Unity did not exist, and engines were rarely used, it is the way my mind works and this is why Unity isn’t worth it for my larger projects.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For my indie adventure I choose to build my own engine and specialize it for racing games to keep my sanity during the long-haul.&lt;/p&gt;

&lt;p&gt;When making the choice for yourself, consider that your needs are likely different than mine. As a hobbyist a generic engine probably makes more sense than a specialized one as it allows more options. From a business perspective it depends on more. While the cost of most commercial engines is tiny compared to building a custom one, at least these days, there is some advantage in specialized tools. A business may also not wish to deal with API breaking issues while updating the tools. That said for game business with no genre in mind an engine is a massive boost and from my previous experience pitching to publishers, a popular engine could increase potential partnerships.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://timbeaudet.itch.io/eggcelerate"&gt;Go have fun balancing eggs in Eggcelerate!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>unity3d</category>
      <category>csharp</category>
      <category>management</category>
    </item>
    <item>
      <title>My First Game in Unity (After Creating My Own Engines for 15 years)</title>
      <dc:creator>🏎️Tim Beaudet🚀</dc:creator>
      <pubDate>Sat, 25 Apr 2020 11:33:54 +0000</pubDate>
      <link>https://forem.com/timbeaudet/my-first-game-in-unity-after-creating-my-own-engines-for-15-years-3bhk</link>
      <guid>https://forem.com/timbeaudet/my-first-game-in-unity-after-creating-my-own-engines-for-15-years-3bhk</guid>
      <description>&lt;h1&gt;
  
  
  Event Details
&lt;/h1&gt;

&lt;p&gt;The theme of LudumDare was announced at 9:00pm Friday evening. Keep It Alive. I like sketching ideas on a scratchpad, but the bamboo tablet was fighting me with Windows Ink or other Photoshop settings. It took ten minutes to setup a relay stream from my macbook which has a much better tablet setup, but it made it more comfortable for sketching.&lt;/p&gt;

&lt;p&gt;After running through some ideas, with viewers from my &lt;a href="https://www.twitch.tv/timbeaudet"&gt;game development stream&lt;/a&gt; throwing in great comments, I steered very quickly into the egg in a bowl on a car. Actually I have wanted to make this very game for years, as it can be a good training tool for driving smoothly at the limit. I continued brainstorming for a bit longer, but this was the idea that pulled the hardest.&lt;/p&gt;

&lt;p&gt;45 minutes after the theme announcement I had committed to the idea and created a list of tasks required for the game. Being near bedtime I chose to work on modeling assets for the game. This is one of the first jams I have ever started with art before programming. Doing so can be somewhat risky, especially  if ideas or concepts are subject to change. I knew the basic objects; car, bowl, egg and some track segments would not be a waste of time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XJKKeSDZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/satbqu6d82db33vzyz87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XJKKeSDZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/satbqu6d82db33vzyz87.png" alt="Alt Text" width="880" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It took one hour to get all the assets created, using &lt;a href="https://www.youtube.com/watch?v=YALV3HqfdLY"&gt;Imphenzia’s&lt;/a&gt; method to make the cars was very quick and easy; though I can’t do them in 10 minutes. Yet! Perhaps my blender practicing is starting to pay off as this process went super smoothly. With some art created I jumped into Unity. At that point I had used Unity for less than 15 hours, and this would be my first jam in it. Upon importing the assets I noticed issues with the lighting and coloring. I went back and forth between Blender and Unity trying to find the issue, tried exporting to fbx manually, nothing fixed it. Though I didn’t figure it out until the middle of the next day, it turned out that my 4×16 color palette was being compressed and lost color information.&lt;/p&gt;

&lt;p&gt;By 11:30pm, 2.5 hours after the theme was announced, the track segments and other objects were setup as basic prefabs and a super simple track was created in Unity. There were no scripts or anything but I went to bed happy with the progress so far.&lt;/p&gt;

&lt;p&gt;This is the first game jam where I did not toss and turn with ideas racing for three hours before getting sleep. Writing the list of items to do, and separating fun extras from the minimal requirements, certainly helped a bit as my brain didn’t fight to remember them. In the morning I woke at 5:45am, which I do every morning for my game development stream and indie adventure. After animal care and breakfast of 30 minutes, I got back to work. 9 hours and 15 minutes after theme announcement I was ready for day two.&lt;/p&gt;

&lt;p&gt;The majority of the second day was spent learning Unity and attempting to create the physics of a driving car and get the egg to work with the bowl. For the car I used wheel colliders and had a crazy time trying to understand how to setup the wheels with good values. It was very easy to hook up the motor, brakes and steering to the racecar script, but the dynamics felt sloppy, slippery – not quite in the way I wanted.&lt;/p&gt;

&lt;p&gt;After reading &lt;a href="https://docs.unity3d.com/Manual/class-WheelCollider.html"&gt;the documentation&lt;/a&gt; many times it took drawing it out to understanding how the slip extremum and asymptote differed from value extremum and asymptote. Also, that stiffness is just a multiplier of value… It took most of the day, but finally I got the car moving in a way that was good enough for what I wanted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--42RZgmno--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cnwmpk5bdgbb8pqcw2l2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--42RZgmno--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cnwmpk5bdgbb8pqcw2l2.png" alt="Alt Text" width="880" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, the bowl was added to the top of the car and getting the egg to stay in was far more tricky than imagined. Unity made it easy to add a mesh collider, and even allows the collider to be non-convex, but requires the rigid body to be kinematic. This seemed okay at first, it even kept the bowl constrained to the car as desired. The egg however failed to accelerate correctly. Kinematic bodies require a developer to perform their own physics handling, even on the bodies they interact with..&lt;/p&gt;

&lt;p&gt;After much exploration, and dragging my feet, I finally gave in and created the bowl colliders out of several box colliders layered together at various angles. This actually didn’t take nearly as long as I expected, and I should not have dragged my feet. The egg worked very well with the bowl after this.&lt;/p&gt;

&lt;p&gt;Finally, I was able to drive around and carry an egg and watch it fly away from the car when driving too aggressively. Added a button to reset the car and egg back to spawn point and it was time for sleep number two. Which also went fairly easy, but not quite as quick as the night before, still only 30 minutes or so to calm down the busy mind.&lt;/p&gt;

&lt;p&gt;The following morning, again waking at 5:45am, I got started on detecting the egg shattering on the ground as the lose condition. When in this state the game will pop up a small display of the title and a retry button. For added effect a cracked egg asset was created and placed on the surface of contact. A decent improvement would be to align with surface normal, but I just used world up for the jam entry. Also I desired the splats to remain from previous attempts so I never cleaned these up. This worked for a jam entry but a larger project would need to clean up after a certain number of attempts.&lt;/p&gt;

&lt;p&gt;Timing and scoring was the next major feature to be added which made use of some box colliders to tell the racecar what checkpoint was hit. This allowed the car to know where it was and ensure a complete was driven before increasing lap count or time. Displaying this, and the retry screen, to the player was confusing for me as a first time Unity developer. I had played with Unity UI for about 30 minutes prior but in that previous project I found it didn’t handle resolution changes very well. Eggcelerate! did not handle this much better, but I certainly tried. (There have since been some notes that the title screen behaves odd on some resolutions.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NJ2v_Jr2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f7wc5rg73wjahotnbbqi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NJ2v_Jr2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f7wc5rg73wjahotnbbqi.png" alt="Alt Text" width="725" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By grabbing a screenshot of the game in play mode, after learning about options to view a different display in a second game tab with viewer support, a title screen was created. In photoshop a quick gaussian blur was applied to the title, and text was added from Unity. In hindsight, I should have added the title text from within photoshop… next time.&lt;/p&gt;

&lt;p&gt;At this point the game was complete. Somewhat silent, but you could lose and compete against the clock for a best time. So far I have seen a screenshot of someone that got a 27.420, while my best is a 27.500. The game desperately needed sound, and while I am awful at music, a viewer shared &lt;a href="https://beepbox.co/"&gt;beepbox.co&lt;/a&gt; with me and I was able to produce something that didn’t melt my brain. After adjusting the instruments it sounded vaguely farmy, and was applied to the game.&lt;/p&gt;

&lt;p&gt;For sound effects the big old mouth was used. I just made some vrrum noises at the mic with various methods and repeated for the rest of the effects. This worked shockingly well and was more funny than intended, but also fit with the game.&lt;/p&gt;

&lt;p&gt;As the game grew, it became harder and harder to add new features. Timing and scoring for instance had to handle edge cases when the player lost. Otherwise laps could be driven without an egg. The engine audio needed to be paused when on the title screen. One thing I found annoying with Unity sounds is the automatically checked “Play On Awake” option. It took a while to figure out why the horn sound was playing when not expected. This later bit a few more times.&lt;/p&gt;

&lt;p&gt;With almost 5 hours still remaining, I was able to create more environment props and track segments that included a banked corner and a hill, barn, silos and fences and more. Initially desired the fence to be dynamic but settled for static when that didn’t work. Static was probably the better option anyway to keep the player on the track. More fences should have been placed near the hill to keep the player from going around. There is a checkpoint  that requires the player to go over, but the lack of fence may confuse them into thinking the lower path is viable.&lt;/p&gt;

&lt;p&gt;With about an hour left I started preparing builds. Unity sure makes that process far easier out of the box than my custom framework and workflow, but the first 2 builds failed as I forgot to turn on music, then tried making last moment changes to the Title Screen that looked okay in the game player but not in the standalone. This goes back to the resolution issues, I need to spend more time learning about Unity UI.&lt;/p&gt;

&lt;p&gt;I spent 25 hours working on Eggcelerate! during LudumDare 46 though I am going to extend the project further as it shows solid potential.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wwJOxK0l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wntz28jfscpcclo15e8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wwJOxK0l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wntz28jfscpcclo15e8w.png" alt="Alt Text" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What Went Right?
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Brainstorming a simple game idea
&lt;/h3&gt;

&lt;p&gt;This was fairly quick and easy to come up and get really eggcited about. It had low requirements and was something I could probably snap together quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Starting with Art
&lt;/h3&gt;

&lt;p&gt;Creating the basic assets went significantly faster than expected and made the game look good right from the start. This started the project on a great path, though I would be weary about starting with art as it can go wrong quickly as pivoting content/ideas is painful in a jam.&lt;/p&gt;

&lt;h3&gt;
  
  
  The game is amazing
&lt;/h3&gt;

&lt;p&gt;Eggcelerate! is by far my best solo jam game. It is easy to drive around with an egg around in a bowl, at slow speeds, but it gets incredibly difficult to speed up. The player feels like each failure is their fault and “I’ll do better next time” making it quite fun and addictive.&lt;/p&gt;

&lt;h1&gt;
  
  
  What Went Wrong?
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Fighting Unity Physics
&lt;/h3&gt;

&lt;p&gt;To be fair I would have been fighting Bullet physics if I used my more traditional setup. Unity at least had significantly better documentation, though still wasn’t explained very well. Both wheel collider and bowl collision took significant time to get reasonable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Not knowing Unity UI
&lt;/h3&gt;

&lt;p&gt;There are some issues with different resolutions and some of the screens or interface elements. I noticed the anchoring, which in theory is intuitive, but – it isn’t. I couldn’t figure out if the anchors were to screen edges or what was happening. Title screen seemed cutoff, but I think the mistake was making it larger than ‘screen’, if I understand the tool correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Not being able to use tablet on main PC
&lt;/h3&gt;

&lt;p&gt;This was a minor inconvenience of 10 minutes or so, and lowered mic quality on stream for a bit, but Windows Ink and Photoshop settings made the tablet on the Windows rig unusable.&lt;/p&gt;

&lt;h1&gt;
  
  
  Lessons Learned
&lt;/h1&gt;

&lt;h3&gt;
  
  
  How to manipulate vehicle controls with Wheel Colliders
&lt;/h3&gt;

&lt;p&gt;It was important to know that Stiffness is just a multiplier to value, so leave this at 1 for testing purposes, then adjust it for terrain variation like 0.2 for ice, etc. Also the extremum of slip should be lower than the asymptote of slip as slip is on x-axis of the graph. It took drawing this out myself to get that to click and start understanding how the values were working together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concave mesh colliders don’t work as expected
&lt;/h3&gt;

&lt;p&gt;A non-convex mesh collider is possible, though Unity throws an error to require a kinematic rigid body. At first glance this ‘worked’ but not completely. Sure the egg would move with the car/bowl, but any speed or jostling and it warped out; The egg never gained velocity. The collision simply moved the bodies apart and never affected momentum as expected. The solution was to build a custom collider from many boxes / convex meshes and keep kinematic off. This initially caused the bowl to go flying off until I constrained the position x, y and z.&lt;/p&gt;

&lt;h3&gt;
  
  
  Texture Compression is not Lossless
&lt;/h3&gt;

&lt;p&gt;While this is something I should have known already, I totally missed this. A few viewers suggested it as the cause of the visuals being odd, and I dismissed them because “why would that change anything”. After hearing it a few times, it was worth checking, and the cause was found. A 4×16 pixel texture being compressed.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/x_vj7Pi5YAY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>unity3d</category>
      <category>csharp</category>
      <category>gamejam</category>
    </item>
    <item>
      <title>20 Questions You Asked About Game Jams!</title>
      <dc:creator>🏎️Tim Beaudet🚀</dc:creator>
      <pubDate>Mon, 13 Apr 2020 11:00:58 +0000</pubDate>
      <link>https://forem.com/timbeaudet/20-questions-you-asked-about-game-jams-4hlg</link>
      <guid>https://forem.com/timbeaudet/20-questions-you-asked-about-game-jams-4hlg</guid>
      <description>&lt;p&gt;&lt;strong&gt;I'm a total gamedev noob and my game won't be any good, should I join a gamejam?&lt;/strong&gt;&lt;br&gt;
As long as you go into the jam with the mindset of learning and creating anything then absolutely jump right in. There should be some caution taken if it will be likely to cause frustrations. There are a lot of developers who made their first ever game during a game jam and most jamming communities are very welcoming to new developers. It is advantageous to know the tools, but it is also possible to learn on the fly as well.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/A_su-iHutkE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if I can't come up with a unique or original game idea?&lt;/strong&gt;&lt;br&gt;
While there are points for originality I personally believe it sometimes overrated and this should not be a reason to worry. If ‘coming up’ with a unique idea is burning you out, just use one that excites you whether it is truly unique or not. Many people will use platformer mechanics, but each game is subtly different and yours will be too. Last week I made my first game in Unity and used an infinite runner like mechanic to explore the engine. A viewer of my streams made a game using the same infinite runner mechanic, but their game played very differently from mine.&lt;br&gt;
It is important that an original idea does not become an excuse to stop you from having a good time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With so few hours in a game jam, how do you plan your time to avoid waste?&lt;/strong&gt;&lt;br&gt;
First I don’t really plan anything during a game jam and just let things happen. That said I use chunks of time to keep things on track during the weekend. The first chunk actually starts before the jam ensuring groceries and other life chores won’t need attention or cause distractions. In a team event I also ensure the entire team knows the schedule and ideas. Once the jam starts a chunk of time lasting an hour or two is started that allows for designing the idea and “planning” how to tackle it.&lt;/p&gt;

&lt;p&gt;Keep the plan minimal. Just answer the question “can I make this before the deadline?”. The next chunk of time is set to about 4 hours and used to get the game working. Gameplay, Win condition, lose condition etc. Just use blocks, shapes and colors and rough out the idea. I find even while aiming for 4 this  often it stretches to 6 or 8 hours. Try keeping it short, it helps. After this chunk, the rest of the time is spent making it better. This final chunk doesn’t really have a plan, I just constantly ask myself “What does the game need to become better?”&lt;/p&gt;

&lt;p&gt;Avoid adding features to make it better, just polish and tune the ones you have. Perhaps your camera is working, but feels a little rigid. Attaching it to the target with a spring/damper could make the game easier to view. Always look for the lowest effort and biggest value, then repeat.&lt;/p&gt;

&lt;p&gt;In a team event a final block of time should be set aside before creating final builds to ensure that everything gets into the game. During this block new things shouldn’t be created. Other team-members could start testing to look for anything super game-breaking, or writing up the material for release.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it make sense to have a reflection after the jam?&lt;/strong&gt;&lt;br&gt;
Absolutely. Highly recommended for both solo and teams to reflect on what happened. Investigate both the game itself and the development processes. How could the team work together better? What processes and tools worked well? Find a few good things that you would like to repeat next time, and a few things that could be improved upon. What slowed down development? Write this information down. Reflecting like this allows learning from the experiences, I do it monthly in my adventure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How can game jams benefit your larger projects?&lt;/strong&gt;&lt;br&gt;
While many jams wind up as small throw-away projects some communities like AlakaJam have an Unranked category that allows you to continue on a larger project. By focusing on a subset of the large project you can still jam with the community and give feedback. In multiple LudumDare events I’ve been able to make new tools for my game development framework, or even levels ongoing projects. Sometimes this takes a bit of effort and creativity to fit into the jam environment but it can work, even if a little logic needs to be recreated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where should someone who wants to participate in game jams start?&lt;/strong&gt;&lt;br&gt;
There are lots of jams available as you can see on indiegamejams.com or itch.io/jams and almost all communities are very welcoming to new participants. Some jams last 7 days or longer and others as short as an hour. As a new developer sometimes a jam provides a good motivation for learning, and other times it can be overwhelming. Depending on your personality you might want to practice before jumping to a jam, or maybe just dive right in.&lt;/p&gt;

&lt;p&gt;The longer jams have a few benefits of allowing more time for learning and more time to create a more polished game. This tends to be a more relaxed experience, though can quickly fall into a procrastination trap for many. “I have 5 days, I’ll do that tomorrow”. The 48 hour or weekend jam is a pretty good sweet spot for avoiding that trap while still having enough time to get something done. As a new developer just know your skills will grow, and submit what you create - even when you wish it were better. Trust me, it is nice to look back on the progress later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can an incomplete game also be a game jam success?&lt;/strong&gt;&lt;br&gt;
Absolutely. Without a doubt. There are many ways to be successful with an incomplete or broken game from a jam. The most obvious being what can be learned from the experience. Take a bit of time to do a quick post-mortem review of the project and process you went through. This lets you consider what went right and what went wrong during the creation process, and allow you to make adjustments in future projects.&lt;/p&gt;

&lt;p&gt;There is also value in having created SOMETHING. While games have become much more approachable for people to create, it still takes a lot. You should congratulate yourself no matter how far you got, trust me, my first attempts at an official game jam were really bad and I had already got a Bachelor’s degree in Game Design and Development, then worked in the game industry for over a year and a half before my first jam. It was rough, the first attempt my attempt to use “procedural” levels took too much time and my engine was filled with bugs, the second attempt I simply went far too big with scope and nobody understood how to play. These are barely things I would call a game today, but successful for learning and creating something.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to not become discouraged by not producing the results you want?&lt;/strong&gt;&lt;br&gt;
Sometimes in the middle of the jam, after the “honeymoon” phase, about where the real work starts kicking in, an overwhelming sense of doom begins. “The game is not good enough” takes over and challenges you and the team. This feeling has been in every single jam I have participated in and while difficult to shake off it, gets easier with time.&lt;/p&gt;

&lt;p&gt;It helps a great deal to understand you are making an entire game in a single weekend. Not an easy task. After commiting to your idea and starting the project, you often build internal hype for the game. Feelings are boosted by envisioning magic visuals and super fun gameplay… This is difficult to find with months of development so when your idea runs a little short it becomes easy to think about the ideas you didn’t choose. This tempts you into changing course, or worse quitting the jam.&lt;/p&gt;

&lt;p&gt;One way I power through this is by doing my best to keep low expectations of a game created in a single weekend. Understand that the game will not match the vision, and power on without swapping to an earlier or different idea. Even Turbo Boom! which has been in development for 6 months, when I planned for 4, is not matching my vision quite as much as desired. This is just how creativity works sometimes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can you specialize in a role while participating alone in a game jam?&lt;/strong&gt;&lt;br&gt;
It is certainly easier to specialize while doing a team event as you can be the dedicated artist, or musician or programmer etc. In a solo jam you need to do everything or you will just have pretty art, good music or code. That said it is still possible to specialize while doing the general tasks. I have a background in programming and naturally feel most comfortable writing code. To practice the artist role I can give myself only 4 hours of programming and focus on art much more. This will allow me to spend the majority of the time practicing new skills and specializing in the artist role.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can a gamejam affect me during my day-job aside from just plotting the next steps?&lt;/strong&gt;&lt;br&gt;
Aside from the mindset of plotting it is possible you wreck sleep schedules during a jam. For this reason and more, I highly recommend keeping your normal eating and sleeping habits. Do not try staying up really late, or eating food that you wouldn’t otherwise normally eat. Lack of sleep will affect your concentration and lead to very simple bugs being hard to track down. This can also plow into your day-job, though you know your body best; some people recover faster and others slower.&lt;/p&gt;

&lt;p&gt;If you are unsure, it can be wise to plan and request a personal-day following the jam just to have some time to recover.&lt;/p&gt;

&lt;p&gt;After doing a lot of game jams, how do you keep the motivation to continue?&lt;br&gt;
This can actually get harder as you do a lot of jams and wish to focus on long-term or larger projects. One trick is to mix things up. If you usually work alone, try jumping into a team to learn more about that process. Try specializing in a role you are not great at, build new skills. Use your strongest skills to challenge yourself with other limitations; Can you make the game look good with only 4 random colors? Focus on programming a game using a different language and framework than you normally use.&lt;/p&gt;

&lt;p&gt;For anyone creating their own engine or tools, a game jam provides an amazing opportunity to test under time pressure and slight stress which will show weak points in the design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When do you start to organize a team?&lt;/strong&gt;&lt;br&gt;
The latest I start organizing a team is the final week before the jam, as in the next couple days. I like knowing who is on the team, what their roles will be and have plans of open communication no later than Wednesday before the jam. I’ve started organizing teams as early as a few weeks before an event. Waiting until the day of, or during the jam, is a very difficult time to find participants for your team, not impossible but difficult.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do you come up with an idea as a team?&lt;/strong&gt;&lt;br&gt;
Together.&lt;/p&gt;

&lt;p&gt;Seriously in all team collaboration projects, for a jam or just for fun, I will always get as many team members as possible to join the first session where the ideas are formed. This is crucial for giving ownership to everybody. Sure team members will come in with some ideas of their own, but as the group discusses these and other ideas in a brainstorm session they will spark more ideas and the group together will start working more on one idea than others. This is usually when I try suggesting to focus on that idea for the weekend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if the team can’t agree on any idea?&lt;/strong&gt;&lt;br&gt;
I have only once had a stalemate with a team finding an idea to work on. No ideas getting discussed was really jumping very high on the interest charts and conversations bounced around for nearly 90 minutes. To keep things moving, in this rare situation, I grabbed one of the most simple mechanics that had been mentioned during the planning session and focused the group on that. It actually wound up being a great game.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can you take input from other team members regarding “your” idea, even if it changes the idea entirely?&lt;/strong&gt;&lt;br&gt;
This is definitely a personality thing and you need to be able to remain open minded and discard any preconceived ideas you might have going into a team event. As mentioned earlier it is best to come up with the idea together as a team. This requires some give and take, and that may require practice. When I first started collaborating for fun, in  non-jam situations, I would allow others to take the driver seat and lead the project even if I had more experience. Even if I thought they were doing things “wrong” or “the hard way”. I would remain open to that path. Doing this allowed me to practice opening my mind, and sometimes the “wrong” or “hard way” may not be as bad as you think initially. Often, it is just different.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do you handle a person in a team who delays the team efforts?&lt;/strong&gt;&lt;br&gt;
First and most importantly is to understand a game jam is not a job and it is done for fun. So when someone doesn’t show up, or they don’t deliver, or whatever issue it might be, address it with the understanding that this is all for fun. It certainly can put a damper on the team when a member doesn’t pull their weight, and yes it has happened to one degree or another in a few projects. This is bound to happen on group projects from time to time unless you know and trust each member very well, and even then it can still occur. Things happen.&lt;/p&gt;

&lt;p&gt;Generally in a jam situation I tend to ignore problems unless it is upsetting the team dynamic. Usually these occur from lack of communication, or improper scheduling and tasking, and often dealing with it after the event is better than during. Just try communicating with that person to find any cause and notify the team if anything changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How can one avoid being the team nanny?&lt;/strong&gt;&lt;br&gt;
This might vary from person to person so do your best to be a team-leader you would like to have leading you. In a jam there isn’t much time to babysit the other team members. Go in blindly trusting that people will do what they say but also monitor if someone might be over promising. I think the key part here is remembering this is all for fun. If the project doesn’t come together as expected, it can still be a fun experience for everyone so try not to ruin it by pointing fingers and blaming others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Would you deliberately take a team role to build skills?&lt;/strong&gt;&lt;br&gt;
Absolutely, although it is intimidating as you go in knowing this is a weak point. I have done it a few times, and seen others as well. There is always a lot to learn by doing so. However when using a team event to build skills you should be very clear with the team. It is important they have the correct expectations going in. Share a taste of your current art, or music skills and then do your best. I have found skill building in a team event has added more pressure and this can result in frustration when skills can’t match a vision. As long as expectations are set this shouldn’t be a problem for anyone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to handle errors or mistakes from other team members?&lt;/strong&gt;&lt;br&gt;
This depends a bit on the situation and how big the mistake might be. If you have a lot more experience than the other team member it might make sense to mention the mistake and offer ‘better’ methods. In general it is best to let others have their freedom to do their own thing, which includes making minor mistakes. Of course if they are asking for it, then give them help!&lt;/p&gt;

&lt;p&gt;After an event you could reflect with the team, or specific developer to offer advice that might help in future projects. Just don’t be pushy as there are many ways to achieve the same things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is the communication overhead to coordinate with multiple people worth it for a game jam?&lt;/strong&gt;&lt;br&gt;
Perhaps depends greatly on you, your wants and the team in question. In all my experiences with team events most of the communication occurred before the game jam. Everyone knew their roles, and the general structure of the weekend, including methods of communication. The start of the event when the theme is announced has the highest communication load as the team collaborates to find the game idea.&lt;/p&gt;

&lt;p&gt;After the idea is found, typically communication overhead is “I finished X” and “I got X into the game.” I have always used source control for code and assets during a jam which makes grabbing and sharing things easy, I also ‘deployed’ team builds for testing this way. In rare cases I have accepted things through email or other means to manually integrate into the game.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Playing Games to Build GameDev Skills</title>
      <dc:creator>🏎️Tim Beaudet🚀</dc:creator>
      <pubDate>Mon, 16 Mar 2020 11:15:40 +0000</pubDate>
      <link>https://forem.com/timbeaudet/playing-games-to-build-gamedev-skills-9pi</link>
      <guid>https://forem.com/timbeaudet/playing-games-to-build-gamedev-skills-9pi</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/_NSku3zi7v0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Publisher Denied My Game Because of Custom C++ Engine</title>
      <dc:creator>🏎️Tim Beaudet🚀</dc:creator>
      <pubDate>Tue, 26 Nov 2019 12:22:33 +0000</pubDate>
      <link>https://forem.com/timbeaudet/publisher-denied-my-game-because-of-custom-c-engine-5g4h</link>
      <guid>https://forem.com/timbeaudet/publisher-denied-my-game-because-of-custom-c-engine-5g4h</guid>
      <description>&lt;p&gt;If you intend to sell and make money by making games, you know that writing your own engine will take a lot of time. However you may not be aware that writing your own technologies can also cost opportunities and partnerships. You will need to keep that in mind as well. This is my story on how I learned that lesson the hard way:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;I went into the publisher search just checking out what opportunities may exist as my&lt;/em&gt; &lt;a href="https://www.twitch.tv/timbeaudet"&gt;&lt;em&gt;game development stream&lt;/em&gt;&lt;/a&gt; &lt;em&gt;viewers were pushing me to try.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pitch
&lt;/h2&gt;

&lt;p&gt;In September 2019 I prepared Turbo Boom! to be pitched to several publishers. After spending many days polishing and tweaking that content, I sent 25-30 emails. The publishers that received this email were chosen based on their interest in racing games, or action based games that are similar enough to Turbo Boom! Throughout October the responses came back, most of which included, “unfortunately not a fit at this time” along with enough information to show they took my pitch seriously.&lt;/p&gt;

&lt;p&gt;One publisher even asked more questions about targeting mobile platforms after initial desktop launch. I knew discussing how my custom C++ engine did not support mobile at this moment would be a ding. So I let the publisher know that mobile wasn’t supported and included a realistic estimation of how long it would take to add that support. I was very confident in this estimate as my engine has been partially working on iOS for some time.&lt;/p&gt;

&lt;p&gt;They took that answer well enough, and went to review it with the rest of their team for a week or two. Unfortunately the next response was them letting off the hook with a not so subtle hint to the reason being my custom engine and the risk it added.&lt;/p&gt;

&lt;h2&gt;
  
  
  It makes sense.
&lt;/h2&gt;

&lt;p&gt;A custom engine has a lot more unknowns, especially to publishers who are not typically developers. Based on the response had a major engine (Unity, Unreal) been used, “that just works” in the eyes of non-developers, my game may have had a publisher. But that is okay, I like doing things my way. It is just a lesson learned that the custom engine can also cost opportunities based on the perceived, &lt;em&gt;and actual,&lt;/em&gt; additional risk that is increased with custom technologies.&lt;/p&gt;

&lt;p&gt;As an indie developer taking a look at things from a business perspective is important and I already knew custom engine development was time consuming, costly and adding risk. It wasn’t until this response that I became aware that risk extends to opportunities and partnerships. Others pursuing similar paths should be aware of this.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>cpp</category>
      <category>todayilearned</category>
      <category>career</category>
    </item>
    <item>
      <title>The Discord Bot That Nearly Killed Me (Created in  C++)</title>
      <dc:creator>🏎️Tim Beaudet🚀</dc:creator>
      <pubDate>Mon, 18 Nov 2019 12:52:41 +0000</pubDate>
      <link>https://forem.com/timbeaudet/the-discord-bot-that-nearly-killed-me-created-in-c-gb5</link>
      <guid>https://forem.com/timbeaudet/the-discord-bot-that-nearly-killed-me-created-in-c-gb5</guid>
      <description>&lt;h2&gt;
  
  
  Project Overview
&lt;/h2&gt;

&lt;p&gt;If you are considering writing a bot yourself, or enjoy reading the adventures of other developers, then this article will serve as a list of pitfalls and how to avoid them, or the quest I took on this adventure. This is a long one as I faced many challenges, so go grab that coffee or popcorn and learn something along the way.&lt;/p&gt;

&lt;p&gt;This adventure was taken in C++. While other languages and frameworks would have made the project &lt;em&gt;significantly easier&lt;/em&gt;, C++ was chosen for code reuse from a twitch bot I use for &lt;a href="https://www.twitch.tv/timbeaudet"&gt;my programming livestream&lt;/a&gt;, it is my comfort language and I want to use websockets in other C++ projects. The last reason being the primary driving force.&lt;/p&gt;

&lt;p&gt;The objective of the project was to create a Discord bot to run on my in-house server box 24/7. The server box runs Linux and at the start of the project I was running Ubuntu on my development machine for an experiment of &lt;a href="https://dev.to/timbeaudet/31-days-of-game-development-on-linux-3bo1"&gt;gamedev on Linux&lt;/a&gt;. The project started with a search for websocket frameworks;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/zaphoyd/websocketpp"&gt;https://github.com/zaphoyd/websocketpp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mattgodbolt/seasocks"&gt;https://github.com/mattgodbolt/seasocks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/uNetworking/uWebSockets"&gt;https://github.com/uNetworking/uWebSockets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;And more: &lt;a href="https://github.com/facundofarias/awesome-websockets"&gt;https://github.com/facundofarias/awesome-websockets&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I did not want to use boost. While I like the concept I have nightmares about it from other projects. In fact I very much dislike dependency management in C++ but still sometimes easier than writing a custom implementation. So I dug into seasocks, got it built, linking and started using it before realizing… seasocks is specifically a websocket server and does not have client capabilities. Wasted effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Challenge, Quitting and a Minor Victory
&lt;/h2&gt;

&lt;p&gt;The first 6 hours were spent jumping between various frameworks and writing a custom implementation. Then I quit the project. Yes, I quit the project after 6 hours deeming it not worth the hassle and effort. A couple day break and the project was reawakened with the intent to write the implementation myself, and power on through. I get knocked down, but I get back up again.&lt;/p&gt;

&lt;p&gt;Secure web-sockets were required to connect to Discord although not required for my future websocket needs. The next several hours of the project were spent dealing with this. First attempting to use OpenSSL, and what a fiasco that was. With much help from twitch chat, I jumped over to LibreSSL and in a few more hours I finally had a connection with Discord. The first baby step. The connection died after a few seconds (no heartbeats sent), but successful upgrade from https:// to wss://.&lt;/p&gt;

&lt;p&gt;I already have TCP and UDP socket implementations for my game development projects. I desired using WebSockets through those socket implementations for future needs. The challenge was getting LibreSSL to use those sockets, though this one was rather easy. Swapping &lt;code&gt;tls_connect_socket()&lt;/code&gt; with &lt;code&gt;tls_connect_cbs()&lt;/code&gt; allowing callbacks to be used for reading and writing to a custom socket implementation. After a bit of cleanup from all the prototyping I was now feeling pretty solid after two victories.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing WebSocket Protocol
&lt;/h2&gt;

&lt;p&gt;This started out &lt;em&gt;way worse&lt;/em&gt; than expected, &lt;a href="https://tools.ietf.org/html/rfc6455"&gt;rfc6455&lt;/a&gt; was a bit scary at first. As stated the https to wss had been implemented in some form to get TLS working with LibreSSL. But to send or receive data over a websocket, special frames are used which contains a header that can be somewhere between 2 and 14 bytes depending on the payload length and masking. This was a perfect place to use a C++ bitfield. Optionally manual bitwise operations could meet the needs, but bitfields are cleaner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct FrameHeader
{
    std::uint8_t mOpCode : 4;
    std::uint8_t mReserved : 3;
    std::uint8_t mFinished : 1;
    std::uint8_t mLength : 7;
    std::uint8_t mMask : 1;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I admit the image in &lt;a href="https://tools.ietf.org/html/rfc6455#page-28"&gt;rfc6455#page-28&lt;/a&gt; describing the frame did throw me for a loop and my first instinct flipped the most and least significant bits of each byte. This was pretty easy to discover and fix. Each frame will have at least two bytes, and after reading those bytes in they could be casted into the header to extract information. The actual payload length can be stored within those 7 bits, an extra 2 bytes or 8 bytes that follow the first two when length (in FrameHeader) is 126 or 127. Note to pay attention to the endianness of those larger byte sizes when sending across the network which expects big-endian to go across the wire, most significant bytes first.&lt;/p&gt;

&lt;p&gt;An additional 4 bytes are added to describe the mask when the mask bit is on. Apparently this is prevent packets getting cached by looking similar to http. Though this made little sense to me I pressed on with help from viewers and playing with the XOR operator to mask the payload. A websocket client is expected to set the mask bit to on and xor each byte of the payload with those of the mask. The mask is randomly selected for each frame of data. &lt;strong&gt;Note, this doesn’t add security&lt;/strong&gt;; as anyone can see the mask and unmask the data, it just makes two frames that would otherwise be identical, become different.&lt;/p&gt;

&lt;p&gt;At this point data was received from Discord in the WebSocket frames and able to be parsed through json. Upon connection Discord sends a &lt;code&gt;HELLO&lt;/code&gt; message through the gateway which tells the bot how often the &lt;code&gt;HEARTBEAT&lt;/code&gt; message should be sent to keep the connection alive. Part of the heartbeat was to contain the last given sequence number from Discord, fairly straight forward, and at this point the connection could live on - but do nothing otherwise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Becoming a Detective
&lt;/h2&gt;

&lt;p&gt;After receiving a &lt;code&gt;HELLO&lt;/code&gt; the bot is expected to send an &lt;code&gt;IDENTIFY&lt;/code&gt; message which contains the bots token and returns a &lt;code&gt;READY&lt;/code&gt; message on success. At that point the bot is connected… Or it should have been. After sending the &lt;code&gt;IDENTIFY&lt;/code&gt; message my bot would immediately disconnect once a &lt;code&gt;HEARTBEAT&lt;/code&gt; message was sent, or never received the &lt;code&gt;READY&lt;/code&gt; message before disconnect by timeout if &lt;code&gt;HEARTBEAT&lt;/code&gt; was never sent.&lt;/p&gt;

&lt;p&gt;There were many hours of digging into this issue. A debug tool for logging hexdumps was added to my debug framework as well. Not entirely sure how I lived this long without that tool, but it will definitely save me in the future. With the hexdumps I was able to start comparing what was getting sent to expectations. I also wrote a small ‘test’ of sorts that created a websocket frame and parsed it to ensure everything worked.&lt;/p&gt;

&lt;p&gt;By far the hardest case to solve was that of the disappearing bug. At first it started with a few random failures and &lt;em&gt;“that was weird”&lt;/em&gt;, but no obvious suspect found. The investigation continued and multiple suspects questioned. Undefined behavior was discovered when the bot was ran several times, without recompiling, with different results for a simple test frame with the string &lt;code&gt;“INDIE”&lt;/code&gt;being unmasked correctly as &lt;code&gt;“INDIE”&lt;/code&gt; or as &lt;code&gt;“INDGD”&lt;/code&gt;. In digging deeper into the handling of the payload a rookie mistake was discovered; referencing of data within a &lt;code&gt;std::vector&lt;/code&gt;, while calling &lt;code&gt;push_back()&lt;/code&gt;. Solutions were simple, either reserve the size required or not hold the reference.&lt;/p&gt;

&lt;p&gt;When everything was looking good with the test code, Discord still failed to respond to &lt;code&gt;IDENTIFY&lt;/code&gt; with a &lt;code&gt;READY&lt;/code&gt;. A significant investigation revealed the &lt;code&gt;IDENTIFY&lt;/code&gt; message was larger than 125 bytes while heartbeats and tests were smaller. This lead to the discovery that endianness was ignored. I take the simplest approach first and in previous experiences endianness is often mentioned but in practice always seemed to work without messing around. Not this time.&lt;/p&gt;

&lt;p&gt;The solution was quite easy. Just flip the order the bytes are sent or received to the way they are stored in memory. So if the uint16 length was 0x1234, and stored in memory (low-endian) as 0x34, 0x12 then sending over the wire they need to be sent (big-endian) 0x12, 0x34. The same process applies for the uint64, there are simply more bytes to swap around. Finally the &lt;code&gt;READY&lt;/code&gt; message arrived.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending a Chat Message
&lt;/h2&gt;

&lt;p&gt;After receiving the READY message other messages came in as well, MessageCreate being the interesting thing to dig into. It was very easy to parse the json object to receive the contents of the message and add a very simple &lt;code&gt;if (message == “!time”) { Respond(“time is…”); }&lt;/code&gt; well, that was where simplicity ended. Implementing Respond() took a lot of digging into Discord documentation before figuring out that, apparently, sending a message requires the http api and cannot be done through the websocket connection.&lt;/p&gt;

&lt;p&gt;I don’t know and cannot speculate why responding to a message is done through an entire different connection when a perfectly good connection already exists, but, I am sure there are reasons. Sending an http post was not too hard since I already had a wrapper around libcurl to do just this, with the exception that my wrapper didn’t send data, only post parameters, headers and url. It was quick work to find and implement a way to post data with CURLOPT_POSTFIELDS. However, I am cursed.&lt;/p&gt;

&lt;p&gt;With postfields you need to give a pointer to data and the size of the data in another option. Unless using CURLOPT_COPYPOSTFIELDS the data needs to be managed on your end. This was all effortless. But it did not work. Discord sent back &lt;code&gt;{"message": "Cannot send an empty message","code": 50006}&lt;/code&gt;. Debug output from curl showed the entire contents of my post data was sent successfully, so how was the message empty? I checked the json, and everything about 400 times. Even used curl through command-line with &lt;code&gt;--libcurl file.c&lt;/code&gt; switch to compare the generated code with mine.&lt;/p&gt;

&lt;p&gt;After a lot of attempts I removed the null-terminator that I naively copied into the data given to postfields. This was the problem. As a game-developer I am not as versed in the internet or http protocol exactly, but sending a null-terminator byte is evidently extremely bad and Discord throws the contents away. I guess this is in defense of a Null Byte Poisoning attack where the server will sanitize content to the null-byte but potententially process unsanitized content after.&lt;/p&gt;

&lt;p&gt;Finally I smashed through the last wall victorious. The bot responded to the &lt;code&gt;!time&lt;/code&gt; command with my local time. A significant amount of code cleanup and refactoring occurred so the project could be maintained into the future and more commands added. There are many plans to enhance my discord server and live-streaming overlay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;The takeaway is that programming is often about persistence. Digging through concrete walls with a plastic spoon. I nearly quit this project at the start, but instead I got back up and powered through. By jumping over, crushing through and going around multiple walls, I managed to get my discord bot working. It makes the project much more rewarding. For more of my projects checkout my &lt;a href="https://www.twitch.tv/timbeaudet"&gt;development stream on twitch.tv/timbeaudet&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>31 Days of Game Development on Linux</title>
      <dc:creator>🏎️Tim Beaudet🚀</dc:creator>
      <pubDate>Mon, 11 Nov 2019 12:25:19 +0000</pubDate>
      <link>https://forem.com/timbeaudet/31-days-of-game-development-on-linux-3bo1</link>
      <guid>https://forem.com/timbeaudet/31-days-of-game-development-on-linux-3bo1</guid>
      <description>&lt;p&gt;During the month of October some of the &lt;a href="https://www.twitch.tv/team/livecoders"&gt;Live Coders Team on Twitch&lt;/a&gt; were challenging themselves to use Linux. As a team-member myself I joined in and used Ubuntu 18.04.3. Ultimately setup went smoother than expected. There were some minor hiccups, but then again there always are. Setup of my 6-monitors in the display settings panel tested my patience, especially after doing it a second and third time when it did not save during restarts.&lt;/p&gt;

&lt;p&gt;Although a large component of using Linux is for customizations, I did not spend my efforts customizing things endlessly and instead used Ubuntu as-is out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Development Experience
&lt;/h2&gt;

&lt;p&gt;I have used Ubuntu previously and already had a build system in place using premake5 to generate make files and such for my custom C++ framework. Setting up Visual Studio Code to run the project was easy enough however it was not nearly as smooth as desired, and I had some issues with full intellisense abilities. Perhaps required more setup than performed; though I tried several times to set the include directory in attempting to make it work.&lt;/p&gt;

&lt;p&gt;It was more of a process than desired to test changes as it required manually saving each file, opening/switching to the terminal window (in or out of VSCode) to run a command. Pressing the play button or F5 in VSCode to run with debugger... and when finished the terminal window needs to hide for code visibility. While that isn't a deal-breaker, Visual Studio does all of this with F5, and auto hides on return to code.&lt;/p&gt;

&lt;p&gt;This was not world-ending, but was a little more frustrating. Perhaps spending more time with setup would have reduced some overhead as I know there are launch tasks. VSCode is not Visual Studio and never will be; some tools are lacking or missing entirely. Extensions help this significantly and other command-line tools may technically fill the gaps, however that is just not as friendly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Liked
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Using apt-get to install software is AWESOME.&lt;/li&gt;
&lt;li&gt;wget downloading via command-line in place is GREAT.&lt;/li&gt;
&lt;li&gt;Much easier to grab and install developer dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A viewer of my &lt;a href="https://twitch.tv/timbeaudet"&gt;game development stream&lt;/a&gt; shared a game for me to try, and had to share a few more files. It was amazing to use a terminal window navigate and just run &lt;code&gt;wget url&lt;/code&gt; to grab those files without opening the browser, save-to prompts and manually moving from &lt;code&gt;/Downloads/&lt;/code&gt;. Also installing software is way more awesome, when it exists in repositories. Instead of searching "audacity" to find and navigate to "audacityteam.org" then finding the download button and yada-yada, just type in terminal &lt;code&gt;apt-get install audacity&lt;/code&gt; and BAM all done. That simple. However Audacity may be a bad example because after installed, it didn't get mic input correctly and I actually failed to get it working at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Streaming Experience
&lt;/h2&gt;

&lt;p&gt;Live streaming was surprisingly easy on Linux, the setup did not take long after downloading OBS as I started with settings from streaming on Windows. The monitor setup/reset issue did cause some more overhead at the start of some streams, and the camera sometimes needed help to sync picture with audio from mic. Also there were a few things I did miss from Windows, namely Auto Hot Key which has scripts for typing out some links and handy messages. However overall the streaming went without issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practicality Linux vs Windows
&lt;/h2&gt;

&lt;p&gt;While development went smoothly on Linux and dealing with external libraries is, &lt;em&gt;in general&lt;/em&gt;, easier - I would argue heavily that Windows is more practical. If only for the reason that 96% of PC gamers are on Windows, based on &lt;a href="https://store.steampowered.com/hwsurvey/Steam-Hardware-Software-Survey-Welcome-to-Steam"&gt;Steam Survey&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Visual Studio also has a sharper edge with debugging tools. This is a potential bias but I honestly believe the tools being built in and easily accessible is a real advantage.&lt;/p&gt;

&lt;p&gt;Linux shines for grabbing dependencies, it is far more practicial in this manner which can increase the rate of development when you target only Linux. This may be shifting slightly as vcpkg is a thing and as it grows perhaps dependency problems will start to become less of a headache.&lt;/p&gt;

&lt;h2&gt;
  
  
  Daily Development Streams
&lt;/h2&gt;

&lt;p&gt;Checkout my &lt;a href="https://twitch.tv/timbeaudet"&gt;game development stream&lt;/a&gt; to watch my indie adventure, I stream daily 6am-9am ET.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>linux</category>
      <category>ubuntu</category>
    </item>
  </channel>
</rss>
