<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mario Mignemi</title>
    <description>The latest articles on DEV Community by Mario Mignemi (@mario_mignemi).</description>
    <link>https://dev.to/mario_mignemi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4078219%2Fa7819b17-f4f2-425f-9161-2f28fbc7b2f4.webp</url>
      <title>DEV Community: Mario Mignemi</title>
      <link>https://dev.to/mario_mignemi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mario_mignemi"/>
    <language>en</language>
    <item>
      <title>GLM-5.3-Flash: A Geopolitical Disruptor Hiding in an Ultra-Cheap Model</title>
      <dc:creator>Mario Mignemi</dc:creator>
      <pubDate>Wed, 02 Sep 2026 12:19:42 +0000</pubDate>
      <link>https://dev.to/mario_mignemi/glm-53-flash-a-geopolitical-disruptor-hiding-in-an-ultra-cheap-model-3plk</link>
      <guid>https://dev.to/mario_mignemi/glm-53-flash-a-geopolitical-disruptor-hiding-in-an-ultra-cheap-model-3plk</guid>
      <description>&lt;p&gt;Before the world knew it was a product of Z.ai, a massive Chinese tech player, this model was running under the secret name "Ox Alpha". It has become the most used model on OpenRouter in a single week, purely through a blind taste test. People loved it before they even knew who to thank (or blame). &lt;/p&gt;

&lt;p&gt;Now, it’s officially out: &lt;strong&gt;GLM-5.3-Flash&lt;/strong&gt;. It’s an open-source, MIT-licensed model that is aggressively cheap, runs on Chinese-made silicon, and has proven it is both a miracle and a menace&lt;/p&gt;




&lt;h2&gt;
  
  
  The End of Nvidia Monopoly
&lt;/h2&gt;

&lt;p&gt;Most people look at AI through the lens of "Which one is the smartest?". The better question should be "Which one is the most accessible?"&lt;/p&gt;

&lt;p&gt;&lt;em&gt;GLM-5.3-Flash&lt;/em&gt; is disruptively cheap. We are talking &lt;strong&gt;$0.15 per million input tokens&lt;/strong&gt;. To put that in perspective, I fed it a completely unfamiliar codebase (my videogame) to run small and big refactorings, and the total cost came out to just &lt;strong&gt;$0.10&lt;/strong&gt;: a fraction of what you would pay for the same work using Claude Opus 4.8.&lt;/p&gt;

&lt;p&gt;But there is a geopolitical layer here, too. This massive spike in global AI traffic isn't running on Nvidia H100s. It’s running on Chinese-made chips. The "export control" era of AI is hitting a wall: China is proving they can serve the global market at scale without Western hardware.&lt;/p&gt;




&lt;h2&gt;
  
  
  Can it Survive the Jovarko Incident?
&lt;/h2&gt;

&lt;p&gt;I decided to put this cheap model through the ringer. I wanted to see if it could survive my game project, &lt;em&gt;The Weight of One – The Jovarko Incident&lt;/em&gt;, which has been in development since 2013, and still is today.&lt;/p&gt;

&lt;p&gt;I started with a tricky class decoupling to clear out direct dependencies. Many other tests followed. Without being overly technical, the most difficult one was converting a local, scene-bound component into a global, scene-unbound service. It was a high-risk refactor designed to test whether the model actually understood Unity state and runtime lifecycles, or if it would just blindly rewrite the logic and break all the classes it depended on.&lt;/p&gt;

&lt;p&gt;I can't stress this enough: I spent several hours with the model, putting it through multi-file refactoring tests, and the entire experiment cost me around &lt;strong&gt;10 cents&lt;/strong&gt;. When I checked my billing dashboard, I couldn't believe my eyes. &lt;/p&gt;




&lt;h2&gt;
  
  
  Beyond Task Completion: Contextual Awareness
&lt;/h2&gt;

&lt;p&gt;What surprised me wasn't just that it solved the tasks, but how it &lt;em&gt;noticed&lt;/em&gt; things. During the first test, it proactively flagged files in the wrong place, and spotted suspicious dependencies and code smells. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;GLM-5.3-Flash&lt;/em&gt; even reported a known bug mid-refactor and addressed it. It seems to have a "split attention" capability: it can focus on the task at hand while keeping a peripheral eye on everything else.&lt;/p&gt;

&lt;p&gt;When I questioned its approach, asking what changes are safer than others, or why it advised against certain refactors instead of others, it didn't just output generic advice. It gave clear, solid reasoning, very specific for my codebase. Having built it myself, I already knew the right answers, and its architectural logic was spot-on.&lt;/p&gt;




&lt;h2&gt;
  
  
  Optimizing for Today, Ignoring Tomorrow
&lt;/h2&gt;

&lt;p&gt;However, being "cheap" came with a side of "unpredictability". &lt;/p&gt;

&lt;p&gt;As weird as it can sound, the model is sometimes overly &lt;em&gt;proactive&lt;/em&gt;. During one big refactor, it deleted several &lt;em&gt;Assembly Definition&lt;/em&gt; files (C# way of grouping code) simply because their folders were empty: an unprompted "cleanup" I've never asked for. The problem? Those empty folders and assembly definitions were placed there for upcoming features. In trying to be helpful, it wiped out intended structure.&lt;/p&gt;

&lt;p&gt;The breaking point was the &lt;strong&gt;FSM Incident&lt;/strong&gt;. One of my packages had a dependency on a complex Finite State Machine (FSM) implementation. The model looked at it, judged the dependency as overkill, and simply deleted it to write its own minimal, "optimized" version. &lt;/p&gt;

&lt;p&gt;The model seems to optimize for &lt;em&gt;today&lt;/em&gt; without considering that I might need that complexity &lt;em&gt;tomorrow&lt;/em&gt;. It’s a reminder that while the model is logical, it lacks the long-term strategic vision of a lead developer.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI for the Rest of Us
&lt;/h2&gt;

&lt;p&gt;For anyone watching the hardware market over the last two years, the trend is impossible to miss. The silicon that once flowed toward desktop GPUs is now being vacuumed up by data centers. This isn't just a temporary pricing fluctuation. It's a fundamental shift in who the industry serves, and who it is leaving behind.&lt;/p&gt;

&lt;p&gt;I feel this shift every time I attempt to run a model locally. I currently own a 4060 Ti with 16GB of VRAM, and running models locally constantly forces me into a lose-lose trade-off.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The smart model route:&lt;/strong&gt; I get good capabilities, but the heavy VRAM footprint leaves me with a tiny context window to barely host a single source file plus some working memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The small model route:&lt;/strong&gt; I get a huge context window, but the model is too dumb to actually use it without degrading into nonsense.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why the push toward miniaturizing models like &lt;em&gt;GLM-5.3-Flash&lt;/em&gt; is so vital. We consumers don't need frontier models that require a nuclear power plant to run. We need good models that can run on the hardware we already own.&lt;/p&gt;




&lt;h2&gt;
  
  
  Looking for a New Equilibrium
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Maybe it’s time to change how I work entirely.&lt;/strong&gt; I’ve spent a long time trying to force local models to do more than my hardware allows. The trade-offs are simply too stark for me. Even with the move to capable remote models, I’m still grappling with the problem of "delegation overhead".&lt;/p&gt;

&lt;p&gt;In my current workflow, there is a sweet spot for AI: it is incredibly efficient when I can delegate large, complex systems, where the time saved outweighs the time spent reviewing the output. Unfortunately, there are no such tasks in &lt;em&gt;The Weight of One&lt;/em&gt;: The Jovarko Incident. The bulk of the systems are already implemented, and only granular, smaller tasks remain. The time required to prompt, review and test generated code often exceeds the time it would take me to just write it myself.&lt;/p&gt;

&lt;p&gt;Therefore, my focus for this next phase is to find a way to bridge this gap.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Have you experimented with the newer "Flash" class models? Do you prefer the "smart but expensive" approach, or are you betting on the "cheap and slightly chaotic" route?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My Game's Links:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@TheWeightOfOne-i9m/streams" rel="noopener noreferrer"&gt;The Weight of One - Official Channel&lt;/a&gt;&lt;br&gt;
&lt;a href="https://giovarco.itch.io/the-weight-of-one-the-jovarko-incident" rel="noopener noreferrer"&gt;The Weight of One - Itch.io Page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My Socials:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mario-mignemi-72482113a/" rel="noopener noreferrer"&gt;My Linkedin&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@mariomignemi1288/streams" rel="noopener noreferrer"&gt;My Personal Channel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find my Dev Vlogs in both Youtube channels!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>gamedev</category>
      <category>unity3d</category>
      <category>csharp</category>
    </item>
    <item>
      <title>#gamedev</title>
      <dc:creator>Mario Mignemi</dc:creator>
      <pubDate>Tue, 25 Aug 2026 05:52:02 +0000</pubDate>
      <link>https://dev.to/mario_mignemi/gamedev-lep</link>
      <guid>https://dev.to/mario_mignemi/gamedev-lep</guid>
      <description></description>
    </item>
    <item>
      <title>How Dyslexia Taught Me to Write Idiot-Proof Docs</title>
      <dc:creator>Mario Mignemi</dc:creator>
      <pubDate>Mon, 24 Aug 2026 20:52:48 +0000</pubDate>
      <link>https://dev.to/mario_mignemi/how-neurodivergence-taught-me-to-write-idiot-proof-docs-a7c</link>
      <guid>https://dev.to/mario_mignemi/how-neurodivergence-taught-me-to-write-idiot-proof-docs-a7c</guid>
      <description>&lt;p&gt;There is a strange dichotomy in my professional life. &lt;/p&gt;

&lt;p&gt;When I'm staring at a codebase, things make sense. Logic flows, structures are clear, and I can navigate complex systems with ease. But the moment I shift from writing code to writing long-form prose — whether it's a development article or a chapter of my novel — the world changes.&lt;/p&gt;

&lt;p&gt;I'm neurodivergent and have dyslexia. While I genuinely enjoy the act of storytelling and sharing knowledge, writing isn't my "natural" mode of output. For me, the cognitive load of structuring thoughts into flowing sentences is immense.&lt;/p&gt;

&lt;p&gt;Ironically, this struggle has become a professional superpower. Because I have to fight so hard to be clear, clarity has become something I pay close attention to. Over time, this has made me exceptionally good at writing idiot-proof technical documentation. I know exactly where a reader is likely to get lost because those are the same places I get stuck while writing.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Quest for a Better Bridge
&lt;/h2&gt;

&lt;p&gt;Because of this gap, I've spent a long time searching for a way to bridge the distance between the ideas in my head and the words on the page. Naturally, I turned to the tools that already help me in my coding workflow: Large Language Models (LLMs).&lt;/p&gt;

&lt;p&gt;However, I quickly discovered a frustrating irony. These tools are incredible at generating clean, functional code, but they often fall apart the moment you ask them to write a cohesive article.&lt;/p&gt;

&lt;p&gt;I tested the heavy hitters — Gemini, Grok, ChatGPT, and Claude — and the results were consistently disappointing. Most of them suffer from "repetition loops" where they repeat the same concept, in the same paragraph, in three different ways, burying the actual point in linguistic fluff. &lt;/p&gt;

&lt;p&gt;Claude was perhaps the best at this. It produces a structure that &lt;em&gt;looks&lt;/em&gt; correct at a glance, but the content is empty, meaningless. The sentences are technically correct but painfully long-winded, requiring multiple reads just to parse the meaning. They aren't writing. They're simulating the &lt;em&gt;sound&lt;/em&gt; of writing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Going Local: Quality Over Speed
&lt;/h2&gt;

&lt;p&gt;As a last resort, I decided to step away from the polished corporate chatbots and move toward local AI via LM Studio. I wanted to see if a specialized model could handle nuance better than these "jack-of-all-trades" giants.&lt;/p&gt;

&lt;p&gt;The biggest model I've tested was &lt;strong&gt;Gemma 4 31B (Q4_K_M)&lt;/strong&gt;, a &lt;strong&gt;20GB&lt;/strong&gt; beast. My 4060 Ti only has 16GB of VRAM, so I had to offload part of the model to system RAM, which made the process agonizingly slow. A 3-to-5-minute read took nearly an hour to generate.&lt;/p&gt;

&lt;p&gt;I didn't mind the wait because the result was fundamentally different. In that instance, the local model produced a high-quality draft on the first try. However, it revealed a critical truth: when using local AI, the quality of your notes is everything. If your input is vague or misspelled, the model can hallucinates wildly. To make it work, you have to be a rigorous "director", providing precise guidance and structured data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemma 4 26B A4B QAT (Q4_0)&lt;/strong&gt; told a different story. At roughly &lt;strong&gt;14GB&lt;/strong&gt;, it fit comfortably in VRAM. The difference was night and day. It took 15 seconds to finish, roughly 240 times faster. Finally fast enough to feel like a tool rather than a test of patience.&lt;/p&gt;

&lt;p&gt;The output quality came surprisingly close to the larger models, though I want to stress-test it further before drawing firm conclusions.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Modern Workflow
&lt;/h2&gt;

&lt;p&gt;This experimentation led me to a workflow that actually works for my brain. It isn't a "Generate" button; it's an iterative loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Brain Dump:&lt;/strong&gt; I start with unordered, chaotic notes of every point I want to cover.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Structuring Pass:&lt;/strong&gt; I hand these raw notes to Claude and ask it to organize them into something readable without changing the meaning. I then check the result to make sure nothing got twisted or lost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Style Guide:&lt;/strong&gt; I maintain a separate reference document defining my voice, structure and language preferences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Draft:&lt;/strong&gt; I feed the notes and the style guide into the local AI to create a good scaffolding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Refinement:&lt;/strong&gt; This is where the real labor happens. I spend 2 to 4 hours reading, editing, discarding nonsense, and refining the prose until the article not only &lt;em&gt;sounds&lt;/em&gt; like me, but it's in fact &lt;em&gt;me&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Stigma of the "Shortcut"
&lt;/h2&gt;

&lt;p&gt;This process, which still takes several hours, recently became a point of contention. &lt;/p&gt;

&lt;p&gt;A loved one, who works in communications and social media, asked if I used AI to write my articles. When I told her that I use it as an assistant, she laughed. In her field, the use of AI is often seen as unprofessional, a shortcut that signals a lack of effort or authenticity. She suggested that, while it might be "fine" for developers to do that, it was still essentially cheating.&lt;/p&gt;

&lt;p&gt;Her perspective highlights a genuine tension between industries. In communications, AI is often viewed as a replacement for the human voice. But in tech, the tide is shifting. Job postings now frequently list "experience with AI tools" as a requirement, signaling that companies view AI as a tool for augmentation, not as a way to avoid work.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Invisible Labor
&lt;/h2&gt;

&lt;p&gt;I'll be honest: being laughed in the face irritated me a lot. The frustration I felt in that moment didn't stem from her opinion on AI, but from the assumption that "AI-assisted" is synonymous with "effortless". &lt;/p&gt;

&lt;p&gt;Equating AI-assisted writing with purely automated output undermines the 2 to 4 hours spend reading, thinking and editing every single line.&lt;/p&gt;

&lt;p&gt;As a neurodivergent writer with dyslexia, AI doesn't do the work for me. It cuts through the "mechanical drag", so I can focus on what really matters: making sure my ideas actually reach the reader.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What about you? Where does AI fit into your creative process? Are you using it for game dev, content creation, or life admin — or are you still holding off? Let me know your favorite use cases (or biggest gripes) below!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My Game's Links:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@TheWeightOfOne-i9m/streams" rel="noopener noreferrer"&gt;The Weight of One - Official Channel&lt;/a&gt;&lt;br&gt;
&lt;a href="https://giovarco.itch.io/the-weight-of-one-the-jovarko-incident" rel="noopener noreferrer"&gt;The Weight of One - Itch.io Page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My Socials:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mario-mignemi-72482113a/" rel="noopener noreferrer"&gt;My Linkedin&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@mariomignemi1288/streams" rel="noopener noreferrer"&gt;My Personal Channel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find my Dev Vlogs in both Youtube channels!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>writing</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Your Unity Tests Are Lying To You (Here's Why)</title>
      <dc:creator>Mario Mignemi</dc:creator>
      <pubDate>Sun, 23 Aug 2026 20:02:12 +0000</pubDate>
      <link>https://dev.to/mario_mignemi/your-unity-tests-are-lying-to-you-heres-why-22h1</link>
      <guid>https://dev.to/mario_mignemi/your-unity-tests-are-lying-to-you-heres-why-22h1</guid>
      <description>&lt;p&gt;There is nothing more gaslighting than a test that passes on Monday and fails on Tuesday, without you changing a single line of code.&lt;/p&gt;

&lt;p&gt;Today, I’ve been diving deep into Unity integration testing for my Selection System. If you read my last post &lt;a href="https://dev.to/mario_mignemi/on-the-illusion-of-architectural-choice-in-unity-8kj"&gt;On the Illusion of Architectural Choice in Unity&lt;/a&gt;, you know I decided to lean into a ScriptableObject-based architecture. It felt elegant. It felt decoupled.&lt;/p&gt;

&lt;p&gt;Then I tried to test it. And that’s when I realized that while ScriptableObjects are great for architecture, they can be absolute nightmare for testing if you don't know the "hidden" rules of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The "Shared State" Trap (Again)
&lt;/h2&gt;

&lt;p&gt;Remember how I mentioned in my last article that SOs are assets and their state persists? Well, that architectural quirk becomes a lethal bug when writing tests.&lt;/p&gt;

&lt;p&gt;I wrote a test: &lt;em&gt;Select a unit → Verify it's selected.&lt;/em&gt; &lt;strong&gt;Pass.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;I wrote a second test: &lt;em&gt;Deselect all units → Verify nothing is selected.&lt;/em&gt; &lt;strong&gt;Pass.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But run them in a different order and they started failing. Why? Because the context was dirty.&lt;/p&gt;

&lt;p&gt;Loading a fresh scene before each test should have given me a clean slate, but the unit from Test A was still selected when Test B started. (Turns out scene loading had its own secrets, but that's a problem for later in this post).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Lesson:&lt;/strong&gt; Even in PlayMode tests, &lt;code&gt;ScriptableObjects&lt;/code&gt; do not magically wipe themselves clean between tests. You have to manually reset your runtime state using the attribute &lt;code&gt;[UnitySetUp]&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UnitySetUp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IEnumerator&lt;/span&gt; &lt;span class="nf"&gt;SetUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="nf"&gt;ClearSelection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Clearing the list containing the selected units&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Frame I Forgot to Wait For
&lt;/h2&gt;

&lt;p&gt;Once I fixed the SO state, I hit a second, sneakier problem: I &lt;em&gt;thought&lt;/em&gt; I was loading a clean scene before every test. I wasn't.&lt;/p&gt;

&lt;p&gt;My first attempt was simple: call &lt;code&gt;SceneManager.LoadScene(scenePath)&lt;/code&gt; in my setup, then immediately go find the GameObject I needed. But it was &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I stared at that &lt;code&gt;NullReferenceException&lt;/code&gt; for way longer than I'd like to admit. The object was &lt;em&gt;right there&lt;/em&gt; in the scene. I could see it in the Editor. Why couldn't my code find it?&lt;/p&gt;

&lt;p&gt;The answer was buried in a line of the Unity docs: &lt;code&gt;LoadScene&lt;/code&gt; is semi-asynchronous. Calling it doesn't load the scene &lt;em&gt;right away&lt;/em&gt;. It queues the load for the next frame. My setup code wasn't waiting for that frame.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; Stop treating scene loading as instant and actually wait for it to finish:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;UnitySetUp&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IEnumerator&lt;/span&gt; &lt;span class="nf"&gt;SetUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;LoadTestScene&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;ClearSelection&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IEnumerator&lt;/span&gt; &lt;span class="nf"&gt;LoadTestScene&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;loadOperation&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EditorSceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LoadSceneAsyncInPlayMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;ScenePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;LoadSceneParameters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LoadSceneMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Single&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;loadOperation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isDone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// one extra frame for safety&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Was it worth the pain?
&lt;/h2&gt;

&lt;p&gt;Here's the thing: none of this was new to me conceptually. I've spent 7-8 years writing Java/Spring Boot integration tests, so "isolate your state" and "don't trust a dirty context" weren't foreign ideas. I saw these problems coming before I'd even written my first test class. After all, that's just what integration testing demands, regardless of framework.&lt;/p&gt;

&lt;p&gt;What I wasn't prepared for was how Unity-specific the actual mechanics turned out to be. But that's the price of admission: you learn the framework's quirks by tripping over them. And it was worth it.&lt;/p&gt;

&lt;p&gt;Finally, I have a robust suite of tests for my Selection System, and I can sell the asset knowing that any future change won't quietly break it.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What about you?&lt;/strong&gt; Do you actually write integration tests in Unity, or do you rely on the "Play button and pray" method? Let me know in the comments!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My Game's Links:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@TheWeightOfOne-i9m/streams" rel="noopener noreferrer"&gt;The Weight of One - Official Channel&lt;/a&gt;&lt;br&gt;
&lt;a href="https://giovarco.itch.io/the-weight-of-one-the-jovarko-incident" rel="noopener noreferrer"&gt;The Weight of One - Itch.io Page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My Socials:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mario-mignemi-72482113a/" rel="noopener noreferrer"&gt;My Linkedin&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@mariomignemi1288/streams" rel="noopener noreferrer"&gt;My Personal Channel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find my Dev Vlogs in both Youtube channels!&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>gamedev</category>
      <category>testing</category>
      <category>csharp</category>
    </item>
    <item>
      <title>On the Illusion of Architectural Choice in Unity</title>
      <dc:creator>Mario Mignemi</dc:creator>
      <pubDate>Sat, 22 Aug 2026 20:25:50 +0000</pubDate>
      <link>https://dev.to/mario_mignemi/on-the-illusion-of-architectural-choice-in-unity-8kj</link>
      <guid>https://dev.to/mario_mignemi/on-the-illusion-of-architectural-choice-in-unity-8kj</guid>
      <description>&lt;p&gt;I was staring at my &lt;code&gt;SelectionSystem&lt;/code&gt; class a few days ago and realized that &lt;strong&gt;the public interface was completely stateless&lt;/strong&gt;, something that immediately raised a design question I hadn't considered.&lt;/p&gt;

&lt;p&gt;It was just a collection of logic handling lists. It didn't care about the frame rate, it didn't care about the scene hierarchy, and it didn't actually "live" anywhere. It just took a unit to select and that was it.&lt;/p&gt;

&lt;p&gt;At that moment, I hit a wall. If the system is stateless, where the hell should it actually reside? &lt;/p&gt;

&lt;p&gt;Now, for a bit of context: I’m building this system in a separate repository as a "test of skill" to master ScriptableObject (SO) architecture. My long-term goal is to package this up and sell it for cheap to help other developers, especially juniors, get a robust selection system without the typical "I just put everything in a singleton" headache. But to make it as easy to use as I wanted, I had to figure out the "entry point" problem.&lt;/p&gt;

&lt;p&gt;Here is the mess I went through trying to decide where the &lt;code&gt;SelectionSystem&lt;/code&gt; should live.&lt;/p&gt;




&lt;h2&gt;
  
  
  The "Comfort Zone": The MonoBehaviour Route
&lt;/h2&gt;

&lt;p&gt;The instinctive move in Unity — the one we all do when we're tired or in a rush — is to just slap a &lt;code&gt;MonoBehaviour&lt;/code&gt; on a GameObject, call it &lt;code&gt;SelectionManager&lt;/code&gt;, and call it a day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Appeal:&lt;/strong&gt; It’s comfy. You can drag and drop references in the Inspector, and you can see the system sitting right there in your Hierarchy. If your selection system is something like an RTS-style box selection, it feels natural for it to be "scene-owned" because it needs the active camera and &lt;code&gt;Physics.Raycast&lt;/code&gt; to figure out what the player is clicking on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; The moment you do this, you’ve basically built a prison for your logic. The system is now coupled to the scene. If you want to use this to a different scene, you have to set this up as a prefab. Also, other systems now have to find this specific instance (hello, &lt;code&gt;FindObjectOfType&amp;lt;T&amp;gt;()&lt;/code&gt; or the dreaded Singleton pattern), and your logic is now tangled up with Unity's scene lifecycle despite not using any of its methods. &lt;/p&gt;

&lt;p&gt;It’s great for a weekend prototype, but for a reusable package? Maybe not my cup of tea.&lt;/p&gt;




&lt;h2&gt;
  
  
  The "Architect's Dream": The ScriptableObject Route
&lt;/h2&gt;

&lt;p&gt;Since I'm leaning heavily into SO architecture, the next logical step was to make the &lt;code&gt;SelectionSystem&lt;/code&gt; an injectable &lt;code&gt;ScriptableObject&lt;/code&gt; service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Appeal:&lt;/strong&gt; This is where things start feeling elegant. The selection rules live in an asset. You can inject that asset into whatever needs it. The logic becomes scene-independent; you can call &lt;code&gt;SelectUnit(unit)&lt;/code&gt; from a UI button, a custom input handler, or a debug tool without needing a reference to a specific GameObject in the scene. It plays beautifully with modular &lt;code&gt;asmdef&lt;/code&gt; designs, keeping the orchestration separate from the scene components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; It's a potential "Shared State" Trap.  Here is where it can get weird for some junior developers. ScriptableObjects are assets. If you store runtime state — like &lt;em&gt;who&lt;/em&gt; is currently selected — directly inside the SO asset, that state persists across scenes. You stop the game, and the unit is still "selected" in the editor. Unless it was destroyed, of course. In that case, your list now contains a null element, ready to bite back at runtime. &lt;/p&gt;

&lt;p&gt;And then there's the lifecycle. SOs don't have an &lt;code&gt;Update&lt;/code&gt; loop. If your selection system needs to do something, even for a single frame, you're back to needing a &lt;code&gt;MonoBehaviour&lt;/code&gt; .&lt;/p&gt;




&lt;h2&gt;
  
  
  The Epiphany: "But wait... what about Split-Screen?"
&lt;/h2&gt;

&lt;p&gt;While debating MB vs. SO, I hit the real wall: &lt;strong&gt;Instance Scalability.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I started asking myself:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What if the game is split-screen?&lt;/em&gt; &lt;br&gt;
Suddenly, one global &lt;code&gt;SelectionSystem&lt;/code&gt; asset isn't enough. You need two. One for Player 1, one for Player 2. If the system is a single SO asset, Player 1 selecting a unit would accidentally select it for Player 2 as well. Total chaos.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What if the AI uses the selection system to target units?&lt;/em&gt;&lt;br&gt;
Does every single AI agent need their own &lt;code&gt;SelectionSystem&lt;/code&gt; asset? If you have 100 of them, are you really going to create 100 SO assets in your project folder? No way. &lt;/p&gt;

&lt;p&gt;Also, this all assumes we know the number of players/AIs ahead of time, and that's not always the case. So the question isn't just "how many &lt;code&gt;SelectionSystem&lt;/code&gt; do I need?" anymore. It's "how do I create one on demand?"&lt;/p&gt;

&lt;p&gt;Now, someone will (rightly) point out: &lt;em&gt;"You can just call &lt;code&gt;ScriptableObject.CreateInstance&amp;lt;SelectionSystem&amp;gt;()&lt;/code&gt; at runtime. Problem solved."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;True. That API exists precisely for this. But ask yourself what you're actually getting when you do that.&lt;/p&gt;

&lt;p&gt;The entire reason to reach for a ScriptableObject in the first place is because it's an &lt;strong&gt;asset&lt;/strong&gt;. If you're using that method, you might as well use a plain C# class instead of inheriting all the overhead of a&lt;code&gt;UnityEngine.Object&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Pure C# Detour
&lt;/h2&gt;

&lt;p&gt;I briefly considered going full "Clean Architecture" and making the system a pure C# domain service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Appeal:&lt;/strong&gt; Maximum flexibility and testability. In theory, I don't even need the Unity Editor. No dependencies, no scene overhead, just pure logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt; Integration friction. Pure C# might be a bit of a pain for junior developers to integrate because there's no "drag and drop" in the Inspector. You need some manual bootstrapping code to get it running in Unity.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: The Hybrid Approach
&lt;/h2&gt;

&lt;p&gt;I realized that the "entry point" shouldn't be the "system" itself. The system should be the logic, and the entry point should be an adapter.&lt;/p&gt;

&lt;p&gt;That's why "which one is better?" doesn't really hold up as a question. It's not an either/or choice. You can offer &lt;strong&gt;all of them&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why I'm sticking with SO (for now)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Going through this exercise, I realized the "correct" answer is probably the hybrid approach, and let each developer decide what's best for their project.&lt;/p&gt;

&lt;p&gt;But here's the thing: this system is a "test of skill" to master ScriptableObject (SO) architecture. Sure, this approach has real problems, but they're not problems I have &lt;em&gt;&lt;em&gt;right now&lt;/em&gt;&lt;/em&gt;, and limitations can be documented. Building the fully decoupled version today would be solving for a scale I don't need yet.&lt;/p&gt;

&lt;p&gt;So I'm keeping the SO-based version as-is and rather focus on flexibility and extensibility. If one of those use cases show up for real, which is very unlikely for my game, at least I know exactly where the seams are.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What about you? Do you prefer the "everything is a MonoBehaviour" simplicity, or have you fallen down the ScriptableObject rabbit hole too? Let me know in the comments!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My Game's Links:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@TheWeightOfOne-i9m/streams" rel="noopener noreferrer"&gt;The Weight of One - Official Channel&lt;/a&gt;&lt;br&gt;
&lt;a href="https://giovarco.itch.io/the-weight-of-one-the-jovarko-incident" rel="noopener noreferrer"&gt;The Weight of One - Itch.io Page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My Socials:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mario-mignemi-72482113a/" rel="noopener noreferrer"&gt;My Linkedin&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@mariomignemi1288/streams" rel="noopener noreferrer"&gt;My Personal Channel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find my Dev Vlogs in both Youtube channels!&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>gamedev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>When Rider Forgets How to Write Assembly Definitions: My Day-Long Fight With UnityAtoms</title>
      <dc:creator>Mario Mignemi</dc:creator>
      <pubDate>Tue, 18 Aug 2026 05:08:47 +0000</pubDate>
      <link>https://dev.to/mario_mignemi/the-rider-bug-thats-probably-already-in-your-project-you-just-havent-noticed-yet-2p0c</link>
      <guid>https://dev.to/mario_mignemi/the-rider-bug-thats-probably-already-in-your-project-you-just-havent-noticed-yet-2p0c</guid>
      <description>&lt;p&gt;Yesterday, adding a dependency in Jetbrains Rider was a non-event: type the class name, hit &lt;code&gt;Alt+Enter&lt;/code&gt;, keep coding. Today, the exact same shortcut quietly stopped writing anything to my .asmdef file  and it took me a full day to even understand what was going on, let alone fix it.&lt;/p&gt;

&lt;p&gt;For context: right now, I'm working on a flexible selection system for my game &lt;strong&gt;The Weight of One: The Jovarko Incident&lt;/strong&gt;, a tactical space-combat game. The project is split into several modules, each with its own Assembly Definition: &lt;code&gt;Core.asmdef&lt;/code&gt;, &lt;code&gt;Systems.asmdef&lt;/code&gt;, &lt;code&gt;UI.asmdef&lt;/code&gt;, &lt;code&gt;Data.asmdef&lt;/code&gt;, and so on. I recently added &lt;strong&gt;UnityAtoms&lt;/strong&gt; through the Package Manager, and I wanted to use types like &lt;code&gt;AtomEvent&lt;/code&gt; and &lt;code&gt;AtomValueList&lt;/code&gt; from the Data module. Simple stuff. Except it wasn't, and here's the story of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Ghost Import
&lt;/h2&gt;

&lt;p&gt;The first sign something was wrong was almost funny. I'd type &lt;code&gt;AtomEvent&lt;/code&gt;, the name would show up red (unresolved), I'd hit &lt;code&gt;Alt+Enter → Reference and import&lt;/code&gt;, and the red would disappear. Great, dependency resolved, right?&lt;/p&gt;

&lt;p&gt;Then I'd switch focus to the Unity Editor window to check something in the Inspector. The moment I clicked back into Rider, the exact same symbol was red again. Same file, same line, nothing touched in between.&lt;/p&gt;

&lt;p&gt;It felt like Rider had briefly &lt;em&gt;pretended&lt;/em&gt; to fix the problem and then changed its mind the second I looked away.&lt;/p&gt;




&lt;h2&gt;
  
  
  What &lt;code&gt;Reference and Import&lt;/code&gt; Is Actually Supposed to Do
&lt;/h2&gt;

&lt;p&gt;To be clear on what should happen: when you add a dependency through the Unity Package Manager, and you click Alt+Enter on an unresolved type that exist in an external assembly, Rider is supposed to add a reference in your .asmdef file. In my case, &lt;code&gt;Data.asmdef&lt;/code&gt; should end up depending on &lt;code&gt;UnityAtoms.UnityAtomsCore.Runtime&lt;/code&gt;. That's the whole mechanism that makes cross-module code work cleanly with Assembly Definitions instead of forcing everything into one giant assembly.&lt;br&gt;
Except my &lt;code&gt;Data.asmdef&lt;/code&gt; never actually gained that reference. The autocomplete &lt;em&gt;looked&lt;/em&gt; like it worked. But the underlying file wasn’t changed, which meant the result was only cosmetic. The Rider’s syntax highlighter got a brief nap before Unity's next domain reload reminded it that, structurally, &lt;strong&gt;nothing had actually been connected&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Troubleshooting Rabbit Hole
&lt;/h2&gt;

&lt;p&gt;At this point, I did what anyone would do: assumed it was something dumb on my end and started working through the usual checklist.&lt;br&gt;
    • Invalidate Caches / Restart &lt;br&gt;
    • Regenerate project files from Unity &lt;br&gt;
    • Fully close Unity, delete the &lt;code&gt;.csproj&lt;/code&gt; / &lt;code&gt;.sln&lt;/code&gt; files, reopen and let them regenerate &lt;br&gt;
    • Clean out the &lt;code&gt;Library&lt;/code&gt;/ folder &lt;br&gt;
    • Update both Rider and the JetBrains Rider Editor package&lt;br&gt;
    • Toggle &lt;code&gt;Git packages&lt;/code&gt; and &lt;code&gt;Built-in packages&lt;/code&gt; under Unity's &lt;em&gt;External Tools&lt;/em&gt; preferences. &lt;/p&gt;

&lt;p&gt;None of it stuck. By the end of the day, I had tried basically every standard fix in the book and I was exactly as blocked as when I started.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Almost-Fix
&lt;/h2&gt;

&lt;p&gt;Here's the one thing that worked, sort of: opening the asmdef file directly inside Rider's own editor and adding the reference by hand. Mind you, not through Unity's Assembly Definition Inspector. Through the raw file directly. That would sometimes get the symbols to resolve and &lt;em&gt;stay&lt;/em&gt; resolved.&lt;/p&gt;

&lt;p&gt;Sometimes. Not always. And I still haven't figured out what actually triggers it to break again. It's not tied to a specific action I can reproduce on demand, which is the most frustrating kind of bug: the kind where your "fix" is really just a temporary appeasement ritual and nothing else.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Bugs Me More Than a Normal Bug
&lt;/h2&gt;

&lt;p&gt;Well, it turns out I wasn't the only one blindsided by this either. A bit of digging turned up &lt;a href="https://youtrack.jetbrains.com/issue/RIDER-94834" rel="noopener noreferrer"&gt;RIDER-94834&lt;/a&gt; on JetBrains' YouTrack, a closely related report of asmdef references not being persisted correctly.&lt;/p&gt;

&lt;p&gt;And what gets under my skin isn't that the bug exists — software breaks, that's just how things go. It's &lt;em&gt;how&lt;/em&gt; it fails. Nothing about the UI hinted that the import hadn't actually landed on disk. That distinction matters to me.&lt;/p&gt;

&lt;p&gt;If package-sourced assemblies are a known blind spot for Rider, that's fine. It's a limitation, and limitations are forgivable. What isn't forgivable is showing that everything is ok when something silently fails. If Rider doesn’t support this type of import, say so: a warning banner, a tooltip, a line in the changelog. Anything beats finding out, after a wasted day, that it’s a visual bug.&lt;/p&gt;

&lt;p&gt;I'm not saying this to pile on. I pay for Rider, and it earns that money close to 100% of the time, which is exactly why this one stings. The bar is set high, and watching a core part of the Unity workflow quietly fail with zero warning felt genuinely out of character.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;I've since opened a &lt;a href="https://rider-support.jetbrains.com/hc/en-us/community/posts/38152781602066-Rider-no-longer-adds-resolves-asmdef-references-for-UnityAtoms" rel="noopener noreferrer"&gt;thread on the Rider support forum&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If this problem sounds familiar to you, don't just quietly work around it, please. Go upvote and comment on both the thread and the  YouTrack issue. A pile of "me too" moves the needle.&lt;/p&gt;

&lt;p&gt;For now, I'm sticking with the manual-edit workaround and treating every successful &lt;code&gt;Alt+Enter&lt;/code&gt; import with deep suspicion until I've actually reopened the file to confirm the reference stuck. Not a great long-term workflow, but it's hopefully unblocking me for the moment.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Has anyone else seen asmdef references silently drop the moment you switch focus between Unity and Rider?&lt;/strong&gt; If you've found a workaround that actually holds, not just "sometimes" but reliably, I'd really like to hear it in the comments.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;My Game's Links:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@TheWeightOfOne-i9m/streams" rel="noopener noreferrer"&gt;The Weight of One - Official Channel&lt;/a&gt;&lt;br&gt;
&lt;a href="https://giovarco.itch.io/the-weight-of-one-the-jovarko-incident" rel="noopener noreferrer"&gt;The Weight of One - Itch.io Page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;My Socials:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/mario-mignemi-72482113a/" rel="noopener noreferrer"&gt;My Linkedin&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@mariomignemi1288/streams" rel="noopener noreferrer"&gt;My Personal Channel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find my Dev Vlogs in both Youtube channels!&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>gamedev</category>
      <category>rider</category>
      <category>csharp</category>
    </item>
    <item>
      <title>How a Broken Button Forced Me to Rebuild My Entire Architecture</title>
      <dc:creator>Mario Mignemi</dc:creator>
      <pubDate>Sat, 15 Aug 2026 16:53:48 +0000</pubDate>
      <link>https://dev.to/mario_mignemi/how-a-broken-button-forced-me-to-rebuild-my-entire-architecture-12da</link>
      <guid>https://dev.to/mario_mignemi/how-a-broken-button-forced-me-to-rebuild-my-entire-architecture-12da</guid>
      <description>&lt;p&gt;A few weeks ago, I hit a deadlock that took me an embarrassingly long time to fix: I couldn't have a shuttle without a button, and I couldn't have a button without a shuttle.&lt;/p&gt;

&lt;p&gt;Here's why. My four-year-old button system required a live GameObject reference to be valid: no reference, and the button would self-destroy. Fine for a button that operates on a ship already sitting in the scene. Not fine for a boarding shuttle, which doesn't exist until a button spawns it. So &lt;strong&gt;the button needed the shuttle to exist to avoid self-destruction, and the shuttle needed a button to exist to spawn&lt;/strong&gt;. Neither one could go first.&lt;/p&gt;

&lt;p&gt;The bug wasn't in the shuttle. It was in a button that was four years old.&lt;/p&gt;

&lt;p&gt;I'm building &lt;strong&gt;&lt;em&gt;The Weight of One: The Jovarko Incident&lt;/em&gt;&lt;/strong&gt;, a tactical space-combat game where you command a capital ship and its subsystems. The shuttle in question is a small craft you launch from your own hangar to either forcibly dock an enemy ship from the outside, or peacefully move into the hangar of a neutral or allied ship. Simple concept. &lt;strong&gt;It broke everything I had.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This post isn't really about the shuttle, though. It's about the module structure I ended up building because of it, and whether drawing hard boundaries — before writing a single line of code — was worth the friction it's currently causing me.&lt;/p&gt;




&lt;h2&gt;
  
  
  Every button in my prototype came with a spaceship stapled to it
&lt;/h2&gt;

&lt;p&gt;My original UI code, written during early prototyping, made buttons stateful. A &lt;code&gt;ButtonModel&lt;/code&gt; held a direct reference to the ship it operated on, and if that reference wasn't there,  another script would destroy the button on the spot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
    &lt;span class="c1"&gt;// Pseudo-Code&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ButtonModel&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Transform&lt;/span&gt; &lt;span class="n"&gt;linkedShip&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SelfDestructOnDestroyedObject&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;ButtonModel&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="p"&gt;...&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;IEnumerator&lt;/span&gt; &lt;span class="nf"&gt;OnLostReferenceDestroySelf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;
                    &lt;span class="nf"&gt;Destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's fine when the ship already exists in the scene before the button does, which has been the case so far. However, for a shuttle, it's exactly backwards: the button is what's supposed to trigger the creation of the gameobject. &lt;strong&gt;The classic Mexican standoff.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I don't blame past-me for this. It was prototype code from 2021-2022, and it did its job for years, until it didn't in 2026. But I'm not the type to bolt on a special case just for shuttles and move on. &lt;strong&gt;If I have the feeling that the design is wrong, I want to know why and fix it.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Making the button stop caring whose ship it was
&lt;/h2&gt;

&lt;p&gt;The fix felt obvious once I named the actual problem: the button shouldn't hold a reference at all. It should announce an intent and let something else figure out the target.&lt;/p&gt;

&lt;p&gt;Stateless buttons break the deadlock cleanly. The catch: &lt;strong&gt;something&lt;/strong&gt; still needs to track which button maps to which ship. There’s no getting around it. That something is basically a lookup — conceptually a &lt;code&gt;Map&amp;lt;Button, Spaceship&amp;gt;&lt;/code&gt; — and I didn't want a bare dictionary sitting inside a &lt;em&gt;MonoBehaviour&lt;/em&gt; pretending to be a service, and six months later nobody remembers what it's for.&lt;/p&gt;




&lt;h2&gt;
  
  
  Down the ScriptableObject rabbit hole
&lt;/h2&gt;

&lt;p&gt;I had used &lt;em&gt;ScriptableObjects&lt;/em&gt; for exactly one thing before this story: configuration data. Stat blocks, balance numbers, that kind of thing. Looking into how larger studios structure decoupled systems, I found a much bigger use of SOs: as runtime variables, event channels, and typed runtime sets that replace both generic &lt;em&gt;EventBuses&lt;/em&gt;, which I've been using so far, and direct references.&lt;/p&gt;

&lt;p&gt;It solved my mapping problem cleanly.&lt;/p&gt;

&lt;p&gt;What it didn't solve was a bigger question: &lt;strong&gt;full rewrite, or hybrid architecture?&lt;/strong&gt; I have &lt;u&gt;no problem&lt;/u&gt; resetting and rebuilding systems, that's genuinely part of why I enjoy programming. However, a full architectural rewrite of a project that's somewhere between a prototype and an actual demo is a different bet than restructuring one feature. So I picked a feature that didn't exist at all — &lt;strong&gt;a flexible mission system&lt;/strong&gt; — and decided to build it entirely with a ScriptableObject architecture in a separate project, as a real test.&lt;/p&gt;




&lt;h2&gt;
  
  
  Drawing five boxes before writing any mission code
&lt;/h2&gt;

&lt;p&gt;Before touching the mission system, I made one decision on purpose: &lt;strong&gt;assembly definitions&lt;/strong&gt;, not just folder conventions, would decide where files were allowed to live. In fact, almost everything I came across about SO architecture — articles, videos, you name it — flagged a common problem: every variable, event channel, and runtime set is its own small asset, and that adds up fast.&lt;/p&gt;

&lt;p&gt;A feature that used to be two files in the old &lt;em&gt;EventBus&lt;/em&gt; system could easily turn into five or six files. Left unorganized, that adds up into a mess fast, so I wanted the boundaries locked in from day one.&lt;/p&gt;

&lt;p&gt;Five main modules, five assemblies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core&lt;/strong&gt;: Generic, game-agnostic primitives — base SO wrappers, generic interfaces, extensions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI&lt;/strong&gt;: Draws to Canvas/Screen, captures interface input, raises intent events&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data&lt;/strong&gt;: SO Variables, Event Channels, Runtime Sets, and config schemas — no &lt;code&gt;Update()&lt;/code&gt; loop&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gameplay&lt;/strong&gt;: Moment-to-moment entity behavior like movement, combat, mission triggers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Systems&lt;/strong&gt;: Global, cross-scene infrastructure, like save/load, scene transitions, campaign progress.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Dependency graph:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3yo8g4a5f5v0a7wukgcd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3yo8g4a5f5v0a7wukgcd.png" alt="Dependency Graph" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The one rule that makes the other five make sense
&lt;/h2&gt;

&lt;p&gt;None of this is exotic on its own. Assembly definitions weren't new to me, but I’ve never actually reached for them. Game development isn't my day job, so they just weren't on my radar until now.&lt;/p&gt;

&lt;p&gt;This is the part that maps directly back to the shuttle deadlock. The old &lt;code&gt;ButtonModel&lt;/code&gt; was a compile-time UI-to-Gameplay dependency wearing a &lt;em&gt;MonoBehaviour&lt;/em&gt; costume. The new rule makes that specific mistake &lt;strong&gt;impossible&lt;/strong&gt; to write by accident. The assembly definition simply won't allow it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where the shuttle actually landed
&lt;/h2&gt;

&lt;p&gt;Here's the part I want other people to take away from this. Understanding &lt;em&gt;ScriptableObject&lt;/em&gt; architecture hasn't stopped me from placing files where I think they belong, only to have the assembly definition reject them.&lt;/p&gt;

&lt;p&gt;At first, this was annoying. Then I noticed a pattern: every one of those errors was telling me one of two things. Either the file is genuinely misplaced, or &lt;strong&gt;the code design underneath it is wrong&lt;/strong&gt;: future tech debt I hadn't noticed yet, because nothing was preventing me from writing it that way.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is it paying off?
&lt;/h2&gt;

&lt;p&gt;Honestly, provisionally, yes! But I'm not going to pretend the trade-off is free: having a &lt;em&gt;ScriptableObject&lt;/em&gt; architecture and five modules means more files, which adds real ceremony for a solo dev before any feature ships. There's no dodging that.&lt;/p&gt;

&lt;p&gt;I picked the mission system specifically because it was new territory: a contained way to test the architecture before betting the rest of the game on it. I'm treating that as a deliberate validation step. I want to see it hold up across a few more features before I call it the standard.&lt;/p&gt;

&lt;p&gt;On the plus side, what I didn't expect was how much &lt;strong&gt;the friction itself became useful information&lt;/strong&gt;. Every misplaced file is a small, cheap lesson about my own design, delivered immediately instead of six months later as an unmaintainable spaghetti mess.&lt;/p&gt;




&lt;p&gt;If you're staring down a similar dilemma, the one thing I want you to take from this “happy accident” is: don't draw module boundaries as folders, draw them as &lt;strong&gt;dependency "permissions"&lt;/strong&gt;. Enforce them with assembly definitions, and let the compiler be blunt with you. &lt;/p&gt;

&lt;p&gt;This whole approach is a sharp departure from the generic &lt;em&gt;EventBus&lt;/em&gt; pattern I used to lean on, which is a big enough topic to deserve its own post. For now: I'll keep building the mission system and report back on whether five assemblies still feel right once the feature list grows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developers unite!&lt;/strong&gt; Let me know how you've drawn your own lines.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Useful Links:&lt;/em&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@TheWeightOfOne-i9m/streams" rel="noopener noreferrer"&gt;The Weight of One - Official Channel&lt;/a&gt;&lt;br&gt;
&lt;a href="https://giovarco.itch.io/the-weight-of-one-the-jovarko-incident" rel="noopener noreferrer"&gt;The Weight of One - Itch.io Page&lt;br&gt;
&lt;/a&gt;&lt;a href="https://www.youtube.com/@mariomignemi1288/streams" rel="noopener noreferrer"&gt;My Personal Channel&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find my Dev Vlogs in all channels!&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>architecture</category>
      <category>eventdriven</category>
      <category>gamedev</category>
    </item>
  </channel>
</rss>
