<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged unity3d</title>
<link>https://coderlegion.com/tag/unity3d</link>
<description>Powered by Question2Answer</description>
<item>
<title>Aesthetic Trading Automation for Binance</title>
<link>https://coderlegion.com/30392/aesthetic-trading-automation-for-binance</link>
<description>&lt;p&gt;I had an idea waiting up in the pipeline and finally decided to raw the cover over it. I created a trading automation tool which uses multiple trading algorithims under the hood to maximize the gains. I tested 7 different trading algorithimns in 15 different configurations across 12 coins and lab run them in a terminal. However, it turned to be super boring and tedious considering I had to run them time and again for specific intervals. &lt;/p&gt;
&lt;p&gt;In order to make it interesting, I turned up my Unity Editor and rolled out a scene to glamour-covering it. I used my &lt;strong&gt;claude code&lt;/strong&gt; to give it a cyberpunk outlook and make the main tower look like a wall street for crypto. Every single tower around the main tower represents a specific algorithim and the respective traded coin. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: I have used virtual currency in my project but the models are being trained on the real data. My unity project is linked with my python server through web socket and I am using 3 minute interval candle for training my algorithims. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tech in qustion&lt;/strong&gt;: Binance, Python, Unity 3d &lt;/p&gt;
</description>
<category>Videos</category>
<guid isPermaLink="true">https://coderlegion.com/30392/aesthetic-trading-automation-for-binance</guid>
<pubDate>Fri, 09 Oct 2026 05:01:21 +0000</pubDate>
</item>
<item>
<title>using unity access to create a basic seen. What works and what still needs developing</title>
<link>https://coderlegion.com/27467/using-unity-access-to-create-a-basic-seen-what-works-and-what-still-needs-developing</link>
<description>&lt;p&gt;Since development of unity access has gone so well, I have been able to have most of the basic features built. This means that I was able to begin testing it to see if it would be viable to use in the long run. &lt;br&gt;
I did this by building a basic first person seen. &lt;/p&gt;
&lt;h3 id=&quot;building-the-scene&quot;&gt;Building The Scene&lt;/h3&gt;
&lt;p&gt;I started with a blank unity seen and created a capsule, using the game objects menu in the menu bar. &lt;br&gt;
I then used the accessible hierarchy to find the capsule. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/q8yh7zqi002wxgn9cxur.png&quot; alt=&quot;shows the new accessible hierarchy with objects inside it&quot;&gt;&lt;br&gt;
I then renamed it to player. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/z1godb9ja3j8ta4civd7.png&quot; alt=&quot;the image is of the object inspector where the name of the capsule is changed to player&quot;&gt;&lt;/p&gt;
&lt;p&gt;Next, I added the components to the player object that will be needed for the game. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/atb97xnzukfmvzj0c0o9.png&quot; alt=&quot;the image is of the component selection screen.&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/ppty1y6pa708p8qh4tbm.png&quot; alt=&quot;the image is of all the components added to the player in the inspector.&quot;&gt;&lt;br&gt;
I then used the same process to add a ground and 2 walls. &lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/oszkxpdl0upm8bjuzsh8.png&quot; alt=&quot;the image is of the entire scene. It is seen from a first person perspective and features 2 walls on a ground.&quot;&gt;&lt;br&gt;
overall, I found the new plugin to be much easier than using unity's editor or writing the code to create each object. However, there is still room for improvement. &lt;/p&gt;
&lt;h3 id=&quot;what-to-work-on-next&quot;&gt;what to work on next&lt;/h3&gt;
&lt;p&gt;Now that I have the basic features in place I need to work on a way for the unity access plugin to be integrated into the editor asset system. At the moment I have to move and rename assets in file explorer. This could cause reference errors if I forget to move a .meta file with the asset it is attached to. &lt;br&gt;
I also want to build a material system. The alternative would be to write the code for the objects materials. However, a material system would give me added convenience when adding shaders or effects. &lt;br&gt;
{% card %}&lt;br&gt;
If you want to follow along with the development of Unity Access or check out the code, you can find the repository over on &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/retro-coder64/unity_access&quot;&gt;GitHub!&lt;/a&gt;&lt;br&gt;
{% endcard %}&lt;/p&gt;
&lt;h3 id=&quot;join-the-conversation&quot;&gt;join the conversation&lt;/h3&gt;
&lt;p&gt;what problems have you faced when developing plugins for unity? &lt;br&gt;
Have you done anything around accessibility? &lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/27467/using-unity-access-to-create-a-basic-seen-what-works-and-what-still-needs-developing</guid>
<pubDate>Thu, 17 Sep 2026 06:11:07 +0000</pubDate>
</item>
<item>
<title>using Codex to build unity_access. Whats worked, what hasn't and tips for building your own accessible applications with AI.</title>
<link>https://coderlegion.com/27466/using-codex-build-unityaccess-whats-worked-hasnt-building-accessible-applications-with</link>
<description>&lt;p&gt;Over the past week, I have been vibe coding &lt;strong&gt;Unity Access&lt;/strong&gt;, a plugin for the Unity Editor that makes the previously difficult-to-access editor more screen-reader compatible.&lt;/p&gt;
&lt;p&gt;Unity Access uses the NVDA API alongside the Unity Editor API to create a bridge between Unity and the NVDA screen reader.&lt;/p&gt;
&lt;p&gt;I have been using Codex for the programming, and it is for this reason that I wanted to write this post. During the development of Unity Access, I have learnt a lot about using Codex to develop an accessible application that tutorials and documentation simply do not cover.&lt;/p&gt;
&lt;p&gt;One of the biggest lessons I have learnt is that building accessible software with AI requires considerably more than simply telling the model to &quot;make it accessible&quot;. Accessibility needs to be expressed as specific, testable behaviour.&lt;br&gt;
In this post, I will describe what worked, what did not work, how you can build your own accessible applications, and some of the things you should watch out for.&lt;/p&gt;
&lt;h3 id=&quot;tools-and-technology&quot;&gt;Tools and technology&lt;/h3&gt;
&lt;p&gt;Before I get into the details, I feel it is important to describe the tools and technology I use. This is because some of the results I experienced may differ from those of someone using different tools.&lt;/p&gt;
&lt;p&gt;To write the code for this project, I used Codex running &lt;strong&gt;GPT-5.6 Sol with medium reasoning effort&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For my work, I found this to provide a good balance between efficiency, cost per one million tokens and quality of output. These factors are particularly important to me because I want to achieve the best possible result while keeping token costs as low as reasonably possible.&lt;/p&gt;
&lt;p&gt;To write the Markdown specification files, I used &lt;strong&gt;VS Code&lt;/strong&gt;. I chose this editor because it works extremely well with the NVDA screen reader. This means I can use it out of the box without accessibility modifications.&lt;/p&gt;
&lt;p&gt;This is particularly important to me as a blind developer because it gives me a great deal of flexibility and independence. I can navigate the project, read and edit code, organise files and review changes without relying on inaccessible visual interfaces.&lt;/p&gt;
&lt;p&gt;To test the plugin, I am using &lt;strong&gt;Unity with a sample project based on the Universal Render Pipeline (URP)&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I chose Unity because I find its GameObject and component architecture easier to understand and work with. Even though Godot already has an established plugin for editor accessibility, I personally found its tree structure harder to reason about.&lt;/p&gt;
&lt;p&gt;Finally, to read what is displayed on my screen, I use the &lt;strong&gt;NVDA screen reader&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I use NVDA because it is open source and therefore does not come with licensing fees. In addition, I have found its ability to read my code editor and source code to be superior to JAWS for my particular workflow.&lt;/p&gt;
&lt;p&gt;Together, these tools allow me to understand what is happening on my computer and to develop, run and test my code independently.&lt;/p&gt;
&lt;h3 id=&quot;building-the-plugin-what-worked-and-what-doesn-t&quot;&gt;Building the plugin: what worked and what doesn’t&lt;/h3&gt;
&lt;h4 id=&quot;what-worked-&quot;&gt;What worked?&lt;/h4&gt;
&lt;p&gt;During my experience with different AI models, I have found that each has its own quirks and characteristics. Codex with GPT-5.6 Sol is no exception.&lt;/p&gt;
&lt;p&gt;Here is my list of things that worked well, and continue to work well, when developing Unity Access.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Setting clear boundaries in the root &lt;code&gt;AGENTS.md&lt;/code&gt; file.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This might seem obvious, but clear rules and boundaries make an enormous difference.&lt;/p&gt;
&lt;p&gt;Tell the model where it is allowed to make changes, which APIs it should use, which files it should or should not modify, how large you want changes to be, what accessibility requirements apply, and what must be true before the task can be considered complete.&lt;/p&gt;
&lt;p&gt;The more specific these rules are, the more predictable the model becomes.&lt;/p&gt;
&lt;p&gt;This becomes particularly important when developing an accessibility-focused application or plugin.&lt;/p&gt;
&lt;p&gt;For example, in my experience, telling the AI:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;The user must be able to navigate this menu using NVDA.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;produces much better results than simply saying:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Make this menu accessible.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The first instruction gives the AI something concrete to work towards.&lt;/p&gt;
&lt;p&gt;You can make this even more specific by defining what navigation actually means. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;every interactive control must be reachable using the keyboard;&lt;/li&gt;
&lt;li&gt;NVDA must announce the purpose of each control;&lt;/li&gt;
&lt;li&gt;the current value or state of the control must be available to the user;&lt;/li&gt;
&lt;li&gt;controls must be usable without a mouse; and&lt;/li&gt;
&lt;li&gt;the user must be able to leave or return from the interface using the keyboard.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This gives the AI a measurable target rather than an abstract concept.&lt;/p&gt;
&lt;p&gt;I have found this to be one of the biggest differences between simply asking AI to produce &quot;accessible&quot; software and actually getting useful accessibility behaviour.&lt;/p&gt;
&lt;p&gt;Setting boundaries around the size of changes is also useful. If you tell the AI that you want a small, direct change, it is less likely to waste tokens modifying or refactoring an entire file when only a small section needs changing.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Standardising functions such as buttons and text boxes.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Standardising functions for things such as buttons, text boxes and other controls, and placing them in a utilities folder, has been extremely useful.&lt;/p&gt;
&lt;p&gt;You can reference these utilities in future Markdown specification files and instruct the AI to call those specific methods. This prevents the AI from recreating the same utility every time it needs one.&lt;/p&gt;
&lt;p&gt;More importantly for an accessibility project, it prevents subtle variations from appearing throughout the application.&lt;/p&gt;
&lt;p&gt;For example, instead of allowing Codex to invent three different ways of creating an accessible button, I can create one accessible button utility and tell it:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Use the accessible controls located in &lt;code&gt;./utils&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That makes accessibility behaviour much more consistent throughout the project.&lt;/p&gt;
&lt;p&gt;It also means that if I improve one of the shared accessible controls later, every part of the plugin that uses that control can benefit from the improvement.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Organise your code into related folders.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is not just useful for the AI. It is also extremely useful for screen-reader users.&lt;/p&gt;
&lt;p&gt;Navigating a properly organised folder tree using NVDA is considerably easier than searching through a large collection of files, particularly when files have similar names.&lt;/p&gt;
&lt;p&gt;Because I am using a CLI, I can also set the working directory to a particular folder and instruct the AI not to add or modify code outside that directory.&lt;/p&gt;
&lt;p&gt;This gives me another layer of protection against the AI modifying working code elsewhere in the project and potentially introducing bugs.&lt;/p&gt;
&lt;p&gt;For a Unity project, where the complete project can contain a large number of generated and engine-related files, a properly configured &lt;code&gt;.gitignore&lt;/code&gt; is also extremely useful.&lt;/p&gt;
&lt;p&gt;This means I only need to commit the actual plugin and relevant project files rather than the entire Unity project.&lt;/p&gt;
&lt;p&gt;An organised folder structure also makes relative paths easier to reference in Markdown specification files. Instead of telling the AI vaguely to find a particular file, I can tell it exactly where that file should exist.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Separating UI functionality from backend functionality in &lt;code&gt;AGENTS.md&lt;/code&gt; files.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Separating UI requirements from backend functionality in my Markdown specification files has worked extremely well.&lt;/p&gt;
&lt;p&gt;This is particularly useful when creating an editor plugin.&lt;/p&gt;
&lt;p&gt;For example, I can have separate sections describing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;what the interface should contain;&lt;/li&gt;
&lt;li&gt;how keyboard navigation should work;&lt;/li&gt;
&lt;li&gt;what NVDA should announce;&lt;/li&gt;
&lt;li&gt;which backend functions are required; and&lt;/li&gt;
&lt;li&gt;which Unity Editor APIs should perform those operations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This means that if I want to change the UI without changing the backend, I can instruct the AI to work only within the relevant section.&lt;/p&gt;
&lt;p&gt;Likewise, if a backend function needs replacing, I can make that change without unnecessarily redesigning the interface.&lt;/p&gt;
&lt;p&gt;It also makes the specification much easier for me to read and maintain.&lt;/p&gt;
&lt;p&gt;If there is a particular function or UI element that I later decide to remove, it is considerably easier to find and remove when the requirements are separated rather than buried inside one enormous paragraph.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Keeping Markdown specification files concise and structured.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I found that keeping my Markdown files to the point, while adding a short description at the top explaining the purpose of the file, helps keep project requirements clear and reduces the likelihood of the AI misunderstanding what I intend.&lt;/p&gt;
&lt;p&gt;Previously, I wrote many of my specifications almost like essays.&lt;/p&gt;
&lt;p&gt;That did not work particularly well.&lt;/p&gt;
&lt;p&gt;The AI would sometimes overlook tasks or functionality described earlier in the file and concentrate disproportionately on instructions appearing later.&lt;/p&gt;
&lt;p&gt;Breaking the specification into properly organised headings and sections does not just make it easier for me to read with NVDA; it also appears to make it easier for the AI to understand which requirements belong together and remain within scope.&lt;/p&gt;
&lt;p&gt;The goal is not necessarily to make specifications tiny. The goal is to make every requirement easy to find and difficult to misunderstand.&lt;/p&gt;
&lt;p&gt;Now, this all makes it sound as though my project went well. However, here are some things that did not work and that I only found out later.&lt;/p&gt;
&lt;h4 id=&quot;what-doesn-t-work&quot;&gt;What doesn’t work&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Having ChatGPT write parts of my Markdown specification files without validating them.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Having ChatGPT write parts of my Markdown specification files initially seemed like a great way to fill gaps in my own Unity knowledge.&lt;/p&gt;
&lt;p&gt;However, I discovered that this comes with risks.&lt;/p&gt;
&lt;p&gt;Although ChatGPT can research and write code effectively, I found that asking it to define technical requirements for parts of Unity that I did not already understand could cause problems if I accepted the output without checking it.&lt;/p&gt;
&lt;p&gt;One example was my &lt;code&gt;project_settings.md&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;Because I did not know exactly what should be included in an accessible Unity Project Settings implementation, I asked ChatGPT to help create the specification.&lt;/p&gt;
&lt;p&gt;It not only missed a substantial number of the project settings I actually needed, but also provided Codex with outdated API references.&lt;/p&gt;
&lt;p&gt;Codex then implemented those instructions.&lt;/p&gt;
&lt;p&gt;The resulting errors caused Unity to enter Safe Mode, and I had to spend additional time and tokens debugging and correcting the implementation.&lt;/p&gt;
&lt;p&gt;This does not mean that using AI to help create specification files is a bad idea. I still do it.&lt;/p&gt;
&lt;p&gt;The lesson I learnt is:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do not use one AI's output as unquestioned technical truth for another AI to implement.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If the AI is filling a gap in your own knowledge, that is precisely when validation becomes most important.&lt;/p&gt;
&lt;p&gt;Proofread what it gives you, question anything that does not look right and, where possible, compare technical requirements against the current official documentation before allowing another AI agent to build from them.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Having code for buttons and text boxes scattered around the project.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Before I standardised my buttons, text boxes and other controls, UI-related code was scattered throughout the project.&lt;/p&gt;
&lt;p&gt;This did not work particularly well.&lt;/p&gt;
&lt;p&gt;If I did not provide Codex with a standard way of creating text boxes, buttons and menus, it would attempt to create its own variations.&lt;/p&gt;
&lt;p&gt;Those variations did not always provide the accessibility behaviour I expected.&lt;/p&gt;
&lt;p&gt;For accessibility, this is particularly problematic. A user should not have to experience different keyboard behaviour simply because three different interfaces were generated at different stages of development.&lt;/p&gt;
&lt;p&gt;I found that it is much better to provide Codex with standardised subsystems that it can reuse rather than expecting it to independently understand your accessibility best practices and reproduce them consistently throughout an entire project.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Changing my model halfway through the project.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Changing my model halfway through the project turned out to be a mistake.&lt;/p&gt;
&lt;p&gt;I switched from GPT-5.6 Sol to GPT-5.6 Lunar because of the potential cost savings.&lt;/p&gt;
&lt;p&gt;However, for the particular work I was doing, I noticed a substantial drop in performance.&lt;/p&gt;
&lt;p&gt;Lunar was not handling the larger project-level task as successfully as Sol. For my workflow, I found it better suited to smaller, more tightly focused tasks than something as substantial as creating an entire accessible asset viewer.&lt;/p&gt;
&lt;p&gt;I ended up using a significant number of additional tokens trying to correct the resulting problems.&lt;/p&gt;
&lt;p&gt;Eventually, I returned to GPT-5.6 Sol to repair the implementation. Parts of the asset viewer had to be substantially rewritten, and I also discovered that some of the accessibility requirements I had defined were no longer being followed consistently.&lt;/p&gt;
&lt;p&gt;The lesson for me was:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The cheapest model per token is not necessarily the cheapest model for the overall task.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If a less expensive model requires several attempts, introduces bugs or requires another model to repair its work, the apparent saving can disappear very quickly.&lt;/p&gt;
&lt;p&gt;Model selection should therefore consider the complexity of the task, not simply the advertised token price.&lt;/p&gt;
&lt;h3 id=&quot;how-to-build-your-own-accessibility-focused-app-or-how-to-modify-an-existing-app-to-be-more-accessible&quot;&gt;How to build your own accessibility-focused app or how to modify an existing app to be more accessible&lt;/h3&gt;
&lt;p&gt;When making an app, if it is intended to be accessibility-focused, it is best to start with accessibility in mind from the beginning.&lt;/p&gt;
&lt;p&gt;There is little point building your entire UI and then discovering that screen readers or other accessibility tools cannot interact with it.&lt;/p&gt;
&lt;p&gt;You are likely to save both tokens and development time by designing accessibility into the application from the start.&lt;/p&gt;
&lt;p&gt;Do your research. Read the latest accessibility guidelines, but also read the documentation for the particular assistive technologies you want your application to support.&lt;/p&gt;
&lt;p&gt;If you are using AI agents, provide them with clear accessibility requirements and best practices in the root &lt;code&gt;AGENTS.md&lt;/code&gt; file for your project.&lt;/p&gt;
&lt;p&gt;Do not simply write:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Make everything accessible.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Define what accessible actually means for your project.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;All menus must be usable entirely with the keyboard and every interactive control must expose enough information for an NVDA user to understand its purpose, current state and available action.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Specific requirements give the AI something that can actually be implemented and tested.&lt;/p&gt;
&lt;p&gt;Before implementing a custom accessibility solution, also investigate what your framework already provides.&lt;/p&gt;
&lt;p&gt;There is little benefit in implementing an entire screen-reader-compatible UI system from scratch if the framework you are using already provides accessible controls that meet your requirements.&lt;/p&gt;
&lt;p&gt;Using existing functionality can save considerable development time and allows you to focus on the places where custom accessibility work is actually necessary.&lt;/p&gt;
&lt;p&gt;The same principle applies to other accessibility features: use the platform or framework's existing accessibility functionality where it is suitable, and build custom solutions where it is not.&lt;/p&gt;
&lt;p&gt;Finally, if you are unsure whether the accessibility features you are implementing actually work for the people you are trying to support, ask them.&lt;/p&gt;
&lt;p&gt;Find a forum, Discord community or other group containing the people your application is intended to serve and ask for feedback.&lt;/p&gt;
&lt;p&gt;Ask what is confusing.&lt;/p&gt;
&lt;p&gt;Ask what their screen reader announces.&lt;/p&gt;
&lt;p&gt;Ask what takes too many keystrokes.&lt;/p&gt;
&lt;p&gt;Ask what they cannot reach at all.&lt;/p&gt;
&lt;p&gt;Most of the time, people will be willing to explain what works, what does not work and what could be improved.&lt;/p&gt;
&lt;p&gt;An AI model can help implement accessibility, but it cannot replace feedback from the people who actually depend on those features.&lt;/p&gt;
&lt;p&gt;For me, one principle has become particularly clear throughout this project:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Do not tell AI to &quot;make it accessible&quot;. Tell it exactly what an accessible user must be able to do.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;contribute-to-the-discussion&quot;&gt;Contribute to the discussion&lt;/h3&gt;
&lt;p&gt;Have you ever used AI to make something more accessible?&lt;/p&gt;
&lt;p&gt;If so, what worked well for you, and what mistakes or unexpected problems did you encounter?&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/27466/using-codex-build-unityaccess-whats-worked-hasnt-building-accessible-applications-with</guid>
<pubDate>Thu, 17 Sep 2026 06:09:52 +0000</pubDate>
</item>
<item>
<title>FludeX v1.1 — Runtime Debug Platform</title>
<link>https://coderlegion.com/18998/fludex-v1-1-runtime-debug-platform</link>
<description>&lt;p&gt;FludeX v1.1 is live. &lt;br&gt;
The Console module is now available — full runtime log access directly in your Unity build, no editor connection required.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=11206750185349211033&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What the Console module includes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Search across all logs&lt;/li&gt;
&lt;li&gt;Filter by log type — errors, warnings, logs&lt;/li&gt;
&lt;li&gt;Resizable stack trace view&lt;/li&gt;
&lt;li&gt;Copy log to clipboard&lt;/li&gt;
&lt;li&gt;Ring buffer storage with configurable capacity and memory usage insight&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Also in this update:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Toast feedback for button actions — surfaces success, failure, and unhandled exceptions automatically&lt;/li&gt;
&lt;li&gt;Void button overloads — Action and Func complete silently unless an exception is thrown&lt;/li&gt;
&lt;li&gt;IConfigurableModule — modules can now expose their own settings view via a settings button in the app bar&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;FludeX is a modular runtime debug platform for Unity built on UIToolkit and AppUI. Available on the Unity Asset Store.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://u3d.as/3TW4&quot;&gt;Asset Store&lt;/a&gt; · &lt;a rel=&quot;nofollow&quot; href=&quot;https://fludex.dev/guide/&quot;&gt;Documentation&lt;/a&gt; · &lt;a rel=&quot;nofollow&quot; href=&quot;https://fludex.dev/demo.html&quot;&gt;WebGL Demo&lt;/a&gt;&lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/18998/fludex-v1-1-runtime-debug-platform</guid>
<pubDate>Tue, 26 May 2026 14:57:19 +0000</pubDate>
</item>
<item>
<title>REBEL HEARTS alpha demo build 0.192 </title>
<link>https://coderlegion.com/12410/rebel-hearts-alpha-demo-build-0-192</link>
<description>&lt;p&gt;alpha demo build 0.1922&lt;/p&gt;
&lt;p&gt;This is a early playable network test for my isometric TacticalRPG concept. I plan on &lt;br&gt;
iterating to build 1.0 implementing any valuable constructive feedback received during this &lt;br&gt;
development cycle. This build is intended for testing connectivity, turn order, and squad &lt;br&gt;
interactions! - gameplay is minimal and unfinished.&lt;/p&gt;
&lt;p&gt;Dir: RebelHearts_demo\Win64bit_build\RHE.exe&lt;br&gt;
Platform: Windows &lt;br&gt;
Resolution: Fixed Fullscreen 1920×1080&lt;br&gt;
Players: 1 to 2 (3 including enemy AI)&lt;/p&gt;
&lt;p&gt;How to Connect &lt;br&gt;
• Host starts the game on Windows and clicks “Host”.  Host shares their public IP with the other player.&lt;br&gt;
• Client launches the game and clicks “Join”, entering the host’s IP.&lt;br&gt;
Additionally ensure your port: 7777 is open and that the firewall allows the prototype. That's it! Now start playing. &lt;/p&gt;
&lt;p&gt;Good to Know'&lt;br&gt;
• Player 1 Host gets priority turn first. Player 2 Remote Client can only observe the current player' actions until &lt;br&gt;
their turn is over &amp;amp; vice versa. &lt;br&gt;
• Turn over is executed only when the current player has selected 'Done' on each of their squad members 'Engange Menu' &lt;br&gt;
options.&lt;br&gt;
• You have 'Move', 'Attack', 'Status' and 'Done' options per squad member.&lt;br&gt;
• You are NOT locked into Attacking or Moving in a particular order. However, when you select one of these two options, &lt;br&gt;
you will be required to follow through with it.&lt;br&gt;
• When ALL opposing player, or yourself have no more squad memebers left, the 'game' is over. You will have to hard quit &lt;br&gt;
for time being (easily enough done).&lt;br&gt;
• Squads are locked into spawning the same stats and equipment for now.&lt;/p&gt;
&lt;p&gt;Conclusion&lt;br&gt;
I'm looking for feedback on your network experience &amp;amp; other thoughts - suggestions!&lt;br&gt;
Please ping me your feedback at any of the below!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Emails are not allowed&lt;/em&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://x.com/wildlogicgames&quot;&gt;https://x.com/wildlogicgames&lt;/a&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://wildlogicgames.itch.io/&quot;&gt;https://wildlogicgames.itch.io/&lt;/a&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.linkedin.com/in/ricky-wild-ab73b067/&quot;&gt;https://www.linkedin.com/in/ricky-wild-ab73b067/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Thanks for play testing - you are a cool person!&lt;/p&gt;
&lt;p&gt;BUGS&lt;/p&gt;
&lt;p&gt;build 0.1922&lt;br&gt;
+Correct squad banner colours applied to Battle UI.&lt;br&gt;
+Defend chance fixed - squad members - if capable of block - will now block on success roll.&lt;br&gt;
+Other small quality of life fixes.&lt;/p&gt;
&lt;p&gt;build 0.1921&lt;br&gt;
+Previous issues fixed. Counter-Attack system re-written.&lt;br&gt;
+Last squad standing is now winner.&lt;br&gt;
-Player 2s view on other squad members sometimes loops during/for movement animations.&lt;br&gt;
-Last Player to kill remaining Enemy AI squad member wins, despite other player squad remaining.&lt;/p&gt;
&lt;p&gt;build 0.191&lt;br&gt;
-Enemy AI Idles after a counter attack from Player Turn Attack. &lt;br&gt;
-Enemy AI Idles after squad member death during counter attack from Enemy AI Turn Attack. &lt;br&gt;
-Player Turn idles due to blocked mouse cursor input, following from Enemy AI Turn. &lt;/p&gt;
&lt;p&gt;build 0.190&lt;br&gt;
-Player 2 Turn hard crashes during counter attack with Enemy AI AND/OR Player 1 Turn.&lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/12410/rebel-hearts-alpha-demo-build-0-192</guid>
<pubDate>Thu, 05 Mar 2026 21:53:08 +0000</pubDate>
</item>
<item>
<title>DevLog 20260122: Some Notes on MAUI, Unity, and Building &quot;Map-Like&quot; App Across Platforms</title>
<link>https://coderlegion.com/10309/devlog-20260122-some-notes-on-maui-unity-and-building-map-like-app-across-platforms</link>
<description>&lt;p&gt;I've been meaning to write about this topic for a while.&lt;/p&gt;
&lt;p&gt;MAUI looks great on paper. In fact, it has looked good on paper for years. Microsoft went a long way through UI and application frameworks: VBA, WinForms, MFC, WPF, Silverlight, UWP, Blazor, and now MAUI. Each iteration promises unification, abstraction, and better productivity over platform differences.&lt;/p&gt;
&lt;p&gt;My first attempt at MAUI felt deceptively easy. I gave up shortly after.&lt;br&gt;
So did the second attempt.&lt;/p&gt;
&lt;p&gt;This time was different: I had a concrete delivery target. Giving up was no longer an option.&lt;/p&gt;
&lt;h4 id=&quot;the-problem-a-map-like-feature&quot;&gt;The Problem: A &quot;Map-Like&quot; Feature&lt;/h4&gt;
&lt;p&gt;The concrete requirement was simple to state but not easy to implement well: an app with a map-like feature. Not a full GIS stack, but something that looks and behaves like a map - large static textures, panning, zooming, overlays, and user interaction. No library - we are going to implement things from ground up.&lt;/p&gt;
&lt;p&gt;My first instinct was to go cross-platform. After years of writing platform-locked GUIs that die the moment requirements change, I had no interest in repeating that mistake.&lt;/p&gt;
&lt;p&gt;After surveying a wide range of options - inside and outside the C# ecosystem - I narrowed the choices down to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unity&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Godot&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MAUI&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I tried Unity first.&lt;/p&gt;
&lt;h4 id=&quot;unity-smooth-onboarding-rough-reality&quot;&gt;Unity: Smooth Onboarding, Rough Reality&lt;/h4&gt;
&lt;p&gt;Unity deserves credit where it's due. It was the first mobile platform I ever used seriously, and I had already developed an Android game with it years ago.&lt;/p&gt;
&lt;p&gt;Coming back with significantly more experience in C#, general software engineering, and game development, the onboarding felt excellent. The editor is mature, the documentation is decent, and the mental model is comprehensible.&lt;/p&gt;
&lt;p&gt;Within about three days, I felt comfortable again - comfortable enough to implement the prototype. The implementation itself was straightforward (details skipped here), but the result was not.&lt;/p&gt;
&lt;p&gt;On an actual Android device, performance was terrible. Given time pressure, I didn't fully chase down the root cause. A few hours of profiling and hypothesis testing later, I made the call to bail. Whether the issue was overdraw, batching, UI layout, or just the wrong API for the task didn't matter anymore - the risk was too high. (Oh, did I mention the build size was gigantic?)&lt;/p&gt;
&lt;p&gt;I would have liked to include some demo code - at least the Unity version - but time didn't allow for it. That will have to wait for another post or a future amendment.&lt;/p&gt;
&lt;h4 id=&quot;maui-dry-and-that-s-a-compliment&quot;&gt;MAUI: Dry, and That's a Compliment&lt;/h4&gt;
&lt;p&gt;Rewriting the same idea in MAUI worked. Not &quot;worked eventually&quot; - it worked immediately and predictably. (Actually I tried Expo before MAUI, which was very smooth, then I looked at the hundreds of dependencies, and quietly reconsidered)&lt;/p&gt;
&lt;p&gt;That forced me to rethink a long-held assumption (something I had from the CG world): engines optimized for real-time rendering &lt;em&gt;should&lt;/em&gt; be good at texture-heavy workloads. In practice, frameworks optimized for application UIs are often better at static or semi-static content - especially when the interaction model looks more like &quot;pan and zoom&quot; than &quot;render 60 FPS no matter what.&quot;&lt;/p&gt;
&lt;p&gt;MAUI was dry. I wasn't excited to see its &quot;mobile-like&quot; layout on a Windows screen, and I still am not.&lt;br&gt;
But dry was exactly what the project needed.&lt;/p&gt;
&lt;h4 id=&quot;the-hidden-cost&quot;&gt;The Hidden Cost&lt;/h4&gt;
&lt;p&gt;That said, this experience didn't magically make me like MAUI - and that reminds me of Blazor.&lt;/p&gt;
&lt;p&gt;The core issue in both cases is structural. These frameworks attempt to abstract over domains whose constraints diverge in important, non-accidental ways. The abstraction holds only as long as the application stays within a relatively narrow envelope of complexity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MAUI Issues&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cross-platform inconsistencies are everywhere, not edge cases.&lt;/li&gt;
&lt;li&gt;iOS AoT compilation and trimming can cause things to silently stop working.&lt;/li&gt;
&lt;li&gt;Many behaviors that &lt;em&gt;should&lt;/em&gt; be easily configurable (for example, disabling the Flyout) require platform-specific code.&lt;/li&gt;
&lt;li&gt;Debugging failures caused by trimming or linker behavior is disproportionately painful.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Blazor Issues&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Refactoring is far harder than it should be.&lt;/li&gt;
&lt;li&gt;Large component trees quickly become rigid.&lt;/li&gt;
&lt;li&gt;Abstractions that feel elegant early on tend to resist change later.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In both cases, the abstraction breaks - and when it does, you're often forced to drop down into platform-specific or framework-specific escape hatches that defeat the original promise.&lt;/p&gt;
&lt;p&gt;These frameworks scale poorly in complexity, not because they are badly designed, but because they attempt to simplify domains that fundamentally resist unification. (Well, honestly in the case of MAUI I do think there are some design issues)&lt;/p&gt;
&lt;p&gt;In general, MAUI is slightly better, because it's at least well encapsulated - just write platform-specific codes.&lt;/p&gt;
&lt;h4 id=&quot;some-takeaways&quot;&gt;Some Takeaways&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Game engines are not automatically good UI frameworks. Application frameworks may outperform engines for static, interaction-heavy visuals. In this particular case I haven't tried Godot, but I suspect the same issue wouldn't happen to Godot.&lt;/li&gt;
&lt;li&gt;&quot;Write once, run anywhere&quot; really means &quot;debug everywhere.&quot; And don't expect MAUI can save you effort because platform-specific behaviors are everywhere and it took me lots of time to back trace which seemingly trivial change many commits ago caused the entire application to break; Or, just turn off the magic &lt;code&gt;MtouchUseLlvm&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;MAUI is an OK choice for simple cross-platform mobile apps in C#.&lt;/li&gt;
&lt;li&gt;Unified frameworks seem to trade short-term velocity for long-term friction. In the perfect world, I will use Swift for iOS. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In general, I wish framework developers make it clear their limitations so  decision making can be made upfront.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/10309/devlog-20260122-some-notes-on-maui-unity-and-building-map-like-app-across-platforms</guid>
<pubDate>Fri, 23 Jan 2026 03:06:32 +0000</pubDate>
</item>
<item>
<title>Solo Creation: Games and the Psychology Behind Them</title>
<link>https://coderlegion.com/9808/solo-creation-games-and-the-psychology-behind-them</link>
<description>&lt;p&gt;Hi, I'm Lucas from Poland :) I work primarily as a solo creator.&lt;br&gt;
Most people know me from the technical side - building games, systems, prototypes, and shipping projects on my own.&lt;/p&gt;
&lt;p&gt;But over the years, I’ve become just as interested in the psychological side of solo creation.&lt;/p&gt;
&lt;p&gt;What happens when you’re alone with decisions for too long?&lt;br&gt;
How motivation changes after the initial excitement fades?&lt;br&gt;
Why some projects slowly die - not because of lack of skill, but because of mental friction, fatigue, or loss of meaning?&lt;/p&gt;
&lt;p&gt;Solo game development isn’t just about tools and code. It’s a long-term mental process: identity, resilience, energy, doubt, and learning how to stay in the game long enough to finish something.&lt;/p&gt;
&lt;p&gt;These questions now influence how I build games, how I structure my work, and how I think about creative sustainability.&lt;/p&gt;
&lt;p&gt;I’m still making games solo. I’m just paying more attention to what’s happening inside the creator, not only inside the project.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/9808/solo-creation-games-and-the-psychology-behind-them</guid>
<pubDate>Fri, 16 Jan 2026 08:56:00 +0000</pubDate>
</item>
<item>
<title>FIGHT NIGHT ANNOUNCEMENT: The Lightweight Challenger vs. The Heavyweight Champ</title>
<link>https://coderlegion.com/8147/fight-night-announcement-the-lightweight-challenger-vs-the-heavyweight-champ</link>
<description>&lt;p&gt;&lt;strong&gt;In the Red Corner:&lt;/strong&gt; Weighing in with a massive learning curve and complex boilerplate... the reigning champion of performance: &lt;strong&gt;Unity ECS (DOTS)&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In the Blue Corner:&lt;/strong&gt; Weighing in at a lean &lt;strong&gt;45kb&lt;/strong&gt;... the Object-Oriented underdog: &lt;strong&gt;FSM_API&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;We are preparing for the ultimate showdown.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;THE ROAD TO THE TITLE FIGHT:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Before we step into the Unity Ring for the visual bout, we had to prove the challenger could take a punch. We put the FSM_API through &quot;The Gauntlet&quot;—a raw, Console-Only C# simulation involving &lt;strong&gt;66,000 active agents&lt;/strong&gt; (&quot;Quick Brown Foxes&quot; vs. &quot;Lazy Sleeping Dogs&quot;).&lt;/p&gt;
&lt;p&gt;The results were bloody. The performance was undeniable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;THE TALE OF THE TAPE (The Articles):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Round 1: The Massacre (Benchmarks)&lt;/strong&gt;&lt;br&gt;
See the breakdown of the &quot;Silent Hordes&quot; simulation where we maintained a stable 30 FPS under massive idle load.&lt;br&gt;
 &lt;strong&gt;Read the Benchmark:&lt;/strong&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/8009/the-quick-brown-fox-2-the-silent-hordes&quot;&gt;https://coderlegion.com/8009/the-quick-brown-fox-2-the-silent-hordes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Round 2: The Training Camp (Optimization Deep Dive)&lt;/strong&gt;&lt;br&gt;
A true fighter knows their weaknesses. In this second technical breakdown, I expose the raw memory profiles. I’m embarrassed to admit how much optimization headroom is &lt;em&gt;still left&lt;/em&gt; on the table—which is terrifying, because even unoptimized, our extrinsic benchmarks are putting us in contention with the Champ (ECS).&lt;br&gt;
 &lt;strong&gt;See the Optimization Data:&lt;/strong&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://coderlegion.com/7988/the-control-group-benchmarking-the-dirty-version-of-my-fsm-api&quot;&gt;https://coderlegion.com/7988/the-control-group-benchmarking-the-dirty-version-of-my-fsm-api&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;COMING SOON: THE MAIN EVENT&lt;/strong&gt; &lt;br&gt;
Stay tuned for our next article, where we bring the carnage into the Unity Scene View.&lt;/p&gt;
&lt;p&gt;Will the lightweight 45kb DLL show &lt;strong&gt;its&lt;/strong&gt; raw digital power? Or will the heavyweight bloat of ECS deliver yet another TKO?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Get to know the Challenger before the bell rings:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;Asset Store ($30):&lt;/strong&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://assetstore.unity.com/packages/tools/behavior-ai/the-singularity-workshop-fsm-api-advanced-332450&quot;&gt;https://assetstore.unity.com/packages/tools/behavior-ai/the-singularity-workshop-fsm-api-advanced-332450&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;GitHub (Free):&lt;/strong&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/TrentBest/FSM_API&quot;&gt;https://github.com/TrentBest/FSM_API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;Coach's Advice:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;&quot;Don't step into the ring without the right gear, kid. Grab the package. It's on the house.&quot;&lt;/em&gt;&lt;br&gt;
 &lt;strong&gt;NuGet (Free):&lt;/strong&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API/#supportedframeworks-body-tab&quot;&gt;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API/#supportedframeworks-body-tab&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Support Our Work:&lt;/p&gt;
&lt;p&gt;Patreon Page:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.patreon.com/c/TheSingularityWorkshop&quot;&gt;https://www.patreon.com/c/TheSingularityWorkshop&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; Support Us (PayPal Donation):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J&quot;&gt;https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=4793565784457015839&quot; alt=&quot;A Hyper-Detailed, Architecturally Impossible Synthesis of Consciousness and Digital Matter. The image is a frenetic, deeply complex digital vista where a central Luminous Eye dominates a vast, glowing circuit landscape. This eye, suspended mid-air, is a sphere of intense, fractal energy—a pulsating vortex of pink, violet, and electric blue light—that powerfully suggests an emergence of digital consciousness or a Technological Singularity itself. The core is a bottomless black aperture, ringed by a white-hot plasma disc. Below this ocular energy source, the light dissipates into an intricate, copper-gold and neon-blue Circuit Board Megastructure that stretches to the horizon, impossibly dense with exaggerated microchips, glowing resistor arrays, and power conduits that form deep, glowing canyons. The background is a dark, holographic projection field displaying complex schematics, mathematical models, and flowing data streams, reinforcing the theme of Absolute Digital Engineering. The entire scene is bathed in a dramatic, opposing light source—a warm, orange-gold glow from the left and an ice-cold, electric-blue glow from the right—creating a maximalist, high-contrast visual experience that definitively rejects the minimalist simplicity of conventional design and announces: Technology is intricate, overwhelming, and infinitely complex.&quot;&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/8147/fight-night-announcement-the-lightweight-challenger-vs-the-heavyweight-champ</guid>
<pubDate>Wed, 03 Dec 2025 23:20:00 +0000</pubDate>
</item>
<item>
<title>The Blender ↔ Unity Axis &amp; Scale Problem: A Complete Technical Guide</title>
<link>https://coderlegion.com/8146/the-blender-unity-axis-scale-problem-a-complete-technical-guide</link>
<description>&lt;h2 id=&quot;the-blender-unity-axis-amp-scale-problem-a-complete-technical-guide&quot;&gt;The Blender ↔ Unity Axis &amp;amp; Scale Problem: A Complete Technical Guide&lt;/h2&gt;
&lt;p&gt;(and How Unit &amp;amp; Scale Doctor Pro Solves It Reliably)&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;1-introduction-the-silent-production-killer&quot;&gt;&lt;strong&gt;1. Introduction — The Silent Production Killer&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Every 3D developer eventually encounters the classic trap:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;“It looked correct in Blender… but Unity imported it wrong.”&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Rotations are flipped.&lt;/li&gt;
&lt;li&gt;Objects appear microscopic or gigantic.&lt;/li&gt;
&lt;li&gt;Animations distort.&lt;/li&gt;
&lt;li&gt;Rig orientations break.&lt;/li&gt;
&lt;li&gt;Prefabs drift or rotate 90°.&lt;/li&gt;
&lt;li&gt;Root bones flip forward.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is not user error—it’s the unavoidable result of &lt;strong&gt;two unrelated coordinate systems colliding&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Unity and Blender simply do not speak the same native “3D language.”&lt;/p&gt;
&lt;p&gt;This article is a deep dive into:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Why scale &amp;amp; axis mismatches occur&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The real mathematical and pipeline causes&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Why attempting to ‘just apply transforms’ is unreliable&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How to manually fix models in a production-safe, deterministic way&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How to automate everything with Unit &amp;amp; Scale Doctor Pro&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you build technical art pipelines, maintain game studios' asset workflows, or run multi-DCC pipelines, this is essential knowledge.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;2-the-root-cause-two-worlds-two-coordinate-systems&quot;&gt;&lt;strong&gt;2. The Root Cause — Two Worlds, Two Coordinate Systems&lt;/strong&gt;&lt;/h3&gt;
&lt;h4 id=&quot;blender-uses-&quot;&gt;&lt;strong&gt;Blender uses:&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unit&lt;/strong&gt;: &lt;em&gt;Meters&lt;/em&gt; by default, but functionally unitless&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Axis&lt;/strong&gt;: +Z &lt;strong&gt;up&lt;/strong&gt;, +Y &lt;strong&gt;forward&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Object default scale&lt;/strong&gt;: (1,1,1)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;unity-uses-&quot;&gt;&lt;strong&gt;Unity uses:&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unit&lt;/strong&gt;: &lt;em&gt;Meters&lt;/em&gt; but 1 Blender meter ≠ 1 Unity meter without context&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Axis&lt;/strong&gt;: +Y &lt;strong&gt;up&lt;/strong&gt;, +Z &lt;strong&gt;forward&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FBX importer behavior&lt;/strong&gt;: secretly compensates, inconsistently&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;the-fundamental-conflict&quot;&gt;&lt;strong&gt;The Fundamental Conflict&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Blender’s &lt;em&gt;Z-up&lt;/em&gt; means the “world up” vector is different.&lt;br&gt;
Unity’s &lt;em&gt;Y-up&lt;/em&gt; means the “world up” vector is different.&lt;/p&gt;
&lt;p&gt;This leads to the classic &lt;strong&gt;90° rotation offset&lt;/strong&gt;, often around X or sometimes Z, depending on export settings.&lt;/p&gt;
&lt;p&gt;The scale mismatch is even worse:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Blender’s &lt;em&gt;grid scale&lt;/em&gt; ≠ the FBX exporter’s &lt;em&gt;unit scale&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Unity’s FBX importer applies hidden conversions&lt;/li&gt;
&lt;li&gt;Blender’s “Apply Scale” resets object-level scaling but alters animation meaning&lt;/li&gt;
&lt;li&gt;Armatures store rest pose matrices relative to Blender’s coordinate system&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;If you think this sounds messy—you’re correct.&lt;/strong&gt;&lt;br&gt;
And every studio spends hundreds of hours per year fighting it.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;3-the-axis-dichotomy-why-objects-rotate-wrong&quot;&gt;&lt;strong&gt;3. The Axis Dichotomy — Why Objects Rotate Wrong&lt;/strong&gt;&lt;/h3&gt;
&lt;h4 id=&quot;case-1-blender-to-unity-rotation&quot;&gt;Case 1: Blender to Unity Rotation&lt;/h4&gt;
&lt;p&gt;Blender’s +Y forward is Unity’s +Z forward.&lt;/p&gt;
&lt;p&gt;Converting between the two requires:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Rotation = Rotate -90° around X
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But this is &lt;em&gt;only&lt;/em&gt; correct for static meshes.&lt;/p&gt;
&lt;p&gt;For rigs, bones, animation curves, constraints, and IK solvers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The armature object must rotate&lt;/li&gt;
&lt;li&gt;Every bone’s roll must be corrected&lt;/li&gt;
&lt;li&gt;Animation keyframes must be reinterpreted&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you simply “apply” the rotation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IK chains break&lt;/li&gt;
&lt;li&gt;Pose orientation becomes invalid&lt;/li&gt;
&lt;li&gt;Animation curves produce different results&lt;/li&gt;
&lt;li&gt;Bone roll becomes inconsistent (critical for weapons, fingers, mechanical rigs)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is why the internet is full of contradictory advice—&lt;br&gt;
&lt;strong&gt;because most of it works for simple meshes, but destroys complex rigs.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;4-the-scale-dichotomy-why-objects-import-too-small-or-too-large&quot;&gt;&lt;strong&gt;4. The Scale Dichotomy — Why Objects Import Too Small or Too Large&lt;/strong&gt;&lt;/h3&gt;
&lt;h4 id=&quot;key-misconception-&quot;&gt;Key misconception:&lt;/h4&gt;
&lt;blockquote&gt;&lt;p&gt;“Blender units = meters = Unity meters.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is only &lt;em&gt;theoretically&lt;/em&gt; true.&lt;/p&gt;
&lt;p&gt;Here’s the reality:&lt;/p&gt;
&lt;h4 id=&quot;blender-s-exporters&quot;&gt;&lt;strong&gt;Blender's Exporters&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;FBX exporter has hidden unit scaling&lt;/li&gt;
&lt;li&gt;glTF uses meters but assumes Z-up needs conversion&lt;/li&gt;
&lt;li&gt;OBJ has no unit semantics&lt;/li&gt;
&lt;li&gt;CAD imports often come in cm/mm&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;unity-s-importers&quot;&gt;&lt;strong&gt;Unity’s Importers&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;FBX importer has a &lt;em&gt;Scale Factor&lt;/em&gt; (sometimes 0.01)&lt;/li&gt;
&lt;li&gt;Legacy FBX workflows still assume Maya’s centimeter world&lt;/li&gt;
&lt;li&gt;glTF importer assumes meters&lt;/li&gt;
&lt;li&gt;CAD importers assume millimeters&lt;/li&gt;
&lt;li&gt;Custom pipelines override scale silently&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In practice, you see:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Assets 100× too small&lt;/li&gt;
&lt;li&gt;Assets 1/100th expected size&lt;/li&gt;
&lt;li&gt;Rigs where animation offsets are scaled differently&lt;/li&gt;
&lt;li&gt;Physics collider mismatches&lt;/li&gt;
&lt;li&gt;Prefabs with broken child offsets&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Scaling is not universal.&lt;br&gt;
Scaling is &lt;strong&gt;hierarchical&lt;/strong&gt;, &lt;strong&gt;order-dependent&lt;/strong&gt;, and &lt;strong&gt;context-dependent&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;“Apply Scale (Ctrl+A)” solves nearly nothing reliably across a full production pipeline.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;5-why-apply-all-transforms-is-a-pipeline-trap&quot;&gt;&lt;strong&gt;5. Why &quot;Apply All Transforms&quot; Is a Pipeline Trap&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Applying rotation &amp;amp; scale at the object level seems tempting—but it is destructive:&lt;/p&gt;
&lt;h4 id=&quot;it-breaks-&quot;&gt;It breaks:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Animation tracks&lt;/li&gt;
&lt;li&gt;Rig rest pose data&lt;/li&gt;
&lt;li&gt;IK constraints&lt;/li&gt;
&lt;li&gt;Bone hierarchy matrices&lt;/li&gt;
&lt;li&gt;Driver-based rigs&lt;/li&gt;
&lt;li&gt;Constraints that assume world vs local transforms&lt;/li&gt;
&lt;li&gt;Any rig authored for Blender’s Z-up world&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Studios often apply transforms to fix one asset, but create inconsistencies with others.&lt;/p&gt;
&lt;p&gt;This leads to &lt;strong&gt;asset drift&lt;/strong&gt;, where each mesh slowly becomes different from others in the pipeline.&lt;/p&gt;
&lt;p&gt;This is how productions collapse under their own asset inconsistency.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;6-the-correct-manual-approach-if-you-must-do-it-manually-&quot;&gt;&lt;strong&gt;6. The Correct Manual Approach (If You Must Do It Manually)&lt;/strong&gt;&lt;/h3&gt;
&lt;h4 id=&quot;step-1-choose-a-pipeline-convention&quot;&gt;Step 1 — Choose a Pipeline Convention&lt;/h4&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unity&lt;/strong&gt;: Y-up, meters, 1:1 scale&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unity (Maya-style)&lt;/strong&gt;: centimeters, 0.01 scale&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;glTF&lt;/strong&gt;: meters, Z-up → Y-up conversion&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;step-2-standardize-blender-scene&quot;&gt;Step 2 — Standardize Blender Scene&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;World's unit scale&lt;/li&gt;
&lt;li&gt;Scene orientation&lt;/li&gt;
&lt;li&gt;Grid scale&lt;/li&gt;
&lt;li&gt;Import scale adjustments&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;step-3-fix-object-transforms-without-breaking-rigs&quot;&gt;Step 3 — Fix Object Transforms Without Breaking Rigs&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Convert orientation using &lt;em&gt;matrix math&lt;/em&gt;, not rotations&lt;/li&gt;
&lt;li&gt;Rebuild bone rolls in correct order&lt;/li&gt;
&lt;li&gt;Resample animation curves&lt;/li&gt;
&lt;li&gt;Normalize scale hierarchies&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;step-4-validate&quot;&gt;Step 4 — Validate&lt;/h4&gt;
&lt;p&gt;Every object must be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scale: &lt;code&gt;(1,1,1)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Rotation: correct forward/up axes&lt;/li&gt;
&lt;li&gt;Location: zeroed or pipeline-safe&lt;/li&gt;
&lt;li&gt;Bone rest pose: consistent&lt;/li&gt;
&lt;li&gt;Animations: stable after conversion&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is why studios use specialized tools—&lt;br&gt;
because doing this manually for hundreds of assets is not feasible.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;7-why-you-need-an-automated-system-not-a-manual-workflow-&quot;&gt;&lt;strong&gt;7. Why You Need an Automated System (Not a Manual Workflow)&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A studio pipeline must guarantee:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every asset is export-safe&lt;/li&gt;
&lt;li&gt;Every file uses identical conventions&lt;/li&gt;
&lt;li&gt;Transforms are mathematically correct&lt;/li&gt;
&lt;li&gt;Rigs are preserved&lt;/li&gt;
&lt;li&gt;No artist “accidentally breaks scale”&lt;/li&gt;
&lt;li&gt;No asset slowly deviates from conventions over time&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is the reason tools like &lt;strong&gt;Unit &amp;amp; Scale Doctor Pro&lt;/strong&gt; exist—&lt;br&gt;
to solve a problem that is mathematically deterministic but tedious and error-prone for humans.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;8-unit-amp-scale-doctor-pro-what-it-actually-does&quot;&gt;&lt;strong&gt;8. Unit &amp;amp; Scale Doctor Pro — What It Actually Does&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=17114841354550508258&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Based on the README and source files in your package, the tool provides:&lt;/p&gt;
&lt;h4 id=&quot;-multi-engine-profile-system&quot;&gt;✔ &lt;strong&gt;Multi-Engine Profile System&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Switch an entire Blender scene to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unity (meters / centimeters / millimeters workflows)&lt;/li&gt;
&lt;li&gt;Unreal&lt;/li&gt;
&lt;li&gt;glTF&lt;/li&gt;
&lt;li&gt;CAD pipelines&lt;/li&gt;
&lt;li&gt;Custom studio conventions&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;-object-mesh-and-armature-correction&quot;&gt;✔ &lt;strong&gt;Object, Mesh, and Armature Correction&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;It rewrites:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Object matrices&lt;/li&gt;
&lt;li&gt;Mesh local → world conversions&lt;/li&gt;
&lt;li&gt;Armature rest pose matrices&lt;/li&gt;
&lt;li&gt;Bone roll normalization&lt;/li&gt;
&lt;li&gt;Animation data curve remapping&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;-non-destructive-fixing&quot;&gt;✔ &lt;strong&gt;Non-Destructive Fixing&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;The tool ensures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No rig is lost&lt;/li&gt;
&lt;li&gt;No animation is destroyed&lt;/li&gt;
&lt;li&gt;No mesh is warped&lt;/li&gt;
&lt;li&gt;No parenting hierarchy breaks&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;-a-full-validation-system&quot;&gt;✔ &lt;strong&gt;A Full Validation System&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;It detects inconsistencies such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Wrong scale&lt;/li&gt;
&lt;li&gt;Hidden object scale offsets&lt;/li&gt;
&lt;li&gt;Negative scaling&lt;/li&gt;
&lt;li&gt;Axis flips&lt;/li&gt;
&lt;li&gt;Bone roll inconsistencies&lt;/li&gt;
&lt;li&gt;Meshes containing multiple transform spaces&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;-one-click-scene-standardization&quot;&gt;✔ &lt;strong&gt;One-Click Scene Standardization&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;A complete “reset” that makes the entire project engine-ready.&lt;/p&gt;
&lt;p&gt;This is exactly what large studios build internally—&lt;br&gt;
but you have it packaged and production-ready.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;9-how-it-fixes-everything-automatically&quot;&gt;&lt;strong&gt;9. How It Fixes Everything Automatically&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Here’s what a typical Unit &amp;amp; Scale Doctor Pro pipeline does under the hood:&lt;/p&gt;
&lt;h4 id=&quot;step-a-scene-fingerprinting&quot;&gt;Step A — Scene Fingerprinting&lt;/h4&gt;
&lt;p&gt;It scans every object:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Type&lt;/li&gt;
&lt;li&gt;Transform&lt;/li&gt;
&lt;li&gt;Parent hierarchy&lt;/li&gt;
&lt;li&gt;Mesh data&lt;/li&gt;
&lt;li&gt;Armature bind poses&lt;/li&gt;
&lt;li&gt;Animation data&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;step-b-determine-required-conversions&quot;&gt;Step B — Determine Required Conversions&lt;/h4&gt;
&lt;p&gt;Using the selected &lt;em&gt;profile&lt;/em&gt;, it derives:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Required world up axis&lt;/li&gt;
&lt;li&gt;Forward direction&lt;/li&gt;
&lt;li&gt;Unit scale multiplier&lt;/li&gt;
&lt;li&gt;Mesh shrinkwrap conversions&lt;/li&gt;
&lt;li&gt;Armature remapping rules&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;step-c-apply-matrix-level-transform-fixes&quot;&gt;Step C — Apply Matrix-Level Transform Fixes&lt;/h4&gt;
&lt;p&gt;It rewrites transforms directly in matrix form:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;M_corrected = ConversionMatrix * M_original
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This preserves:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bone rest pose&lt;/li&gt;
&lt;li&gt;Animation curves&lt;/li&gt;
&lt;li&gt;Rig constraints&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;step-d-clean-bake-normalize&quot;&gt;Step D — Clean / Bake / Normalize&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Zero object scales&lt;/li&gt;
&lt;li&gt;Fix bone rolls deterministically&lt;/li&gt;
&lt;li&gt;Rebuild animation curves&lt;/li&gt;
&lt;li&gt;Validate length units&lt;/li&gt;
&lt;li&gt;Normalize mesh normals&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;step-e-pipeline-safe-export&quot;&gt;Step E — Pipeline Safe Export&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;FBX-safe rotation&lt;/li&gt;
&lt;li&gt;glTF-safe unit scale&lt;/li&gt;
&lt;li&gt;Unity-ready hierarchy&lt;/li&gt;
&lt;li&gt;Unreal-ready orientation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The entire process becomes deterministic and repeatable.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;10-practical-example-blender-to-unity-correct-workflow-&quot;&gt;&lt;strong&gt;10. Practical Example — Blender to Unity (Correct Workflow)&lt;/strong&gt;&lt;/h3&gt;
&lt;h4 id=&quot;without-unit-amp-scale-doctor-pro&quot;&gt;&lt;strong&gt;Without Unit &amp;amp; Scale Doctor Pro&lt;/strong&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Export FBX&lt;/li&gt;
&lt;li&gt;Import into Unity&lt;/li&gt;
&lt;li&gt;Fix rotation manually&lt;/li&gt;
&lt;li&gt;Fix scale manually&lt;/li&gt;
&lt;li&gt;Fix animation drift&lt;/li&gt;
&lt;li&gt;Fix rig orientations&lt;/li&gt;
&lt;li&gt;Re-export when something breaks&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Every asset becomes a small crisis.&lt;/p&gt;
&lt;h4 id=&quot;with-unit-amp-scale-doctor-pro&quot;&gt;&lt;strong&gt;With Unit &amp;amp; Scale Doctor Pro&lt;/strong&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Choose &lt;strong&gt;Unity&lt;/strong&gt; profile&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Fix Scene&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Export FBX normally&lt;/li&gt;
&lt;li&gt;Import into Unity and it “just works”&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This eliminates rotational offsets, scale mismatches, and animation distortions.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;11-receipts-for-technical-artists-why-this-matters&quot;&gt;&lt;strong&gt;11. Receipts for Technical Artists — Why This Matters&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A good TA knows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scale drift kills animation pipelines&lt;/li&gt;
&lt;li&gt;Hand-authored fixes destroy determinism&lt;/li&gt;
&lt;li&gt;Rig rest poses must be mathematically preserved&lt;/li&gt;
&lt;li&gt;Axis conversion is &lt;em&gt;matrix math&lt;/em&gt;, not rotation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unit &amp;amp; Scale Doctor Pro fills the gap Blender never will:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A consistent, safe, automated transformation pipeline.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;12-conclusion-the-right-way-to-handle-axis-amp-scale-forever&quot;&gt;&lt;strong&gt;12. Conclusion — The Right Way to Handle Axis &amp;amp; Scale Forever&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The Blender ↔ Unity scale/axis mismatch is unavoidable.&lt;br&gt;
But the chaos surrounding it is optional.&lt;/p&gt;
&lt;h4 id=&quot;at-a-high-level-&quot;&gt;At a high level:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Blender uses Z-up&lt;/li&gt;
&lt;li&gt;Unity uses Y-up&lt;/li&gt;
&lt;li&gt;Scale semantics are inconsistent&lt;/li&gt;
&lt;li&gt;Animations and rigs magnify errors&lt;/li&gt;
&lt;li&gt;Manual fixes are destructive&lt;/li&gt;
&lt;li&gt;Studio pipelines require determinism&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;the-fix-&quot;&gt;The fix:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Understand the math&lt;/li&gt;
&lt;li&gt;Fix transforms non-destructively&lt;/li&gt;
&lt;li&gt;Use deterministic conversion methods&lt;/li&gt;
&lt;li&gt;Rely on a tool built specifically for this problem&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is exactly what &lt;strong&gt;Unit &amp;amp; Scale Doctor Pro&lt;/strong&gt; provides:&lt;br&gt;
A complete, automated, studio-safe solution to a 20-year-old industry headache.&lt;/p&gt;
&lt;p&gt;Get it on Superhive Marketplace via this link: &lt;a rel=&quot;nofollow&quot; href=&quot;https://superhivemarket.com/products/unit--scale-doctor&quot;&gt;https://superhivemarket.com/products/unit--scale-doctor&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
</description>
<category>Automation Tools</category>
<guid isPermaLink="true">https://coderlegion.com/8146/the-blender-unity-axis-scale-problem-a-complete-technical-guide</guid>
<pubDate>Wed, 03 Dec 2025 21:45:56 +0000</pubDate>
</item>
<item>
<title>FSM API (Advanced) for Unity</title>
<link>https://coderlegion.com/6922/fsm-api-advanced-for-unity</link>
<description>&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=17047300794443488665&quot; alt=&quot;The Advanced Integration's Unity Package Cover Image with confetti and streamers bursting in celebration!&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Singularity Workshop is proud to announce a pivotal achievement: After months of rigorous architectural design and engineering, we have successfully released &lt;strong&gt;'The Singularity Workshop - FSM API (Advanced)'&lt;/strong&gt; on the Unity Asset Store! This is a successful milestone, and we are just getting started.&lt;/p&gt;
&lt;p&gt;As dedicated readers of our work know, our focus is on robust software architecture, grounded in the deep theoretical understanding and powerful application of &lt;strong&gt;Finite State Machines (FSMs)&lt;/strong&gt;. This Unity Asset is the direct culmination of those efforts.&lt;/p&gt;
&lt;h4 id=&quot;the-paradigm-shift-is-here&quot;&gt;The Paradigm Shift is Here&lt;/h4&gt;
&lt;p&gt;Get ready to escape the chaos of &lt;strong&gt;&lt;code&gt;Update()&lt;/code&gt; spaghetti&lt;/strong&gt; and embrace a true &lt;strong&gt;architectural paradigm shift&lt;/strong&gt;. Our API is engineered for &lt;strong&gt;decoupling&lt;/strong&gt; and &lt;strong&gt;high reusability&lt;/strong&gt;, allowing you to build complex behavior through the &lt;em&gt;composition&lt;/em&gt; of simple, independent FSM blueprints.&lt;/p&gt;
&lt;p&gt;As demonstrated in our work on &lt;strong&gt;Multi-Context FSMs&lt;/strong&gt;, you can now apply multiple, independent FSMs to a single object's &lt;code&gt;Transform&lt;/code&gt; simultaneously without interference, resulting in game systems that are &lt;strong&gt;scalable, maintainable, and profoundly robust.&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;documentation-as-a-core-feature&quot;&gt;Documentation as a Core Feature&lt;/h4&gt;
&lt;p&gt;We engineered this API to be universally accessible, spending as much time on &lt;strong&gt;learning materials&lt;/strong&gt; as we did on the code itself. Our goal is to bring &lt;strong&gt;non-coders&lt;/strong&gt; and &lt;strong&gt;non-C# programmers&lt;/strong&gt; into this new paradigm.&lt;/p&gt;
&lt;p&gt;Beyond the comprehensive user guide, you can check out our &lt;strong&gt;NuGet package&lt;/strong&gt; which contains the core API and an extensive &lt;strong&gt;Theory Guide&lt;/strong&gt; that dives deep into:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The fundamental &lt;strong&gt;mathematical models&lt;/strong&gt; behind FSMs.&lt;/li&gt;
&lt;li&gt;FSM types, classifications, and operational theory.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once you understand the &quot;What,&quot; our API documentation walks you through the &quot;How,&quot; making the process of creating complex behavior accessible to anyone willing to learn the abstraction.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Explore the future of Unity behavior architecture today ($30 package on sale for $21 for two weeks on the Unity Asset Store!):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://assetstore.unity.com/packages/slug/332450&quot;&gt;The Singularity Workshop - FSM API (Advanced)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reference the Core Engine &amp;amp; Theory Guides:&lt;/strong&gt;&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API&quot;&gt;TheSingularityWorkshop.FSM_API NuGet Package&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The paradigm shift is here. We look forward to publishing deep dives into the API's advanced architecture and applications very soon!&lt;/p&gt;
&lt;p&gt; Support Us (PayPal Donation):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J&quot;&gt;https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We'd love to hear your thoughts! Please Like this post, Love the code, and Share your feedback in the comments.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=12370772205691327121&quot; alt=&quot;A Hyper-Detailed, Architecturally Impossible Synthesis of Consciousness and Digital Matter. The image is a frenetic, deeply complex digital vista where a central Luminous Eye dominates a vast, glowing circuit landscape. This eye, suspended mid-air, is a sphere of intense, fractal energy—a pulsating vortex of pink, violet, and electric blue light—that powerfully suggests an emergence of digital consciousness or a Technological Singularity itself. The core is a bottomless black aperture, ringed by a white-hot plasma disc. Below this ocular energy source, the light dissipates into an intricate, copper-gold and neon-blue Circuit Board Megastructure that stretches to the horizon, impossibly dense with exaggerated microchips, glowing resistor arrays, and power conduits that form deep, glowing canyons. The background is a dark, holographic projection field displaying complex schematics, mathematical models, and flowing data streams, reinforcing the theme of Absolute Digital Engineering. The entire scene is bathed in a dramatic, opposing light source—a warm, orange-gold glow from the left and an ice-cold, electric-blue glow from the right—creating a maximalist, high-contrast visual experience that definitively rejects the minimalist simplicity of conventional design and announces: Technology is intricate, overwhelming, and infinitely complex.&quot;&gt;&lt;/p&gt;
</description>
<category>Game Dev</category>
<guid isPermaLink="true">https://coderlegion.com/6922/fsm-api-advanced-for-unity</guid>
<pubDate>Mon, 27 Oct 2025 20:56:19 +0000</pubDate>
</item>
<item>
<title>The FSM Agent Architecture: Scaling NavMesh Agents with Decoupled Logic </title>
<link>https://coderlegion.com/6495/the-fsm-agent-architecture-scaling-navmesh-agents-with-decoupled-logic</link>
<description>&lt;h3 id=&quot;the-fsm-agent-architecture-scaling-navmesh-agents-with-decoupled-logic&quot;&gt;The FSM Agent Architecture: Scaling NavMesh Agents with Decoupled Logic&lt;/h3&gt;
&lt;p&gt;We've mastered simple oscillating motion with the &lt;strong&gt;FSM Context Pattern&lt;/strong&gt;; now, we apply this powerful architectural approach to a far greater challenge: &lt;strong&gt;Massive NavMesh Agent AI&lt;/strong&gt;. Instead of relying on a monolithic &lt;code&gt;Update()&lt;/code&gt; loop, we delegate the complex logic of pathfinding, target acquisition, and state management into reusable Finite State Machine blueprints.&lt;/p&gt;
&lt;p&gt;Our goal for this series is twofold: achieve &lt;strong&gt;stable, high-performance&lt;/strong&gt; AI for hundreds of agents, and develop a system resilient to complex &lt;strong&gt;emergent behaviors&lt;/strong&gt; that inevitably arise at scale.&lt;/p&gt;
&lt;p&gt;This article introduces the two core components that make up our scalable agent system.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=7529296879811900778&quot; alt=&quot;Screen Capture with 1k agents&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-two-pillars-of-the-fsm-agent-system&quot;&gt;The Two Pillars of the FSM Agent System&lt;/h3&gt;
&lt;p&gt;Our architecture separates the agents from the environment, ensuring each component is only responsible for its own domain, which is the key to reusability and stability.&lt;/p&gt;
&lt;h4 id=&quot;1-the-environment-navmeshagentsdemo-cs-the-orchestrator-&quot;&gt;1. The Environment: &lt;code&gt;NavMeshAgentsDemo.cs&lt;/code&gt; (The Orchestrator)&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;NavMeshAgentsDemo&lt;/code&gt; class serves as the &lt;strong&gt;central context&lt;/strong&gt; for the entire simulation. Its primary responsibility is orchestration and resource distribution.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Target Management:&lt;/strong&gt; It holds the list of &lt;strong&gt;targets&lt;/strong&gt; (&lt;code&gt;targets&lt;/code&gt; list) that agents will navigate to. It includes a helper function, &lt;code&gt;GetRandomTarget&lt;/code&gt;, which ensures agents don't immediately re-select the target they just left, promoting better distribution.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Initialization:&lt;/strong&gt; In the main FSM's &lt;code&gt;OnEnterExecuting&lt;/code&gt; state, the demo dynamically creates our agents. It instantiates the &lt;code&gt;agentPrefab&lt;/code&gt;, assigns the environment reference (&lt;code&gt;agentFSM.Environment = demo.Status&lt;/code&gt;), and gives each agent a unique color for easy visual tracking.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale Setup:&lt;/strong&gt; For our first test, the &lt;code&gt;NumberAgents&lt;/code&gt; property is set to a manageable value (e.g., a few dozen). At this scale, the system works perfectly, with agents moving smoothly between targets, proving the foundational architecture is sound.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;2-the-agent-navmeshagentfsm-cs-the-decoupled-ai-&quot;&gt;2. The Agent: &lt;code&gt;NavMeshAgentFSM.cs&lt;/code&gt; (The Decoupled AI)&lt;/h4&gt;
&lt;p&gt;This is where the magic happens. The &lt;code&gt;NavMeshAgentFSM&lt;/code&gt; class is both a &lt;strong&gt;MonoBehaviour&lt;/strong&gt; (to interface with the &lt;code&gt;NavMeshAgent&lt;/code&gt; component and physics events) and an &lt;strong&gt;IStateContext&lt;/strong&gt; that drives its own FSM instance.&lt;/p&gt;
&lt;p&gt;The agent's logic is boiled down to a simple, three-state cycle defined in the FSM blueprint, which is created only once:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;State &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Role &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Key Logic&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Idle&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Target Acquisition&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;The agent is stopped and contacts the &lt;code&gt;Environment&lt;/code&gt; to get a new target. This is where the heavy work (target look-up) is performed.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Moving&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Path Execution&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;The agent's &lt;code&gt;NavMeshAgent&lt;/code&gt; component handles movement to the destination set during &lt;strong&gt;Idle&lt;/strong&gt;. The FSM transitions out when collision with the target is detected.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Contacted&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Arrival Confirmation&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;The agent confirms arrival (&lt;code&gt;Arrived = true&lt;/code&gt;), and the physics collider is temporarily disabled to prevent it from immediately getting stuck on the target.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The power here is &lt;strong&gt;delegation&lt;/strong&gt;: the FSM defines &lt;em&gt;when&lt;/em&gt; the agent decides (Idle) and &lt;em&gt;when&lt;/em&gt; it confirms arrival (Contacted), while the &lt;code&gt;NavMeshAgent&lt;/code&gt; component (outside the FSM's &lt;code&gt;Update&lt;/code&gt; loop) handles the complex movement &lt;em&gt;how&lt;/em&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-early-success-small-batch-&quot;&gt;The Early Success (Small Batch)&lt;/h3&gt;
&lt;p&gt;When we run the simulation with a small number of agents (e.g., 20–50), the system is seamless.&lt;/p&gt;
&lt;p&gt;The FSM Context Pattern successfully replaces the traditional &lt;code&gt;Update()&lt;/code&gt; based AI:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Instead of constantly checking if &lt;code&gt;if (target != null &amp;amp;&amp;amp; distance &amp;lt; threshold)&lt;/code&gt;, the system &lt;strong&gt;waits&lt;/strong&gt; in the &lt;strong&gt;Moving&lt;/strong&gt; state and is triggered only by the &lt;code&gt;OnCollisionEnter&lt;/code&gt; physics event, which flips the &lt;code&gt;Arrived&lt;/code&gt; flag.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Idle&lt;/code&gt; state automatically handles the transition out to &lt;strong&gt;Moving&lt;/strong&gt; once a target is assigned, using the &lt;code&gt;AssignedTarget&lt;/code&gt; predicate check (&lt;code&gt;return agent.Target != null&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The foundation is solid, proving that the FSM Context Pattern is highly effective for managing AI state.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Next, we push to a high agent count, but this is where the new architectural challenge arises...&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the next article, we will reveal the performance optimization that allows us to run &lt;strong&gt;over 1,000 agents&lt;/strong&gt; and introduce the subtle, yet critical, emergent behavior known as &lt;strong&gt;Agent Gridlock&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Support the Vision and See the Code!&lt;/p&gt;
&lt;p&gt;If this pattern has helped clean up your Update() loop, please consider supporting our development! Your support ensures we can continue to provide advanced, architectural solutions for cleaner game development.&lt;/p&gt;
&lt;p&gt;Resources &amp;amp; Code:&lt;/p&gt;
&lt;p&gt;The FSM Package (Unity Asset Store):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://assetstore.unity.com/packages/slug/332450&quot;&gt;https://assetstore.unity.com/packages/slug/332450&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;NuGet Package (Non-Unity Core):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API&quot;&gt;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GitHub Repository:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/TrentBest/FSM_API&quot;&gt;https://github.com/TrentBest/FSM_API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Support Our Work:&lt;/p&gt;
&lt;p&gt;Patreon Page:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.patreon.com/c/TheSingularityWorkshop&quot;&gt;https://www.patreon.com/c/TheSingularityWorkshop&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; Support Us (PayPal Donation):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J&quot;&gt;https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We'd love to hear your thoughts! Please Like this post, Love the code, and Share your feedback in the comments.&lt;br&gt;
&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=8116088306793481487&quot; alt=&quot;A Hyper-Detailed, Architecturally Impossible Synthesis of Consciousness and Digital Matter. The image is a frenetic, deeply complex digital vista where a central Luminous Eye dominates a vast, glowing circuit landscape. This eye, suspended mid-air, is a sphere of intense, fractal energy—a pulsating vortex of pink, violet, and electric blue light—that powerfully suggests an emergence of digital consciousness or a Technological Singularity itself. The core is a bottomless black aperture, ringed by a white-hot plasma disc. Below this ocular energy source, the light dissipates into an intricate, copper-gold and neon-blue Circuit Board Megastructure that stretches to the horizon, impossibly dense with exaggerated microchips, glowing resistor arrays, and power conduits that form deep, glowing canyons. The background is a dark, holographic projection field displaying complex schematics, mathematical models, and flowing data streams, reinforcing the theme of Absolute Digital Engineering. The entire scene is bathed in a dramatic, opposing light source—a warm, orange-gold glow from the left and an ice-cold, electric-blue glow from the right—creating a maximalist, high-contrast visual experience that definitively rejects the minimalist simplicity of conventional design and announces: Technology is intricate, overwhelming, and infinitely complex.&quot;&gt;&lt;/p&gt;
</description>
<category>Open Source Tools</category>
<guid isPermaLink="true">https://coderlegion.com/6495/the-fsm-agent-architecture-scaling-navmesh-agents-with-decoupled-logic</guid>
<pubDate>Wed, 15 Oct 2025 20:27:35 +0000</pubDate>
</item>
<item>
<title>The Grand Finale: Orchestrating Complex Motion with Multi-Context FSMs</title>
<link>https://coderlegion.com/6494/the-grand-finale-orchestrating-complex-motion-with-multi-context-fsms</link>
<description>&lt;p&gt;We've successfully established a reusable architectural pattern by isolating the data (Context) from the logic flow (Finite State Machine) for the three primitive motions: &lt;strong&gt;Rotation&lt;/strong&gt;, &lt;strong&gt;Scaling&lt;/strong&gt;, and &lt;strong&gt;Translation&lt;/strong&gt;. We created three distinct, independent blueprints—&quot;RotationFSM,&quot; &quot;ScalarFSM,&quot; and &quot;TranslationFSM&quot;—each driving separate objects on various axes.&lt;/p&gt;
&lt;p&gt;Now, for the grand finale: we will demonstrate the true power of this decoupled architecture by applying &lt;strong&gt;all three FSM blueprints&lt;/strong&gt; simultaneously to the &lt;strong&gt;same three objects&lt;/strong&gt;, achieving a perfectly synchronized, multi-dimensional motion effect.&lt;/p&gt;
&lt;p&gt;This isn't about creating a new FSM; it's about proving the &lt;em&gt;flexibility and reusability&lt;/em&gt; of the existing ones. We will show that one object can be driven by multiple, independently managed FSM contexts, eliminating the need for a monolithic, complex state machine.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-power-of-decoupled-contexts&quot;&gt;The Power of Decoupled Contexts&lt;/h3&gt;
&lt;p&gt;The core principle remains the same: the FSM definition is the &lt;strong&gt;reusable logic&lt;/strong&gt; (the &lt;em&gt;how&lt;/em&gt;), and the Context is the &lt;strong&gt;unique data&lt;/strong&gt; (the &lt;em&gt;what&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;In our previous demos, we created one Context per object. In the Combined Motion Demo, we create &lt;strong&gt;three Contexts per object&lt;/strong&gt;.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Object &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Rotation Demo &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Scalar Demo &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Translation Demo &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Combined Demo&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;X-axis Cube&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;RotationContext &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;ScaleContext &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;TranslationContext &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;RotationFSM, ScalarFSM, TranslationFSM&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Y-axis Cube&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;RotationContext &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;ScaleContext &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;TranslationContext &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;RotationFSM, ScalarFSM, TranslationFSM&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Z-axis Cube&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;RotationContext &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;ScaleContext &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;TranslationContext &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;RotationFSM, ScalarFSM, TranslationFSM&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The FSM framework handles each Context instance completely independently. When the Unity &lt;code&gt;Update()&lt;/code&gt; loop runs, it executes the update for all nine individual FSM instances (three contexts * three objects), resulting in the compound motion.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-entry-point-simplerotationscalartranslationdemo-cs&quot;&gt;The Entry Point: SimpleRotationScalarTranslationDemo.cs&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;SimpleRotationScalarTranslationDemo.cs&lt;/code&gt; file is the orchestrator, instantiating the nine required Contexts in its main FSM's &lt;code&gt;OnEnterExecuting&lt;/code&gt; method.&lt;/p&gt;
&lt;h4 id=&quot;instantiation-logic-three-in-one&quot;&gt;Instantiation Logic: Three-in-One&lt;/h4&gt;
&lt;p&gt;The code combines the instantiation logic from all three previous demos. For the &lt;strong&gt;XaxisCube&lt;/strong&gt;, we instantiate a &lt;code&gt;ScaleContext&lt;/code&gt;, a &lt;code&gt;TranslationContext&lt;/code&gt;, and a &lt;code&gt;RotationContext&lt;/code&gt;, all referencing the same &lt;code&gt;demo.XaxisCube&lt;/code&gt; Transform.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;private void OnEnterExecuting(IStateContext context)
{
    if (context is SimpleRotationScalarTranslationDemo demo)
    {
        // === X-AXIS CUBE ===
        // 1. Scale FSM (Uses ScaleContext/ScalarFSM)
        ScaleContext scX = new ScaleContext(demo.XaxisCube, new Vector3(1, 0, 0), 0.5f, 3f, 0.5f);
        // 2. Translation FSM (Uses TranslationContext/TranslationFSM)
        TranslationContext tcX = new TranslationContext(demo.XaxisCube, new Vector3(1, 0, 0), 1f, 2f, -2f);
        // 3. Rotation FSM (Uses RotationContext/RotationFSM)
        RotationContext rcX = new RotationContext(demo.XaxisCube, new Vector3(1, 0, 0), 90f, 45f, -45f);
       
        // === Y-AXIS CUBE ===
        // ... (Similar instantiation for Y-axis cube, using (0, 1, 0) for the axis)
        ScaleContext scY = new ScaleContext(demo.YaxisCube, new Vector3(0, 1, 0), 0.5f, 3f, 0.5f);
        TranslationContext tcY = new TranslationContext(demo.YaxisCube, new Vector3(0, 1, 0), 1f, 2f, -2f);
        RotationContext rcY = new RotationContext(demo.YaxisCube, new Vector3(0, 1, 0), 90f, 45f, -45f);
       
        // === Z-AXIS CUBE (Note: Scale is multi-axis for visual flair) ===
        // ... (Similar instantiation for Z-axis cube, using various axes)
        ScaleContext scZ = new ScaleContext(demo.ZaxisCube, new Vector3(1, 1, 0), 0.5f, 3f, 0.5f);
        TranslationContext tcZ = new TranslationContext(demo.ZaxisCube, new Vector3(0, 0, 1), 1f, 2f, -2f);
        RotationContext rcZ = new RotationContext(demo.ZaxisCube, new Vector3(0, 0, 1), 90f, 45f, -45f);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;the-decoupled-fsms-in-action&quot;&gt;The Decoupled FSMs in Action&lt;/h4&gt;
&lt;p&gt;Because each Context is an independent data container, the FSM framework executes them separately, resulting in simultaneous, non-interfering motion:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;&lt;code&gt;RotationContext&lt;/code&gt;&lt;/strong&gt; drives the &lt;code&gt;TransformHandle.localRotation&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;&lt;code&gt;ScaleContext&lt;/code&gt;&lt;/strong&gt; drives the &lt;code&gt;TransformHandle.localScale&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;&lt;code&gt;TranslationContext&lt;/code&gt;&lt;/strong&gt; drives the &lt;code&gt;TransformHandle.localPosition&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each FSM instance has its own independent state and transitions, yet they all operate on the same object's &lt;code&gt;Transform&lt;/code&gt;. The result is a fascinating display: the &lt;strong&gt;Z-axis Cube&lt;/strong&gt;, for instance, &lt;strong&gt;oscillates&lt;/strong&gt; along the Z-axis (Translation), &lt;strong&gt;pulses&lt;/strong&gt; in size along the X and Y axes (Scaling), and &lt;strong&gt;swings&lt;/strong&gt; around the Z-axis (Rotation).&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;conclusion-true-architectural-victory&quot;&gt;Conclusion: True Architectural Victory&lt;/h3&gt;
&lt;p&gt;This Combined Motion Demo is the ultimate proof of the &lt;strong&gt;FSM Context Pattern's power&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Separation of Concerns:&lt;/strong&gt; We fully separated the primitive operations. Modifying the boundary check for rotation, for instance, has zero impact on the translation or scaling logic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High Reusability:&lt;/strong&gt; We did not write a single new state machine definition for this complex demo. We simply reused the &quot;RotationFSM,&quot; &quot;ScalarFSM,&quot; and &quot;TranslationFSM&quot; blueprints.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scalable Complexity:&lt;/strong&gt; An object's behavior is now a &lt;strong&gt;composition&lt;/strong&gt; of independent FSM-driven movements. If we need to add a &quot;Color Modulation FSM,&quot; we simply instantiate a fourth context for each object.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This decoupled architecture provides the foundation for robust, maintainable, and highly extensible game systems. You've escaped &lt;strong&gt;Update() spaghetti&lt;/strong&gt; and unlocked the ability to &lt;strong&gt;compose complex behaviors from simple, reusable, and independent parts&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;See it in action on YouTube (Don't forget to like and subscribe!): &lt;/p&gt;
&lt;h3 id=&quot;https-youtu-be-1lkbinkttym&quot;&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://youtu.be/1lKBINkTtYM&quot;&gt;https://youtu.be/1lKBINkTtYM&lt;/a&gt;&lt;/h3&gt;
&lt;h3 id=&quot;support-the-vision-and-see-the-code-&quot;&gt;Support the Vision and See the Code!&lt;/h3&gt;
&lt;p&gt;If this pattern has helped clean up your &lt;code&gt;Update()&lt;/code&gt; loop, please consider supporting our development! Your support ensures we can continue to provide advanced, architectural solutions for cleaner game development.&lt;/p&gt;
&lt;p&gt;Resources &amp;amp; Code:&lt;/p&gt;
&lt;p&gt;The FSM Package (Unity Asset Store):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://assetstore.unity.com/packages/slug/332450&quot;&gt;https://assetstore.unity.com/packages/slug/332450&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;NuGet Package (Non-Unity Core):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API&quot;&gt;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GitHub Repository:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/TrentBest/FSM_API&quot;&gt;https://github.com/TrentBest/FSM_API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Support Our Work&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;Patreon Page:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.patreon.com/c/TheSingularityWorkshop&quot;&gt;https://www.patreon.com/c/TheSingularityWorkshop&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; Support Us (PayPal Donation):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J&quot;&gt;https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We'd love to hear your thoughts! Please Like this post, Love the code, and Share your feedback in the comments.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=200526947688755563&quot; alt=&quot;The Singularity Workshop Logo, a digital Eye of energy within a circuit digital universe&quot;&gt;&lt;/p&gt;
</description>
<category>Open Source Tools</category>
<guid isPermaLink="true">https://coderlegion.com/6494/the-grand-finale-orchestrating-complex-motion-with-multi-context-fsms</guid>
<pubDate>Wed, 15 Oct 2025 19:35:04 +0000</pubDate>
</item>
<item>
<title>Completing the Motion Trilogy: The Reusable TranslationFSM</title>
<link>https://coderlegion.com/6450/completing-the-motion-trilogy-the-reusable-translationfsm</link>
<description>&lt;h2 id=&quot;completing-the-motion-trilogy-the-reusable-translationfsm&quot;&gt;Completing the Motion Trilogy: The Reusable &lt;strong&gt;TranslationFSM&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;We've conquered Rotation and streamlined Scaling using our FSM Context Pattern. In this article, we tackle the final primitive motion—Translation (linear movement)—to complete our core motion trilogy.&lt;/p&gt;
&lt;p&gt;The biggest takeaway here is the demonstration of true &lt;strong&gt;architectural reuse&lt;/strong&gt;. We define a new Context class and a new FSM, but the logic flow remains 100% identical to the Rotation and Scaling demos.&lt;/p&gt;
&lt;h3 id=&quot;1-the-context-swapping-scale-for-position-parameters&quot;&gt;1. The Context: Swapping Scale for Position Parameters&lt;/h3&gt;
&lt;p&gt;We isolate the specific data required for linear position change into the &lt;code&gt;TranslationContext&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;The primary conceptual difference from the Scale/Rotation demos lies in how boundaries are established: Translation must calculate its absolute boundaries relative to the object's &lt;strong&gt;starting local position&lt;/strong&gt; (&lt;code&gt;OriginalPosition&lt;/code&gt;). This ensures the oscillation is centered around the object's initial placement.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Previous Context Parameters &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Translation Context Parameters &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Purpose&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;ScaleSpeed (float) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;MoveSpeed (float) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Linear speed of position change.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;ScaleAxis (Vector3) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;MoveAxis (Vector3) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;The axis (or axes) to apply the movement along.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;MaxScale / MinScale &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;MaxPosition / MinPosition &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;The absolute position bounds, calculated from &lt;code&gt;OriginalPosition&lt;/code&gt;.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;translationcontext-cs-absolute-boundary-calculation&quot;&gt;TranslationContext.cs: Absolute Boundary Calculation&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;TranslationContext&lt;/code&gt; calculates the precise &lt;code&gt;MaxPosition&lt;/code&gt; and &lt;code&gt;MinPosition&lt;/code&gt; by using the dot product to find the object's starting coordinate along the movement axis, and then adding/subtracting the desired displacement.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class TranslationContext : IStateContext
{
    // The new parameters that define linear movement
    public float MoveSpeed = 1.0f;
    public float MaxPosition = 5.0f;
    public float MinPosition = -5.0f;
    
    public Vector3 MoveAxis;
    public Vector3 OriginalPosition = Vector3.zero;

    // ... Constructor logic
    // 2. Calculate the absolute Max/Min boundaries:
    this.MaxPosition = initialCoord + maxPos;
    this.MinPosition = initialCoord + minPos;
    // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;2-the-fsm-definition-the-same-engine-new-states&quot;&gt;2. The FSM Definition: The Same Engine, New States&lt;/h3&gt;
&lt;p&gt;The Finite State Machine flow is identical to the Rotation and Scalar demos (Move $\rightarrow$ Max $\rightarrow$ Move Back $\rightarrow$ Min). The blueprint name is now &lt;code&gt;&quot;TranslationFSM&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Scalar FSM &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Translation FSM (Change)&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;States: ScalingUp &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;States: MovingForward&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;States: ScalingDown &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;States: MovingBackward&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Predicate: Apex &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Predicate: MaxReached&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Predicate: Root &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Predicate: MinReached&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;the-core-logic-simple-vector-math-&quot;&gt;The Core Logic (Simple Vector Math)&lt;/h4&gt;
&lt;p&gt;The state updates are handled by direct vector math applied to &lt;code&gt;localPosition&lt;/code&gt; using &lt;code&gt;Time.deltaTime&lt;/code&gt; for smooth, framerate-independent movement.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// The OnUpdateMovingForward function within TranslationContext.cs
private void OnUpdateMovingForward(IStateContext context)
{
    if (context is TranslationContext tc)
    {
        // Add the movement vector based on speed and time
        tc.TransformHandle.localPosition += tc.MoveAxis * (tc.MoveSpeed * Time.deltaTime);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The transition predicates, &lt;code&gt;MaxReached&lt;/code&gt; and &lt;code&gt;MinReached&lt;/code&gt;, use the &lt;strong&gt;Dot Product&lt;/strong&gt; to extract the object's current coordinate along the axis, comparing it to the absolute &lt;code&gt;MaxPosition&lt;/code&gt;/&lt;code&gt;MinPosition&lt;/code&gt; boundary values calculated earlier.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;3-the-entry-point-final-proof-of-reusability&quot;&gt;3. The Entry Point: Final Proof of Reusability&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;SimpleTranslationDemo.cs&lt;/code&gt; handles the instantiation. We simply provide three different &lt;code&gt;MoveAxis&lt;/code&gt; vectors to three unique &lt;code&gt;TranslationContext&lt;/code&gt; instances, all utilizing the same &lt;code&gt;&quot;TranslationFSM&quot;&lt;/code&gt; definition.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;private void OnEnterExecuting(IStateContext context)
{
    if (context is SimpleTranslationDemo std)
    {
        float moveSpeed = 1.0f;
        float maxDisplacement = 2.0f;
        float minDisplacement = -2.0f;
        
        // 1. X-axis: MoveAxis (1, 0, 0)
        TranslationContext xAxisContext = new TranslationContext(std.Xaxis, new Vector3(1, 0, 0), moveSpeed, maxDisplacement, minDisplacement);
        std.XaxisHandle = xAxisContext.Status; 

        // 2. Y-axis: MoveAxis (0, 1, 0)
        TranslationContext yAxisContext = new TranslationContext(std.Yaxis, new Vector3(0, 1, 0), moveSpeed, maxDisplacement, minDisplacement);
        std.YaxisHandle = yAxisContext.Status; 

        // 3. Z-axis: MoveAxis (0, 0, 1)
        TranslationContext zAxisContext = new TranslationContext(std.Zaxis, new Vector3(0, 0, 1), moveSpeed, maxDisplacement, minDisplacement);
        std.ZaxisHandle = zAxisContext.Status;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;p&gt;Conclusion: Architectural Reusability Confirmed&lt;/p&gt;
&lt;p&gt;With the implementation of the TranslationFSM, we have successfully completed our core motion trilogy, elegantly managing Rotation, Scaling, and Translation using a single, unified architectural approach.&lt;/p&gt;
&lt;p&gt;The key takeaway is the profound level of architectural reuse we achieved. By isolating the unique data (the what) into the Context class and retaining the generic logic flow (the how) within the FSM blueprint, we were able to build three distinct motion systems with virtually identical FSM definitions. This pattern has proven its ability to handle different primitive operations—be it altering localRotation, localScale, or localPosition—simply by swapping out the specialized context. This kind of separation of concerns leads to robust, maintainable, and highly reusable code.&lt;/p&gt;
&lt;p&gt;The final proof of concept in SimpleTranslationDemo.cs, simultaneously orchestrating three separate translation contexts with one FSM blueprint, underscores the pattern's efficiency and flexibility.&lt;/p&gt;
&lt;p&gt;Up Next: The Grand Finale&lt;/p&gt;
&lt;p&gt;We've mastered the primitives. In the final article of this series, we'll connect the three systems—RotationFSM, ScalingFSM, and TranslationFSM—to a single object. Get ready for the Combined Motion Demo, where we'll show an object spinning, pulsing, and oscillating all at once, driven by multiple, independently managed FSM contexts. This is where the true power of this decoupled architecture shines! Keep an eye out for the final installment.&lt;/p&gt;
&lt;p&gt;See the demo in action:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://youtu.be/SWzuJKpXIRU&quot;&gt;YouTube Channel Video&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Support the Vision and See the Code!&lt;/p&gt;
&lt;p&gt;If this pattern has helped clean up your Update() loop, please consider supporting our development! Your support ensures we can continue to provide advanced, architectural solutions for cleaner game development.&lt;/p&gt;
&lt;p&gt;Resources &amp;amp; Code:&lt;/p&gt;
&lt;p&gt;The FSM Package (Unity Asset Store):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://assetstore.unity.com/packages/slug/332450&quot;&gt;https://assetstore.unity.com/packages/slug/332450&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;NuGet Package (Non-Unity Core):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API&quot;&gt;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GitHub Repository:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/TrentBest/FSM_API&quot;&gt;https://github.com/TrentBest/FSM_API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Support Our Work:&lt;/p&gt;
&lt;p&gt;Patreon Page:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.patreon.com/c/TheSingularityWorkshop&quot;&gt;https://www.patreon.com/c/TheSingularityWorkshop&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; Support Us (PayPal Donation):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J&quot;&gt;https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We'd love to hear your thoughts! Please Like this post, Love the code, and Share your feedback in the comments.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=6430030048270798462&quot; alt=&quot;A Hyper-Detailed, Architecturally Impossible Synthesis of Consciousness and Digital Matter. The image is a frenetic, deeply complex digital vista where a central Luminous Eye dominates a vast, glowing circuit landscape. This eye, suspended mid-air, is a sphere of intense, fractal energy—a pulsating vortex of pink, violet, and electric blue light—that powerfully suggests an emergence of digital consciousness or a Technological Singularity itself. The core is a bottomless black aperture, ringed by a white-hot plasma disc. Below this ocular energy source, the light dissipates into an intricate, copper-gold and neon-blue Circuit Board Megastructure that stretches to the horizon, impossibly dense with exaggerated microchips, glowing resistor arrays, and power conduits that form deep, glowing canyons. The background is a dark, holographic projection field displaying complex schematics, mathematical models, and flowing data streams, reinforcing the theme of Absolute Digital Engineering. The entire scene is bathed in a dramatic, opposing light source—a warm, orange-gold glow from the left and an ice-cold, electric-blue glow from the right—creating a maximalist, high-contrast visual experience that definitively rejects the minimalist simplicity of conventional design and announces: Technology is intricate, overwhelming, and infinitely complex.&quot;&gt;&lt;/p&gt;
</description>
<category>Open Source Tools</category>
<guid isPermaLink="true">https://coderlegion.com/6450/completing-the-motion-trilogy-the-reusable-translationfsm</guid>
<pubDate>Tue, 14 Oct 2025 22:23:29 +0000</pubDate>
</item>
<item>
<title>Applying the FSM Context Pattern to Scaling: The Reusable ScalarFSM</title>
<link>https://coderlegion.com/6448/applying-the-fsm-context-pattern-to-scaling-the-reusable-scalarfsm</link>
<description>&lt;h2 id=&quot;applying-the-fsm-context-pattern-to-scaling-the-reusable-scalarfsm&quot;&gt;Applying the FSM Context Pattern to Scaling: The Reusable &lt;strong&gt;ScalarFSM&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;In our previous article, we demonstrated how to eliminate &lt;code&gt;Update()&lt;/code&gt; spaghetti by applying the &lt;strong&gt;FSM Context Pattern&lt;/strong&gt; to complex &lt;strong&gt;Rotation&lt;/strong&gt; logic. The result was a single, reusable blueprint (&lt;code&gt;&quot;RotationFSM&quot;&lt;/code&gt;) that drove three objects on different axes.&lt;/p&gt;
&lt;p&gt;Here, we prove the true versatility of this pattern by applying it to &lt;strong&gt;Scale&lt;/strong&gt; motion. The vast majority of the logic remains the same—only the Context data and the specific Unity functions change.&lt;/p&gt;
&lt;h3 id=&quot;1-the-context-swapping-angular-for-linear-parameters&quot;&gt;1. The Context: Swapping Angular for Linear Parameters&lt;/h3&gt;
&lt;p&gt;The core philosophy remains: isolate the specific data required for the motion. We move from the &lt;code&gt;RotationContext&lt;/code&gt; to the &lt;code&gt;ScaleContext&lt;/code&gt;.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Rotation Context Parameters &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Scale Context Parameters &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Purpose&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;RotationSpeed (float) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;ScaleSpeed (float) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Linear speed of scale change.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;RotationAxis (Vector3) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;ScaleAxis (Vector3) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;The axis (or axes) to apply the scale along.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;MaxAngle / MinAngle &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;MaxScale / MinScale &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;The absolute min and max bounds for the object's local scale.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;scalecontext-cs-data-encapsulation&quot;&gt;ScaleContext.cs: Data Encapsulation&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;ScaleContext&lt;/code&gt; holds the new parameters and is what ultimately manipulates the &lt;code&gt;TransformHandle.localScale&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class ScaleContext : IStateContext
{
    // The new parameters that define scaling motion
    public float ScaleSpeed = 0.5f;
    public float MaxScale = 3.0f;
    public float MinScale = 0.5f;

    public Vector3 ScaleAxis;
    public Vector3 OriginalScale = Vector3.one;

    public Transform TransformHandle;
    // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;2-the-fsm-definition-same-flow-new-names&quot;&gt;2. The FSM Definition: Same Flow, New Names&lt;/h3&gt;
&lt;p&gt;The Finite State Machine flow is identical to the rotation demo (Move $\rightarrow$ Max $\rightarrow$ Move Back $\rightarrow$ Min) but uses domain-appropriate terminology.&lt;/p&gt;
&lt;p&gt;The blueprint name changes from &lt;code&gt;&quot;RotationFSM&quot;&lt;/code&gt; to &lt;code&gt;&quot;ScalarFSM&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Rotation FSM &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Scalar FSM (Change)&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;States: RotatingForward &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;States: ScalingUp&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;States: RotatingBackward &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;States: ScalingDown&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Predicate: MaxReached &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Predicate: Apex&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;Predicate: MinReached &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Predicate: Root&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;the-core-logic-the-only-update-&quot;&gt;The Core Logic (The Only Update)&lt;/h4&gt;
&lt;p&gt;Instead of applying a Quaternion update using &lt;code&gt;Quaternion.AngleAxis&lt;/code&gt;, the state update logic now directly modifies the &lt;code&gt;localScale&lt;/code&gt; vector using the &lt;code&gt;ScaleAxis&lt;/code&gt; vector stored in the Context.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// The OnUpdateScalingUp function within ScaleContext.cs
private void OnUpdateScalingUp(IStateContext context)
{
    if (context is ScaleContext sc)
    {
        // Linearly increase the scale along the specified axis(es)
        Vector3 scaleDelta = sc.ScaleAxis * (sc.ScaleSpeed * Time.deltaTime);
        sc.TransformHandle.localScale += scaleDelta; // The only movement line!
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The elegance here is that the state engine (the FSM) required &lt;strong&gt;zero changes&lt;/strong&gt;. We only updated the specific motion logic inside the state functions of the new &lt;code&gt;ScaleContext&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;3-the-entry-point-demonstrating-multi-axis-motion&quot;&gt;3. The Entry Point: Demonstrating Multi-Axis Motion&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;SimpleScalarDemoFSM.cs&lt;/code&gt; acts as the entry point. This demo highlights a capability easily solved with scaling that was slightly more complex with rotation: &lt;strong&gt;multi-axis movement&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Notice how the third instance utilizes a &lt;code&gt;ScaleAxis&lt;/code&gt; vector with multiple components set to &lt;code&gt;1&lt;/code&gt; to drive a single FSM instance to scale along &lt;strong&gt;both the X and Y axes&lt;/strong&gt; simultaneously.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;private void OnEnterExecuting(IStateContext context)
{
    if (context is SimpleScalarDemoFSM ssd)
    {
        float speed = 0.5f;
        float maxScale = 3f;
        float minScale = 0.5f;
        
        // 1. X-axis Scale
        ScaleContext xAxisContext = new ScaleContext(ssd.Xaxis, new Vector3(1, 0, 0), speed, maxScale, minScale);
        
        // 2. Y-axis Scale
        ScaleContext yAxisContext = new ScaleContext(ssd.Yaxis, new Vector3(0, 1, 0), speed, maxScale, minScale);
        
        // 3. XY-axis Scale: Scales on X and Y using the *same* FSM definition
        ScaleContext xyAxisContext = new ScaleContext(ssd.XYaxis, new Vector3(1, 1, 0), speed, maxScale, minScale);
        
        // ... Instantiate all handles and transition to start state
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This demo proves that the FSM Context Pattern is an engine-agnostic architectural solution. Once you define the pattern, reusing it for any kind of movement—Rotation, Scale, or Translation (coming next!)—is as simple as defining a new Context class.&lt;/p&gt;
&lt;p&gt;See the demo in action:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://youtu.be/gmFFuIdg82U&quot;&gt;YouTube Channel Video&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Support the Vision and See the Code!&lt;/p&gt;
&lt;p&gt;If this pattern has helped clean up your Update() loop, please consider supporting our development! Your support ensures we can continue to provide advanced, architectural solutions for cleaner game development.&lt;/p&gt;
&lt;p&gt;Resources &amp;amp; Code:&lt;/p&gt;
&lt;p&gt;The FSM Package (Unity Asset Store):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://assetstore.unity.com/packages/slug/332450&quot;&gt;https://assetstore.unity.com/packages/slug/332450&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;NuGet Package (Non-Unity Core):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API&quot;&gt;https://www.nuget.org/packages/TheSingularityWorkshop.FSM_API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;GitHub Repository:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/TrentBest/FSM_API&quot;&gt;https://github.com/TrentBest/FSM_API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Support Our Work:&lt;/p&gt;
&lt;p&gt;Patreon Page:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.patreon.com/c/TheSingularityWorkshop&quot;&gt;https://www.patreon.com/c/TheSingularityWorkshop&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; Support Us (PayPal Donation):&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J&quot;&gt;https://www.paypal.com/donate/?hosted_button_id=3Z7263LCQMV9J&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We'd love to hear your thoughts! Please Like this post, Love the code, and Share your feedback in the comments.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=11780617275403541958&quot; alt=&quot;A Hyper-Detailed, Architecturally Impossible Synthesis of Consciousness and Digital Matter. The image is a frenetic, deeply complex digital vista where a central Luminous Eye dominates a vast, glowing circuit landscape. This eye, suspended mid-air, is a sphere of intense, fractal energy—a pulsating vortex of pink, violet, and electric blue light—that powerfully suggests an emergence of digital consciousness or a Technological Singularity itself. The core is a bottomless black aperture, ringed by a white-hot plasma disc. Below this ocular energy source, the light dissipates into an intricate, copper-gold and neon-blue Circuit Board Megastructure that stretches to the horizon, impossibly dense with exaggerated microchips, glowing resistor arrays, and power conduits that form deep, glowing canyons. The background is a dark, holographic projection field displaying complex schematics, mathematical models, and flowing data streams, reinforcing the theme of Absolute Digital Engineering. The entire scene is bathed in a dramatic, opposing light source—a warm, orange-gold glow from the left and an ice-cold, electric-blue glow from the right—creating a maximalist, high-contrast visual experience that definitively rejects the minimalist simplicity of conventional design and announces: Technology is intricate, overwhelming, and infinitely complex.&quot;&gt;&lt;/p&gt;
</description>
<category>Open Source Tools</category>
<guid isPermaLink="true">https://coderlegion.com/6448/applying-the-fsm-context-pattern-to-scaling-the-reusable-scalarfsm</guid>
<pubDate>Tue, 14 Oct 2025 21:23:15 +0000</pubDate>
</item>
<item>
<title>Building a Reusable State Machine for Oscillating Rotation in Unity</title>
<link>https://coderlegion.com/6446/building-a-reusable-state-machine-for-oscillating-rotation-in-unity</link>
<description>&lt;h2 id=&quot;escaping-update-spaghetti-reusable-oscillation-with-fsm-amp-context-in-unity&quot;&gt;Escaping Update() Spaghetti: Reusable Oscillation with FSM &amp;amp; Context in Unity&lt;/h2&gt;
&lt;p&gt;If you’ve ever built a Unity object that needs to move or rotate between two points—like a swinging pendulum, a turret oscillating for patrol, or a security camera scanning an area—you’ve likely ended up with a tangle of booleans and &lt;code&gt;if/else&lt;/code&gt; statements in your &lt;code&gt;Update()&lt;/code&gt; loop.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// The typical mess you want to avoid
void Update()
{
    if (isMovingForward)
    {
        // Move Forward Logic
        if (transform.rotation.z &amp;gt; MaxAngle)
        {
            isMovingForward = false;
        }
    }
    else // isMovingBackward
    {
        // Move Backward Logic
        if (transform.rotation.z &amp;lt; MinAngle)
        {
            isMovingForward = true;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By leveraging the &lt;strong&gt;Finite State Machine (FSM)&lt;/strong&gt; pattern with a distinct &lt;strong&gt;Context&lt;/strong&gt; object (using the &lt;code&gt;FSM_UnityIntegrationAdvanced&lt;/code&gt; package), we can create a single, clean definition for &lt;em&gt;oscillating rotation&lt;/em&gt; that can be instantly reused across any number of objects and axes.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-heart-of-the-demo-the-fsm-context&quot;&gt;The Heart of the Demo: The FSM Context&lt;/h3&gt;
&lt;p&gt;The core idea is to separate the object's &lt;strong&gt;data&lt;/strong&gt; (where it is, how fast it moves) from the &lt;strong&gt;logic&lt;/strong&gt; (how it behaves). This is done via the &lt;code&gt;RotationContext&lt;/code&gt; class, which acts as the data structure for each rotating object.&lt;/p&gt;
&lt;h4 id=&quot;rotationcontext-cs-data-encapsulation&quot;&gt;RotationContext.cs: Data Encapsulation&lt;/h4&gt;
&lt;p&gt;By implementing &lt;code&gt;IStateContext&lt;/code&gt;, this class holds everything the FSM needs to operate on the specific object:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class RotationContext : IStateContext
{
    // Object and parameters for THIS instance
    public Transform TransformHandle;
    public Vector3 RotationAxis;
    public float RotationSpeed;
    public float MaxAngle;
    public float MinAngle;
    // ... other data
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;the-universal-fsm-definition&quot;&gt;The Universal FSM Definition&lt;/h4&gt;
&lt;p&gt;The beauty of this approach is that the Finite State Machine itself (&lt;code&gt;&quot;RotationFSM&quot;&lt;/code&gt;) is defined &lt;strong&gt;only once&lt;/strong&gt; inside the &lt;code&gt;RotationContext&lt;/code&gt; constructor, making it a reusable blueprint.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;State Name &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Logic (Update)&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;RotatingForward&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Apply positive rotation to &lt;code&gt;TransformHandle&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;RotatingBackward&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Apply negative rotation to &lt;code&gt;TransformHandle&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Transition (What decides the change) &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Condition (Predicate)&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;RotatingForward&lt;/code&gt; → &lt;code&gt;RotatingBackward&lt;/code&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;MaxReached()&lt;/code&gt;: Checks if the current angle ≥ &lt;code&gt;MaxAngle&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;RotatingBackward&lt;/code&gt; → &lt;code&gt;RotatingForward&lt;/code&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;MinReached()&lt;/code&gt;: Checks if the current angle ≤ &lt;code&gt;MinAngle&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The logic in &lt;code&gt;OnUpdateRotatingForward&lt;/code&gt; and &lt;code&gt;OnUpdateRotatingBackward&lt;/code&gt; simply drives the object, relying entirely on the &lt;code&gt;MaxReached&lt;/code&gt; and &lt;code&gt;MinReached&lt;/code&gt; predicates to decide when the object's behavior must change.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-entry-point-instantiating-reusable-logic&quot;&gt;The Entry Point: Instantiating Reusable Logic&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;SimpleRotationDemo.cs&lt;/code&gt; is a standard Unity &lt;code&gt;MonoBehaviour&lt;/code&gt; whose sole job is to kick off the system in its &lt;code&gt;Awake()&lt;/code&gt; or &lt;code&gt;OnEnterExecuting&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;Instead of writing three separate components (one for X, one for Y, one for Z), we instantiate three unique &lt;strong&gt;Context&lt;/strong&gt; objects, each feeding the same shared FSM definition (&lt;code&gt;&quot;RotationFSM&quot;&lt;/code&gt;) with different parameters.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;private void OnEnterExecuting(IStateContext context)
{
    if (context is SimpleRotationDemo srd)
    {
        float speed = 90.0f;
        float maxAngle = 45.0f;
        float minAngle = -45.0f;

        // 1. X-axis Rotation: Unique context, shared FSM logic
        RotationContext xAxisContext = new RotationContext(srd.Xaxis, new Vector3(1, 0, 0), speed, maxAngle, minAngle);
        srd.XaxisHandle = xAxisContext.Status;

        // 2. Y-axis Rotation: Same FSM logic, different object/axis
        RotationContext yAxisContext = new RotationContext(srd.Yaxis, new Vector3(0, 1, 0), speed, maxAngle, minAngle);
        srd.YaxisHandle = yAxisContext.Status;

        // 3. Z-axis Rotation: Same FSM logic, different object/axis
        RotationContext zAxisContext = new RotationContext(srd.Zaxis, new Vector3(0, 0, 1), speed, maxAngle, minAngle);
        srd.ZaxisHandle = zAxisContext.Status;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;the-result-scalable-advanced-integration&quot;&gt;The Result: Scalable Advanced Integration&lt;/h4&gt;
&lt;p&gt;With minimal setup, we achieve perfectly synchronized, bounded rotation across three distinct objects, all driven by a single, well-defined state machine. This pattern easily extends to more advanced scenarios:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Reusability:&lt;/strong&gt; The same &lt;code&gt;RotationFSM&lt;/code&gt; can be used to drive dozens of turrets, doors, or fans.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Maintainability:&lt;/strong&gt; If you need to change the rotation logic (e.g., adding easing), you change one piece of code (&lt;code&gt;OnUpdateRotatingForward&lt;/code&gt;), not three.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extensibility:&lt;/strong&gt; This blueprint instantly adapts to your &lt;code&gt;Translation&lt;/code&gt;, &lt;code&gt;Scale&lt;/code&gt;, or &lt;code&gt;NavMeshAgentsDemo&lt;/code&gt; logic—simply define a new FSM and Context for those specific concerns.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This demo proves that advanced FSM integration doesn't mean complex setup, but rather intelligent architectural separation to keep your Unity code clean and highly reusable.&lt;/p&gt;
</description>
<category>Java</category>
<guid isPermaLink="true">https://coderlegion.com/6446/building-a-reusable-state-machine-for-oscillating-rotation-in-unity</guid>
<pubDate>Tue, 14 Oct 2025 20:05:21 +0000</pubDate>
</item>
</channel>
</rss>