<?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>DEV Community: Trent Best</title>
    <description>The latest articles on DEV Community by Trent Best (@trent_best_ca8617e4911baf).</description>
    <link>https://dev.to/trent_best_ca8617e4911baf</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%2F3482664%2F90efa0f5-3882-4e17-8765-c58e8ce36a7b.jpg</url>
      <title>DEV Community: Trent Best</title>
      <link>https://dev.to/trent_best_ca8617e4911baf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/trent_best_ca8617e4911baf"/>
    <language>en</language>
    <item>
      <title>FSM_API: The Pure C# Core That Decouples Your Logic from Any Engine</title>
      <dc:creator>Trent Best</dc:creator>
      <pubDate>Thu, 09 Oct 2025 20:31:42 +0000</pubDate>
      <link>https://dev.to/trent_best_ca8617e4911baf/fsmapi-the-pure-c-core-that-decouples-your-logic-from-any-engine-1d0j</link>
      <guid>https://dev.to/trent_best_ca8617e4911baf/fsmapi-the-pure-c-core-that-decouples-your-logic-from-any-engine-1d0j</guid>
      <description>&lt;p&gt;We recently announced our pivot at The Singularity Workshop: shifting focus from building a custom ECS engine to perfecting the &lt;strong&gt;FSM_API (Finite State Machine Application Programming Interface)&lt;/strong&gt;. This move ensures a stronger, more maintainable foundation for &lt;strong&gt;MyVR&lt;/strong&gt; and offers immediate, open-source value to every C# developer.&lt;/p&gt;

&lt;p&gt;The FSM_API is the blazing-fast core of this vision. It is built to be completely &lt;strong&gt;engine-agnostic&lt;/strong&gt;, allowing you to define complex, reliable behavior in pure C# and deploy it anywhere—from backend services and robotics to Unity or other game engines.&lt;/p&gt;

&lt;p&gt;Here's how FSM_API provides the decoupling and power every developer needs in their toolkit:&lt;/p&gt;




&lt;h3&gt;
  
  
  🧠 1. Decoupling Logic: The IStateContext Contract
&lt;/h3&gt;

&lt;p&gt;The biggest challenge in state management is coupling logic (the &lt;em&gt;how&lt;/em&gt;) to data (the &lt;em&gt;what&lt;/em&gt;). FSM_API solves this by requiring every managed entity to implement the simple &lt;strong&gt;&lt;code&gt;IStateContext&lt;/code&gt;&lt;/strong&gt; interface.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FSM Logic is Abstract:&lt;/strong&gt; The FSM Definition (your blueprint) contains the states and transitions, but it knows nothing about "player health" or "door position". It only understands abstract actions like &lt;code&gt;onEnter&lt;/code&gt;, &lt;code&gt;onUpdate&lt;/code&gt;, and &lt;code&gt;onExit&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your Data is the Context:&lt;/strong&gt; Your custom C# class (e.g., &lt;code&gt;PlayerContext&lt;/code&gt; or &lt;code&gt;LightSwitch&lt;/code&gt;) implements &lt;code&gt;IStateContext&lt;/code&gt;. This object holds all the data and physical methods (like &lt;code&gt;PlayAnimation()&lt;/code&gt; or &lt;code&gt;TakeDamage()&lt;/code&gt;) that the FSM's actions will call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Self-Cleaning System:&lt;/strong&gt; The &lt;code&gt;IStateContext&lt;/code&gt; includes a crucial &lt;strong&gt;&lt;code&gt;IsValid&lt;/code&gt;&lt;/strong&gt; property. If your object is destroyed or no longer relevant, setting &lt;code&gt;IsValid&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; automatically tells the FSM_API to unregister and clean up the associated FSM instance, preventing memory leaks and errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  This clear separation ensures your logic is reusable, and the system manages its own lifecycle. 
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ⚙️ 2. Engine Agnosticism: Deployment Anywhere
&lt;/h3&gt;

&lt;p&gt;Because the core FSM logic doesn't touch Unity's &lt;code&gt;MonoBehaviour&lt;/code&gt; or any other engine code, FSM_API is instantly compatible with any C# environment.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pure C# Ready:&lt;/strong&gt; You can define a complex AI system using the fluent &lt;strong&gt;&lt;code&gt;FSMBuilder&lt;/code&gt;&lt;/strong&gt; and run it in a simple console application, a backend server, or a robotics controller.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Explicit Control with Processing Groups:&lt;/strong&gt; In environments without a built-in game loop (like a console app or backend service), you gain &lt;strong&gt;explicit control&lt;/strong&gt; over the update cycle using &lt;strong&gt;Processing Groups&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; You create a logical group (e.g., &lt;code&gt;"AI_Logic"&lt;/code&gt; or &lt;code&gt;"Network_Processor"&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; You assign FSM instances to that group.&lt;/li&gt;
&lt;li&gt; You manually call &lt;code&gt;FSM_API.Interaction.Update("GroupName")&lt;/code&gt; exactly when you want the FSMs to tick.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  This level of control is essential for server-side logic and custom engine environments where performance demands are high. 
&lt;/h2&gt;

&lt;h3&gt;
  
  
  💡 3. Dynamic Power: Runtime Modification
&lt;/h3&gt;

&lt;p&gt;Most FSM solutions are static: once defined, they can't change. FSM_API's &lt;strong&gt;&lt;code&gt;FSMModifier&lt;/code&gt;&lt;/strong&gt; shatters this limitation, enabling the &lt;strong&gt;runtime recomposition&lt;/strong&gt; that powers our innovative AnyApp vision.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;FSMModifier&lt;/code&gt; allows you to change the FSM blueprint (&lt;em&gt;the definition&lt;/em&gt;) after it has been built, even while instances are actively running from it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Adaptive AI:&lt;/strong&gt; Dynamically add a new "Enraged" state or modify the transition condition for "Flee" after a major in-game event.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic UI/Content:&lt;/strong&gt; Add or remove navigation paths based on user unlocks or content downloads without requiring a full recompile or app restart.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live Hot-Reloading:&lt;/strong&gt; During development, modify FSM logic and apply the changes immediately in a running build for rapid iteration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  This is the key to creating applications that can genuinely adapt and change on the fly, transforming static software into fluid, composable experiences. 
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🚀 Get Started with the Free Core
&lt;/h3&gt;

&lt;p&gt;The FSM_API is designed to be the fastest, most flexible, and most robust solution available for C# developers.&lt;/p&gt;

&lt;p&gt;The core DLL is open-source and free, available now on NuGet. Get started today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NuGet Package:&lt;/strong&gt; &lt;a href="https://github.com/TrentBest/FSM_API" rel="noopener noreferrer"&gt;TheSingularityWorkshop.FSM_API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find out more&lt;/strong&gt; about our full roadmap (MyVR, AnyApp, and the FSM_Layer Asset Store packages) on our &lt;a href="https://www.patreon.com/c/TheSingularityWorkshop" rel="noopener noreferrer"&gt;Patreon page&lt;/a&gt;.&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%2Fkhh2zalnahg528dci5zo.jpg" 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%2Fkhh2zalnahg528dci5zo.jpg" alt="The Singularity Workshop Logo - A digital eyeball within a computer environment showing wires and circuits" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>api</category>
      <category>designpatterns</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Stop Getting Blocked: How a Simple Design Pattern Unlocks Your Project's Complex Logic</title>
      <dc:creator>Trent Best</dc:creator>
      <pubDate>Fri, 26 Sep 2025 23:57:31 +0000</pubDate>
      <link>https://dev.to/trent_best_ca8617e4911baf/stop-getting-blocked-how-a-simple-design-pattern-unlocks-your-projects-complex-logic-1420</link>
      <guid>https://dev.to/trent_best_ca8617e4911baf/stop-getting-blocked-how-a-simple-design-pattern-unlocks-your-projects-complex-logic-1420</guid>
      <description>&lt;p&gt;Have you ever started a project—a simple game, a complex UI, or any interactive system—only to feel completely overwhelmed by the chaos of your main logic loop? You add an &lt;code&gt;if&lt;/code&gt; statement for one behavior, and it breaks another. You try to fix it, and it breaks three more. Sound familiar?&lt;/p&gt;

&lt;p&gt;You're not alone. This is the moment when many new developers get &lt;strong&gt;blocked&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But what if I told you there's a simple, powerful structure you can &lt;em&gt;design&lt;/em&gt; before you even write the code? This design acts as a scaffold, letting you build complex, reliable behavior piece by piece.&lt;/p&gt;

&lt;p&gt;That structure is called the &lt;strong&gt;Finite State Machine (FSM)&lt;/strong&gt;, and we're going to break down a demo to show you how it works and how it can unblock your next project.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Power of a Structured Design: FSMs
&lt;/h2&gt;

&lt;p&gt;In its simplest form, a Finite State Machine is a way to model anything that behaves differently based on its current status. Every piece of logic is isolated into a &lt;strong&gt;State&lt;/strong&gt;, and you define strict &lt;strong&gt;Transitions&lt;/strong&gt; (rules) for moving between them.&lt;/p&gt;

&lt;p&gt;This learned structure is the key to escaping the "spaghetti code" trap:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Define Intent:&lt;/strong&gt; Draw a diagram of what you want to happen.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Implement Isolation:&lt;/strong&gt; Write the code for each State and Transition in isolation.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Know It Works:&lt;/strong&gt; Since the FSM framework manages the flow, you know the overall logic will function as designed—you just have to fill in the behavior for each small piece.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's see this in action using the &lt;strong&gt;Quick Brown Fox&lt;/strong&gt; demo.&lt;/p&gt;




&lt;h2&gt;
  
  
  Case Study: The Quick Brown Fox Demo
&lt;/h2&gt;

&lt;p&gt;Our simulation is based on the classic phrase, "The quick brown fox jumps over the lazy sleeping dog". We have two agents, and we use FSMs to define their entire behavioral logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Simulation Setup (&lt;code&gt;SimpleDemoContext.cs&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;This is the central application, which manages the world and the agents.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Fox&lt;/strong&gt; starts at &lt;code&gt;Position 0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Dog&lt;/strong&gt; starts at &lt;code&gt;Position 3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The goal is for the Fox to reach the &lt;code&gt;WinPosition&lt;/code&gt; of &lt;code&gt;10&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every frame, the simulation context performs three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Clear vision and collision data for all agents.&lt;/li&gt;
&lt;li&gt; Perform &lt;strong&gt;Vision&lt;/strong&gt; and &lt;strong&gt;Collision&lt;/strong&gt; checks between agents (our world rules).&lt;/li&gt;
&lt;li&gt; Calls &lt;code&gt;FSM_API.Interaction.Update("Update")&lt;/code&gt; to tell every agent's FSM to run its logic for the current frame.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2. Modeling the Fox: The &lt;code&gt;QuickBrownFoxFSM&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The Fox's FSM is a perfect example of how a simple diagram can define complex behavior. The fox primarily &lt;strong&gt;Walks&lt;/strong&gt;, &lt;strong&gt;Jumps&lt;/strong&gt; over obstacles (the dog), or &lt;strong&gt;Flees&lt;/strong&gt; if it collides.&lt;/p&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%2F5l01ummuz6vyxqgc90v9.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%2F5l01ummuz6vyxqgc90v9.png" alt="Finite State Machine showing how the fox behaves:  Walking, jumping, fleeing, and Mangled (which is driven by the dog) with the transitions: ShouldJump, ShouldFlee, and ShouldLand" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a summary of the Fox's logic:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;th&gt;Transition Condition&lt;/th&gt;
&lt;th&gt;Action (OnUpdate)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Walking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;ShouldJump&lt;/em&gt;: A visible agent is within 2 units. &lt;em&gt;ShouldFlee&lt;/em&gt;: Collision with a dog.&lt;/td&gt;
&lt;td&gt;Increments position by 1 (Speed).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Jumping&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;em&gt;ShouldLand&lt;/em&gt;: Position is greater than or equal to &lt;code&gt;JumpEnd&lt;/code&gt; (2 steps after jumping started).&lt;/td&gt;
&lt;td&gt;Increments position by 1.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fleeing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;None (Terminal state).&lt;/td&gt;
&lt;td&gt;Increments position by 2 (Speed).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mangled&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;None (Terminal state).&lt;/td&gt;
&lt;td&gt;Outputs current status.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notice how clean the logic is for a State like &lt;strong&gt;Walking&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnUpdateWalking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IStateContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;QuickBrownFox&lt;/span&gt; &lt;span class="n"&gt;fox&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Simple: Just move forward by its speed&lt;/span&gt;
        &lt;span class="n"&gt;fox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Position&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;fox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Speed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is walking:  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Position&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Its complexity comes from the &lt;strong&gt;Transitions&lt;/strong&gt;—the rules that change the state. The Fox will only switch from &lt;code&gt;Walking&lt;/code&gt; to &lt;code&gt;Jumping&lt;/code&gt; if the condition in &lt;code&gt;ShouldJump&lt;/code&gt; is met:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;ShouldJump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IStateContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;QuickBrownFox&lt;/span&gt; &lt;span class="n"&gt;fox&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Transition rule: Look at all visible agents (provided by SimpleDemoContext)&lt;/span&gt;
        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VisibleAgents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Position&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;fox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Position&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// If the visible agent is too close (within 2 units)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Fox isn't doing collision logic; the main simulation is. The Fox is only checking its readily available &lt;code&gt;VisibleAgents&lt;/code&gt; list, keeping its own code extremely focused!&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Interacting Agents: The &lt;code&gt;LazyDogFSM&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The Dog's behavior is even simpler. It starts &lt;strong&gt;Sleeping&lt;/strong&gt; until an external force (a collision) wakes it up.&lt;/p&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%2Frwbhiow7jy84h016f35a.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%2Frwbhiow7jy84h016f35a.png" alt="Finite State Machine for the Dog showing it's states: Sleeping, Awake, Chasing, Mangling and it's Transitions:  IsAwake, ShouldChase, and IsMangling" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sleeping&lt;/strong&gt; to &lt;strong&gt;Awake&lt;/strong&gt;: The transition condition &lt;code&gt;IsAwake&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt; if a collision has occurred.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Awake&lt;/strong&gt; to &lt;strong&gt;Chasing&lt;/strong&gt;: The dog sees the fox (&lt;code&gt;ShouldChase&lt;/code&gt; is true) and begins to chase at speed 3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chasing&lt;/strong&gt; to &lt;strong&gt;Mangling&lt;/strong&gt;: Collision with the Fox occurs again (&lt;code&gt;IsMangling&lt;/code&gt; is true).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The true power is seen in the &lt;strong&gt;Mangling&lt;/strong&gt; state, which demonstrates &lt;strong&gt;Inter-FSM Communication&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnEnterMangling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IStateContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;LazySleepingDog&lt;/span&gt; &lt;span class="n"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; has started Mangling the fox!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// The dog reaches into the Fox's FSM and forces a state change!&lt;/span&gt;
        &lt;span class="n"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CollidedAgents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;()?.&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TransitionTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Mangled"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Dog doesn't need to know &lt;em&gt;how&lt;/em&gt; the Fox gets mangled, only that it &lt;em&gt;can&lt;/em&gt; force the Fox's FSM to the terminal &lt;code&gt;Mangled&lt;/code&gt; state. This isolation keeps the Dog's code simple, too.&lt;/p&gt;




&lt;h2&gt;
  
  
  Your Takeaway: Design Before You Code
&lt;/h2&gt;

&lt;p&gt;This simple example proves the structure works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No monolithic &lt;code&gt;if/else&lt;/code&gt; block&lt;/strong&gt; is needed in one huge update function.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design First:&lt;/strong&gt; You can draft the FSM diagram first and use it as a blueprint for development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Focus:&lt;/strong&gt; You only need to think about what happens &lt;em&gt;in that specific state&lt;/em&gt; and what rules trigger a &lt;em&gt;specific transition&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach is your new scaffolding tool. It lets you design robust, complex applications without getting blocked by logic that breaks down the line. You know what needs to be implemented because you've already defined it on your diagram!&lt;/p&gt;

&lt;h2&gt;
  
  
  Get the FSM_API
&lt;/h2&gt;

&lt;p&gt;You can access and support the FSM_API at the following links:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/trentbest/fsm_api" rel="noopener noreferrer"&gt;GitHub Repository:  https://github.com/trentbest/fsm_api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API/" rel="noopener noreferrer"&gt;NuGet Package:  https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.paypal.com/paypalme/TheSingularityWorkshop" rel="noopener noreferrer"&gt;&lt;strong&gt;💖 Support Us&lt;/strong&gt;:  https://www.paypal.com/paypalme/TheSingularityWorkshop&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Singularity Workshop
&lt;/h2&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%2Fgbk0q9wxm34iykf9b97h.webp" 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%2Fgbk0q9wxm34iykf9b97h.webp" alt="The singularity Workshop - a vortex of energy forming an eye with an internal computer background with circuitry" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>fsm</category>
      <category>gamedev</category>
      <category>designpatterns</category>
      <category>csharp</category>
    </item>
    <item>
      <title>A FSM Challenge for the c#/DotNet Dev Community</title>
      <dc:creator>Trent Best</dc:creator>
      <pubDate>Fri, 19 Sep 2025 22:49:59 +0000</pubDate>
      <link>https://dev.to/trent_best_ca8617e4911baf/a-fsm-challenge-for-the-cdotnet-dev-community-2c9k</link>
      <guid>https://dev.to/trent_best_ca8617e4911baf/a-fsm-challenge-for-the-cdotnet-dev-community-2c9k</guid>
      <description>&lt;p&gt;Hey everyone! 👋&lt;/p&gt;

&lt;p&gt;I'm excited to share a fun challenge with you. For those looking to learn something new, test their skills, or just have some fun, I've created something I think you'll enjoy.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Introducing FSM_API&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I've made my free, open-source &lt;strong&gt;FSM_API&lt;/strong&gt; NuGet package public. It's a platform-agnostic C# library, meaning you can integrate its behavior into almost any C# application. If you've ever wanted to explore the power of &lt;strong&gt;Finite State Machines (FSMs)&lt;/strong&gt;, this is a great opportunity.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What is a Finite State Machine?&lt;/strong&gt;&lt;br&gt;
A finite state machine is a mathematical model of computation. It is an abstract machine that can be in exactly one of a finite number of states at any given time. The FSM can change from one state to another in response to some inputs; the change from one state to another is called a &lt;strong&gt;transition&lt;/strong&gt;. An FSM is defined by a list of its states, its initial state, and the inputs that trigger each transition.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;The Challenge: What Will You Create?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Your task is simple: install the &lt;strong&gt;FSM_API&lt;/strong&gt; NuGet package and show us what you can build. It could be a simple game, a workflow for a business application, or a unique UI behavior. The possibilities are endless.&lt;/p&gt;

&lt;p&gt;You can get the package here: &lt;a href="https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API/" rel="noopener noreferrer"&gt;NuGet&lt;/a&gt;.&lt;/p&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%2Fug3lg680weumc0yii7ej.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%2Fug3lg680weumc0yii7ej.png" alt="Complex System of Gears Working Together" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Get Started&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To help you, I'll be releasing a new public GitHub repository soon. It will feature four examples of how to integrate the API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A minimal FSM-based console application&lt;/strong&gt; that demonstrates the core loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An Advanced console application&lt;/strong&gt; which demonstrates fine grained control over the initialization, update, and shutdown behavior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A minimal FSM-based WPF application&lt;/strong&gt; which demonstrates the simplest FSM loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An advanced WPF application&lt;/strong&gt; that shows how to decouple your application's behavior from the UI itself, a key principle of modern software design.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm eager to see what you create. Share your ideas and projects in the comments below, and let's get building!&lt;/p&gt;

&lt;p&gt;The Singularity Workshop&lt;/p&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%2F8ys9z96rd1o6akeirmtp.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%2F8ys9z96rd1o6akeirmtp.png" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>fsm</category>
      <category>opensource</category>
    </item>
    <item>
      <title>From Chaos to Cohesion: A Retrospective on How FSMs Connect Us to Domain Experts</title>
      <dc:creator>Trent Best</dc:creator>
      <pubDate>Wed, 17 Sep 2025 20:35:18 +0000</pubDate>
      <link>https://dev.to/trent_best_ca8617e4911baf/from-chaos-to-cohesion-a-retrospective-on-how-fsms-connect-us-to-domain-experts-391p</link>
      <guid>https://dev.to/trent_best_ca8617e4911baf/from-chaos-to-cohesion-a-retrospective-on-how-fsms-connect-us-to-domain-experts-391p</guid>
      <description>&lt;p&gt;Having spent the better part of 16 years creating complex drawing sets for various trades in the AEC industry where I not only created their complex 3D models but the sheets which were submitted for permit, or shop/field install drawings. I have had the privilege of working with Experts in their trades and I have built a career on using the software on their behalf and automating the software to do what their expertise prescribes.&lt;/p&gt;

&lt;p&gt;When I started building my FSM_API, it began as an offshoot of a hobby, building Starcraft 2 bots. Frustrated with the complex commands and controls available in this domain, I explored all sorts of options, eventually realizing the absolute necessity for Finite State Machines.&lt;/p&gt;

&lt;p&gt;However, the typical way of doing this—what we learn in the forums or watch in the tutorials—is itself valid, yet quite lacking. As I've also, as part of my career, driven efficiency up everywhere I work by analyzing complex workflows and identifying the bottlenecks, just like debugging.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Problem with Traditional FSMs
&lt;/h3&gt;

&lt;p&gt;The final piece of the puzzle clicked when we implement an FSM: we don't want to be blocked by having to always ensure it follows proper sequence, we don't want to have to provide similar or the same implementations, and most importantly, we want to be able to apply an FSM's behavior to as many contexts as possible. Here I recognized the need for a central abstraction, what I call the "Universal Unit of Work" which I believe I took from college math, but that was decades ago, so don't quote me on it.&lt;/p&gt;

&lt;p&gt;This fundamental realization led to the core design principles of the &lt;code&gt;FSM_API&lt;/code&gt;, which solves these issues by decoupling the FSM logic from its data, a concept referred to as the &lt;strong&gt;Context&lt;/strong&gt;. This allows a single FSM blueprint to be instantiated and applied to many different objects or systems, streamlining development and ensuring consistency across an entire application. The core of this abstraction is that a domain expert, regardless of their coding background, can describe a complex process, which can then be directly translated into a functional FSM.&lt;/p&gt;

&lt;p&gt;The shocker to me was that we can have an expert do something like this:&lt;/p&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%2Fyxz5beoexyzptyoc4agd.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%2Fyxz5beoexyzptyoc4agd.png" alt=" " width="762" height="1259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This diagram represents the expertise of a professional in their trade. They can capture every state, condition, and transition necessary to describe a complex workflow. By using a fluent, human-readable API, we can empower them to define this logic directly.&lt;/p&gt;




&lt;h3&gt;
  
  
  Translating Expertise into Code
&lt;/h3&gt;

&lt;p&gt;The complex diagram above, which a typical coder would spend hours trying to replicate with convoluted &lt;code&gt;if/else&lt;/code&gt; statements, can be translated into a clean and maintainable C# code block using the &lt;code&gt;FSM_API&lt;/code&gt;. The API's fluent interface and clear method names allow for a near-direct transcription of the domain expert's diagram into functional, debuggable code.&lt;/p&gt;

&lt;p&gt;The following code shows a comprehensive implementation of a &lt;strong&gt;Car Transmission FSM&lt;/strong&gt;, demonstrating the power of the &lt;code&gt;FSMBuilder&lt;/code&gt; to define a full domain of knowledge in a single, cohesive unit. Each state's actions (&lt;code&gt;onEnter&lt;/code&gt;, &lt;code&gt;onUpdate&lt;/code&gt;, &lt;code&gt;onExit&lt;/code&gt;) are defined along with the specific transitions that connect them. This includes complex logic for gear shifting and critical safety protocols like the &lt;code&gt;Fault&lt;/code&gt; state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;TheSingularityWorkshop.FSM_API&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 1. Define the Context Class&lt;/span&gt;
&lt;span class="c1"&gt;// This "data bag" holds all the real-time information the FSM needs to make decisions.&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CarContext&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IStateContext&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0.0f&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;BrakePedalPressed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;ThrottleDown&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;EngineFault&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Define the FSM&lt;/span&gt;
&lt;span class="c1"&gt;// This class contains the blueprint for the entire car transmission system.&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CarTransmissionFSM&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;CreateComplexFSM&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;FSM_API&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateFiniteStateMachine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CarFSM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"VehicleUpdate"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;// --- Define Top-Level States ---&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Park"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Transmission is in Park."&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;onUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Check for input */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;onExit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Exiting Park."&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Reverse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Transmission is in Reverse."&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;onUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Reverse logic */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;onExit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Exiting Reverse."&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Neutral"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Transmission is in Neutral."&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;onUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Idle engine logic */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;onExit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Exiting Neutral."&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fault"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CRITICAL FAULT: Transitioning to Fault state."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="c1"&gt;// Simulate a critical safety action: disable the engine&lt;/span&gt;
                    &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;EngineFault&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;onUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"In Fault mode. Cannot proceed."&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;onExit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fault has been manually reset."&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

            &lt;span class="c1"&gt;// --- Define Drive Sub-States (Gears) ---&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"First_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Shifted into First Gear."&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;onUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Apply torque for first gear */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;onExit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Prepare for shift up */&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Second_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Shifted into Second Gear."&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;onUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Apply torque for second gear */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;onExit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Prepare for shift */&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Third_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Shifted into Third Gear."&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;onUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Apply torque for third gear */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;onExit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Prepare for shift */&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fourth_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Shifted into Fourth Gear."&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;onUpdate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Apply torque for fourth gear */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="n"&gt;onExit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Prepare for shift */&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

            &lt;span class="c1"&gt;// --- Set Initial State ---&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithInitialState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Park"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;// --- Define Transitions ---&lt;/span&gt;
            &lt;span class="c1"&gt;// Top-level transitions (P, R, N, D)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Park"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Reverse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;BrakePedalPressed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Park"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"First_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;BrakePedalPressed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Reverse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Park"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;!((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;BrakePedalPressed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Reverse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Neutral"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Always can shift from R to N&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Neutral"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Park"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Neutral"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Reverse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;BrakePedalPressed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Neutral"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"First_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;BrakePedalPressed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;// A transition from any Drive gear back to Neutral or Park&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AnyTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Neutral"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;!((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;BrakePedalPressed&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1.0f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AnyTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Park"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;!((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;BrakePedalPressed&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1.0f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;// Drive sub-state transitions (Gear Shifting)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"First_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Second_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;15.0f&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;!((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;ThrottleDown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Second_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Third_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;30.0f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Third_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Fourth_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;45.0f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;// Downshifting transitions&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fourth_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Third_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;40.0f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Third_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Second_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;25.0f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Second_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"First_Gear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10.0f&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;ThrottleDown&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;// "Any-State" transitions for safety and error handling&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AnyTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fault"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;EngineFault&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AnyTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Park"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;BrakePedalPressed&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;CarContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Speed&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1.0f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;// Finalize the FSM blueprint&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BuildDefinition&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  The Paradigm Shift
&lt;/h3&gt;

&lt;p&gt;Now if we are able to get to this point where an expert has been able to input their domain of expertise into FSMs, then we only need a competent coder to follow behind implementing the scaffolded code. This changes everything! The complex, abstract logic that once resided solely within the mind of the expert is now a tangible, version-controlled asset. It becomes a &lt;strong&gt;unified logical architecture&lt;/strong&gt; that is easily accessible and maintainable, bridging the gap between domain knowledge and software implementation. The &lt;code&gt;FSM_API&lt;/code&gt; proves that by building the right tools, we can empower experts to define their complex worlds with ease.&lt;/p&gt;




&lt;h3&gt;
  
  
  Get the &lt;code&gt;FSM_API&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;You can access and support the &lt;code&gt;FSM_API&lt;/code&gt; at the following links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;code&gt;https://github.com/trentbest/fsm_api&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NuGet Package&lt;/strong&gt;: &lt;code&gt;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PayPal&lt;/strong&gt;: &lt;code&gt;https://www.paypal.com/paypalme/TheSingularityWorkshop&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>designpatterns</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Engineering "The" Loop</title>
      <dc:creator>Trent Best</dc:creator>
      <pubDate>Wed, 17 Sep 2025 01:32:57 +0000</pubDate>
      <link>https://dev.to/trent_best_ca8617e4911baf/engineering-the-loop-2cof</link>
      <guid>https://dev.to/trent_best_ca8617e4911baf/engineering-the-loop-2cof</guid>
      <description>&lt;h2&gt;
  
  
  The Problem with the Classic Game Loop 🎮
&lt;/h2&gt;

&lt;p&gt;Almost every interactive application, from video games to user interfaces, relies on a continuous &lt;strong&gt;execution loop&lt;/strong&gt;. This loop is the heart of the application, responsible for everything from updating the game state to rendering graphics. While it's a fundamental concept, the traditional approach can often feel like a point of contention among developers. Why? Because the classic game loop, often a simple &lt;code&gt;while(true)&lt;/code&gt; or &lt;code&gt;while(IsRunning)&lt;/code&gt; block, can quickly become an unmanageable monolith.&lt;/p&gt;

&lt;p&gt;Consider a typical game loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;MainGameLoop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt;  &lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IsRunning&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;ProcessInput&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;UpdateGameState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;RenderGraphics&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;PlayAudio&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// ...and a dozen other things&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt;  &lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;Shutdown&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works for simple projects, but as an application grows, this single loop becomes a catch-all for complex logic. It tightly couples disparate systems (like input, rendering, and AI), making the code difficult to maintain, test, and debug. You end up with a single, massive function that handles everything, and any small change can have unintended consequences.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Better Way: A State Machine-Driven Loop ✨
&lt;/h2&gt;

&lt;p&gt;What if we could break free from this monolithic approach? What if our application's "loop" wasn't a static &lt;code&gt;while&lt;/code&gt; statement, but a dynamic, self-managing system? That's the power of a &lt;strong&gt;Finite State Machine (FSM)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In our project, we've integrated this idea into the &lt;strong&gt;MainWindowViewModel&lt;/strong&gt; for a WPF application. Instead of a single, endlessly running loop, our application's flow is managed by an FSM. Each "tick" of the application isn't a fixed set of actions, but a transition to a new state based on events.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;MainWindowViewModel&lt;/code&gt; (from the provided code) implements the &lt;code&gt;IStateContext&lt;/code&gt; interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MainWindowViewModel&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;INotifyPropertyChanged&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IStateContext&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// ... properties and methods&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsValid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InitializeState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// This method will be called by the FSM&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// It will be the entry point for our initial actions&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach allows the FSM to dictate what happens at any given moment. For example, when the application starts, the FSM can trigger the &lt;code&gt;InitializeState()&lt;/code&gt; method. If a user clicks a button, the FSM can transition the application into a new state that handles that specific action, like fetching GitHub repository data. The loop isn't a single, continuous block—it's a series of transitions and actions managed by a state machine.&lt;/p&gt;

&lt;p&gt;This makes the &lt;code&gt;MainWindowViewModel&lt;/code&gt; highly modular and responsive. We can have states like &lt;code&gt;LoadingRepositories&lt;/code&gt;, &lt;code&gt;ShowingGitHubStatus&lt;/code&gt;, or &lt;code&gt;Idle&lt;/code&gt;, and the FSM ensures that the correct actions are executed for each state.&lt;/p&gt;




&lt;h2&gt;
  
  
  The API Evolution: From Simple to Dynamic 🚀
&lt;/h2&gt;

&lt;p&gt;The two provided Unity C# scripts, &lt;code&gt;FSM_UnityIntegration.cs&lt;/code&gt; and &lt;code&gt;FSM_UnityIntegrationAdvanced.cs&lt;/code&gt;, showcase different approaches to creating a game loop driven by a Finite State Machine (FSM) API. The basic &lt;code&gt;FSM_UnityIntegration&lt;/code&gt; script uses a rigid one-to-one mapping between Unity's lifecycle methods and a single FSM processing group. In contrast, &lt;code&gt;FSM_UnityIntegrationAdvanced&lt;/code&gt; allows for a dynamic, runtime-modifiable list of processing groups for each Unity message, providing greater flexibility. Both scripts implement the singleton pattern to ensure only one instance of the integration exists in a scene.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Basic Approach: Direct Mapping
&lt;/h3&gt;

&lt;p&gt;In our initial API, we used a direct one-to-one mapping. Each Unity message (like &lt;code&gt;Start&lt;/code&gt;, &lt;code&gt;Update&lt;/code&gt;, &lt;code&gt;OnDestroy&lt;/code&gt;) directly called a single, corresponding process group. This was a step up from the monolithic loop, but it was still quite rigid. You had a predefined set of actions for each phase of the application lifecycle.&lt;/p&gt;

&lt;p&gt;For instance, the &lt;code&gt;Update()&lt;/code&gt; method in the basic integration always calls the single &lt;code&gt;_updateProcessingGroup&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;FSM_API&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_updateProcessingGroup&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;FSM_API&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_unityHandles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity:&lt;/strong&gt; It's a simple, predictable model that's easy for new developers to grasp.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; The direct call to a single processing group is efficient and has minimal overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability:&lt;/strong&gt; The flow is fixed and well-defined, reducing the chance of unexpected behavior.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rigidity:&lt;/strong&gt; The biggest drawback is its lack of flexibility. You can't dynamically add or remove processing groups at runtime. To change what happens during an &lt;code&gt;Update&lt;/code&gt;, you'd need to modify the code itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited Customization:&lt;/strong&gt; It's not suitable for scenarios where the game loop needs to change its behavior based on the application's state, such as enabling or disabling different systems (e.g., a combat system) only when a specific state is active.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Advanced Approach: Runtime Modifiable Loops
&lt;/h3&gt;

&lt;p&gt;Our more advanced API takes this a step further. We don't just have a single method for &lt;code&gt;Update&lt;/code&gt;; instead, we provide a &lt;strong&gt;list of strings&lt;/strong&gt; that represent the process groups to be executed. This is a simple but incredibly powerful change.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Update()&lt;/code&gt; method in the advanced integration iterates through a list of groups, calling &lt;code&gt;FSM_API.Interaction.Update()&lt;/code&gt; for each one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_updateProcessingGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;FSM_API&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;group&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;FSM_API&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_unityHandles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows us to add, remove, or reorder process groups on the fly. For example, when the FSM enters a &lt;code&gt;FetchRepositories&lt;/code&gt; state, it can dynamically add the &lt;code&gt;GitHubRepositoryService&lt;/code&gt; process group to the update list using the &lt;code&gt;AddProcessingGroup()&lt;/code&gt; method. When the fetch is complete, the FSM transitions to another state and can remove that process group. The application's loop isn't just a fixed sequence of events—it's a fluid, context-aware process.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility and Modularity:&lt;/strong&gt; You can compose the game loop on the fly, adding and removing systems as needed without changing the core integration code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State-Driven Behavior:&lt;/strong&gt; This approach fully leverages the power of the FSM. Different states can dictate which systems are active, making the application's behavior highly contextual and adaptive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; It's easier to add new systems without a cascading effect. You simply create a new processing group and add it to the relevant list when it's needed.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complexity:&lt;/strong&gt; This model is more complex to set up and manage. Developers must be mindful of which groups are active at any given time to avoid unexpected behavior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Potential Performance Overhead:&lt;/strong&gt; Iterating through a list of groups every frame adds a small amount of overhead compared to a direct function call, though this is negligible in most cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging:&lt;/strong&gt; It can be more challenging to debug, as the flow of execution isn't fixed; it depends on the current state and the contents of the processing group lists.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Comparison and Conclusion ⚖️
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Basic Integration&lt;/th&gt;
&lt;th&gt;Advanced Integration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Execution Model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Fixed&lt;/strong&gt;: One-to-one mapping between Unity messages and FSM groups.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Dynamic&lt;/strong&gt;: Iterates through a runtime-modifiable list of groups.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low: Changes require code modification.&lt;/td&gt;
&lt;td&gt;High: Groups can be added/removed at runtime.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Use Case&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Ideal for simple applications with a consistent, unchanging game loop.&lt;/td&gt;
&lt;td&gt;Best for complex, state-driven applications where systems need to be enabled/disabled dynamically.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Maintainability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Easy to maintain and understand for small projects.&lt;/td&gt;
&lt;td&gt;More maintainable in the long run for large projects, as logic is isolated by state.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited: Adding new features can lead to a monolithic &lt;code&gt;Update()&lt;/code&gt; method.&lt;/td&gt;
&lt;td&gt;High: New systems can be added without modifying core code.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The choice between the two integrations depends on the needs of the project. The &lt;strong&gt;basic &lt;code&gt;FSM_UnityIntegration&lt;/code&gt;&lt;/strong&gt; is a great starting point for developers who want a simple, reliable FSM-driven loop without the need for complex, dynamic behavior. The &lt;strong&gt;advanced &lt;code&gt;FSM_UnityIntegrationAdvanced&lt;/code&gt;&lt;/strong&gt; is a more powerful and scalable solution for larger, more complex applications that require a fluid and responsive game loop that can adapt to different application states. By leveraging the FSM to control which groups are active, the advanced model creates a truly &lt;strong&gt;context-aware&lt;/strong&gt; application loop.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: The Future is State-Driven 🤖
&lt;/h2&gt;

&lt;p&gt;By moving from a monolithic &lt;code&gt;while&lt;/code&gt; loop to a &lt;strong&gt;dynamic, FSM-driven execution model&lt;/strong&gt;, we've created an application that is more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modular&lt;/strong&gt;: Each process group and state handles a single responsibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainable&lt;/strong&gt;: Logic is isolated, making it easier to debug and modify.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable&lt;/strong&gt;: We can easily add new features without a cascading effect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime Modifiable&lt;/strong&gt;: The application can adapt its behavior on the fly based on its current state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't just about elegant code; it's about building robust, flexible, and powerful applications that can grow and evolve without becoming a tangled mess. So next time you're about to write a classic &lt;code&gt;while(true)&lt;/code&gt; loop, ask yourself: could a state machine do this better?&lt;/p&gt;




&lt;h3&gt;
  
  
  💖 Support Us
&lt;/h3&gt;

&lt;p&gt;If you find this project useful, you can support its development through PayPal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J" rel="noopener noreferrer"&gt;&lt;strong&gt;Donate via PayPal&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🔗 Useful Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NuGet Package:&lt;/strong&gt; &lt;a href="https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API" rel="noopener noreferrer"&gt;TheSingularityWorkshop.FSM_API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://github.com/TrentBest/FSM_API" rel="noopener noreferrer"&gt;TrentBest/FSM_API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License:&lt;/strong&gt; &lt;a href="https://opensource.org/licenses/MIT" rel="noopener noreferrer"&gt;MIT License&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🧠 Brought to you by
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Singularity Workshop&lt;/strong&gt; – Tools for the curious, the bold, and the systemically inclined.&lt;/p&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%2Fgl6tdvgg73ixyj0m0kuf.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%2Fgl6tdvgg73ixyj0m0kuf.png" alt="The image depicts a futuristic, sci-fi landscape dominated by glowing circuitry. A large, stylized Patreon logo hovers in the dark, starry sky above a radiant, eye-like sphere. This sphere pulses with vibrant, multicolored light, casting a brilliant glow onto the digital terrain below. The ground is a vast circuit board, with rivers of glowing orange and blue energy flowing along intricate pathways. Small, button-like structures on the surface emit soft light. The overall scene feels alive and dynamic, suggesting a powerful, almost magical, connection between technology and consciousness, with the Patreon logo at the center of it all." width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
Because state shouldn’t be a mess.&lt;/p&gt;




</description>
      <category>architecture</category>
      <category>designpatterns</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Announcing The Singularity Workshop: A New FSM API for Unity</title>
      <dc:creator>Trent Best</dc:creator>
      <pubDate>Sun, 07 Sep 2025 05:56:30 +0000</pubDate>
      <link>https://dev.to/trent_best_ca8617e4911baf/announcing-the-singularity-workshop-a-new-fsm-api-for-unity-48np</link>
      <guid>https://dev.to/trent_best_ca8617e4911baf/announcing-the-singularity-workshop-a-new-fsm-api-for-unity-48np</guid>
      <description>&lt;p&gt;Today marks a major milestone for &lt;strong&gt;The Singularity Workshop&lt;/strong&gt;—we've successfully submitted our first product, a lightweight and powerful &lt;strong&gt;FSM API&lt;/strong&gt;, to the Unity Asset Store. This isn't just a simple tool; it's the first step in our mission to build foundational technologies that empower creators to bring their ambitious projects to life.&lt;/p&gt;

&lt;p&gt;When building complex games or applications in Unity, managing states can become incredibly challenging. Our FSM API is designed to solve this problem by providing a clean, elegant, and high-performance framework for building state-driven logic. It's built for developers who want to focus on their core gameplay without getting bogged down in boilerplate code.&lt;/p&gt;

&lt;p&gt;The core of the FSM API is a standalone C# library, delivered as a NuGet package. We then developed a dedicated integration layer that brings this core functionality directly into the Unity Editor. This approach allows us to ensure the API is robust and continuously developed while providing a seamless experience for Unity developers.&lt;/p&gt;




&lt;h3&gt;
  
  
  Join Our Journey
&lt;/h3&gt;

&lt;p&gt;The submission to the Asset Store is just the beginning. The Singularity Workshop is committed to building a suite of interconnected tools that will help you create advanced systems for game AI, player mechanics, and more.&lt;/p&gt;

&lt;p&gt;You can follow our journey and support our work here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Explore the Code:&lt;/strong&gt;
Explore the Code:
&lt;a href="https://github.com/TrentBest/FSM_API" rel="noopener noreferrer"&gt;https://github.com/TrentBest/FSM_API&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Get the NuGet Package:&lt;br&gt;
&lt;a href="https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API/" rel="noopener noreferrer"&gt;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Explore Our Vision:&lt;br&gt;
&lt;a href="https://www.patreon.com/TheSingularityWorkshop" rel="noopener noreferrer"&gt;https://www.patreon.com/TheSingularityWorkshop&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Support the project:&lt;/strong&gt; &lt;a href="https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J" rel="noopener noreferrer"&gt;&lt;strong&gt;Donate via PayPal&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>fsm</category>
      <category>csharp</category>
      <category>assetstore</category>
    </item>
    <item>
      <title>Finite State Machines - the Universal Unit of Work</title>
      <dc:creator>Trent Best</dc:creator>
      <pubDate>Sat, 06 Sep 2025 02:48:11 +0000</pubDate>
      <link>https://dev.to/trent_best_ca8617e4911baf/finite-state-machines-the-universal-unit-of-work-313p</link>
      <guid>https://dev.to/trent_best_ca8617e4911baf/finite-state-machines-the-universal-unit-of-work-313p</guid>
      <description>&lt;p&gt;We've all been there: a simple boolean flag here, a nested if statement there. It seems harmless at first, but soon your codebase is a tangled mess of conditional logic. Your &lt;code&gt;Door&lt;/code&gt; class can be opened and closed. Easy, right?&lt;/p&gt;

&lt;p&gt;But in the wild, the simple, intuitive code you first wrote for a door quickly starts to smell. The moment we try to add a new feature, such as a lock, our elegant two-state object becomes a mess of conditional logic.&lt;/p&gt;

&lt;p&gt;Let's look at what our intuitive code looks like to begin with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Door&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The door is now open."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The door is now closed."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, imagine we need to add a "locked" state. To accommodate this, our code is no longer simple. We have to add a new boolean flag, &lt;code&gt;IsLocked&lt;/code&gt;, and then we have to modify all of our existing methods to account for this new state. We also have to add new methods, such as &lt;code&gt;Lock&lt;/code&gt; and &lt;code&gt;Unlock&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Door&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsLocked&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// We added this!&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;IsLocked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// We modified this!&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The door is now open."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The door is locked and cannot be opened."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The door is now closed."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// We added this!&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;IsLocked&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The door is now locked."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Unlock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// We added this!&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;IsLocked&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The door is now unlocked."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What about a Broken state? Or a Sliding door? Or a RollUp door? We can approximate these with more booleans, but each new addition requires us to go back and add more and more &lt;code&gt;if/else&lt;/code&gt; statements to every method. It's not scalable, it's brittle, and it's full of boilerplate.&lt;/p&gt;

&lt;p&gt;Here are the pros and cons of using this approach:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Simple and quick to implement for basic cases.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Tight Coupling&lt;/strong&gt;: Logic is tied to a single object.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No external dependencies or abstractions.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Boilerplate&lt;/strong&gt;: &lt;code&gt;if/else&lt;/code&gt; checks for every state change.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Difficult to Scale&lt;/strong&gt;: Adding new features breaks existing logic.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Difficult to maintain&lt;/strong&gt;: Code becomes a tangled mess.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  The Typical FSM Solution and Its Pitfalls
&lt;/h2&gt;

&lt;p&gt;A typical FSM approach would have you create distinct classes for each state (e.g., &lt;code&gt;DoorOpenState&lt;/code&gt;, &lt;code&gt;DoorClosedState&lt;/code&gt;, &lt;code&gt;DoorLockedState&lt;/code&gt;) that all implement a common &lt;code&gt;IState&lt;/code&gt; interface. The &lt;code&gt;Door&lt;/code&gt; class would then hold a reference to its current state object. This is what you'll see in most tutorials and books.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IState&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DoorContext&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DoorClosedState&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IState&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DoorContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DoorContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The door is now closed."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DoorContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DoorContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DoorOpenState&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IState&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DoorContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DoorContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"The door is now open."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DoorContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DoorContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, what does it take to add a "locked" state to this? It's not as simple as adding a boolean. We need to create a new state class, &lt;code&gt;DoorLockedState&lt;/code&gt;, and then modify our existing states and the context to allow for transitions to this new state. This still requires a fair amount of boilerplate and modification of existing code.&lt;/p&gt;

&lt;p&gt;Here's an overview of the pros and cons of this and other FSM implementations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Clean State Separation&lt;/strong&gt;: Logic for each state is in a distinct class.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Boilerplate&lt;/strong&gt;: Requires a lot of code to set up states, transitions, and the state machine itself.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Enforced Transitions&lt;/strong&gt;: The model naturally enforces valid transitions.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Framework-Dependent&lt;/strong&gt;: Often tightly coupled to a specific game engine or framework.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Well-Established Pattern&lt;/strong&gt;: A common and well-understood design pattern.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Rigid Design&lt;/strong&gt;: FSM definition is static and difficult to modify at runtime.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Hierarchical FSMs (HFSMs)&lt;/strong&gt;: Allows for nested states, which can reduce complexity.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Hierarchical FSMs (HFSMs)&lt;/strong&gt;: Can introduce complexity and make the state machine harder to understand and debug.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Behavior Trees&lt;/strong&gt;: A different approach that uses a tree structure to define behavior.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Behavior Trees&lt;/strong&gt;: Can be overkill for simple state management and can be difficult to reason about the overall state of the system.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Hybrid Approaches&lt;/strong&gt;: Combining FSMs with other patterns like Behavior Trees.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Hybrid Approaches&lt;/strong&gt;: Can be overly complex and lead to "spaghetti code" if not carefully implemented.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;State Pattern&lt;/strong&gt;: Allows a context object to change its behavior depending on its internal state.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;State Pattern&lt;/strong&gt;: Can lead to a large number of classes for each state, which can be difficult to manage. Changes to the state machine often require changing multiple classes.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  A Better Way: FSM_API and Centralized State
&lt;/h2&gt;

&lt;p&gt;The FSM_API is a new approach to FSMs that is designed to be blazing-fast, software-agnostic, and fully decoupled from your application's logic. It's a declarative, data-driven approach that allows you to define your FSM once and use it everywhere.&lt;/p&gt;

&lt;p&gt;The key concept is that the FSM_API operates on Plain Old C# Objects (POCOs) that simply implement the &lt;code&gt;IStateContext&lt;/code&gt; interface. This ensures a clean separation between your FSM logic and your application's data.&lt;/p&gt;

&lt;p&gt;Here's our door, refactored with the FSM_API.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Define the Context
&lt;/h3&gt;

&lt;p&gt;Our &lt;code&gt;Door&lt;/code&gt; class is now a simple POCO. All its logic is handled by the FSMs we are about to create.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Door&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IStateContext&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsLocked&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"FrontDoor"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsValid&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// FSM API will not operate on this if false.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Multiple FSMs on a Single Context
&lt;/h3&gt;

&lt;p&gt;The true power of FSM_API is its ability to manage multiple, independent behaviors on a single context object. This allows us to separate our "open/close" logic from our "lock/unlock" logic.&lt;/p&gt;

&lt;p&gt;First, let's create a simple FSM to handle the door's opening and closing. This is the &lt;code&gt;DoorFSM&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;FSM_API&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateFiniteStateMachine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DoorFSM"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Closed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;Door&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;State&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Open"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onEnter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;Door&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;IsOpen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithInitialState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Closed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Closed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Open"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;!((&lt;/span&gt;&lt;span class="n"&gt;Door&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;IsLocked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Open"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Closed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Closed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Locked"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Locked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Closed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;!((&lt;/span&gt;&lt;span class="n"&gt;Door&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;IsLocked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unlocked"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Closed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BuildDefinition&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the FSM_API allows for runtime redefinition of FSMs, we can dynamically add states and transitions to our door object without recompiling. This capability is what makes the FSM_API a powerful choice for highly configurable or live-updating systems.&lt;/p&gt;

&lt;p&gt;Here's an overview of the pros and cons of our API:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Centralized State&lt;/strong&gt;: FSM logic is separated from data.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Learning Curve&lt;/strong&gt;: New concepts might take time to grasp, especially if you are used to traditional FSM implementations.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Extremely Lightweight&lt;/strong&gt;: The core FSM_API.dll is a tiny 45kb, and the full NuGet package is only 417.09kb.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Minimalism&lt;/strong&gt;: The API is minimal by design; you will need to rely on the provided documentation and quick-start guides to get started.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Runtime Redefinition&lt;/strong&gt;: FSMs can be modified on the fly.&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Lightweight &amp;amp; Performant&lt;/strong&gt;: Minimal memory allocations and optimized performance.&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Framework Agnostic&lt;/strong&gt;: No external dependencies or frameworks required.&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Thread-Safe&lt;/strong&gt;: Designed for safe, deferred mutation handling.&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Error-Tolerant&lt;/strong&gt;: Built-in diagnostics prevent runaway logic.&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is just a glimpse of what's possible with the FSM_API. Its features make it a robust choice for any C# application requiring sophisticated state management.&lt;/p&gt;

&lt;p&gt;If you'd like to get started, you can find our NuGet package and all the documentation on our GitHub repository:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NuGet Package:&lt;/strong&gt; &lt;a href="https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API" rel="noopener noreferrer"&gt;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository:&lt;/strong&gt; &lt;a href="https://www.google.com/search?q=https://github.com/TrentBest/FSM_API" rel="noopener noreferrer"&gt;https://github.com/TrentBest/FSM_API&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you feel this tool is valuable to you, please consider supporting the project. &lt;strong&gt;&lt;a href="https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J" rel="noopener noreferrer"&gt;Donate via PayPal&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>api</category>
      <category>fsm</category>
    </item>
  </channel>
</rss>
