Monday, November 9, 2026Gaming News
Armor QuestSearch
Gaming Industry

My RTS stuttered at 40 units. The fix was letting every unit roll


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Post news Report RSS 
 My RTS stuttered at 40…

Armor Quest4 min read
My RTS stuttered at 40 units. The fix was letting every unit roll
Post news Report RSS My RTS stuttered at 40 units. The fix was letting every unit roll a die

Once a second, the whole game hitched. The code was correct - it just ran for every unit in exactly the same frame.

Posted by iron-commandNET on Sep 13th, 2026

During a test run on a winter map I noticed a hitch. Once a second, like clockwork, as soon as there were more than 40 units on the field. Not in VR this time - on the monitor.

I wanted to push the army size to a hundred and never got there. At 60 to 70 units it wasn't a micro-stutter anymore. It was properly in the way.

Looking in the wrong place

My first look was shallow. I went through the code I had touched most recently, anything that could plausibly be related. That turned into searching for a needle in a haystack very quickly. Before burning more time, I wrote an analysis tool instead - something that reports everything that takes longer than it should.

Everyone into the canteen at noon

The cause turned out to be simple. Every unit checks four times a second whom it could attack. It walks the list of possible targets and tests each one. That is the correct way to do it. The problem: every single unit did it in exactly the same frame.

Twenty units checking in the same frame, you don't notice. Forty and more, and the system is briefly so busy that the picture stops.

Picture a hundred people walking into the canteen at exactly twelve o'clock. No need to describe how that goes. Spread the same hundred people over an hour, and nobody in the kitchen is rushed and nobody queues.

So that is what I did. Units no longer start their check at the same moment. Each one rolls its own die for when, and in which frame, it looks around. The checks spread out instead of piling up in a single frame.

The result

I built 40 to 50 units again - nothing. Then a hundred - still smooth. Past 200 - smooth. I stopped at just over 300 units, and there was no stutter at all.

119 soldiers on screen, and the counter still reads 100 FPS.

Iron Command isn't designed for that many units on one side. But it is good to know how much room there is above what the game actually needs.

Same test on the desert map - the base, the army and 124 FPS in one frame.

Have you had a bug like that - where every piece was correct on its own and it only broke once they all ran together?

Steam page, if you want to follow along: Store.steampowered.com

iron-command.net

Post a comment "); var textarea = $("#reply"+post); var mentions = $("#commentform .mentions-input").length > 0; if(mentions) { textarea.mentionsInput({source: "https://www.moddb.com/html/scripts/autocomplete.php?a=mentions&p=home&l=6&u=666"}); } $("#cancelreply"+post).click(function() { $("#"+post+" div.replypostholder").remove(); }); $("#savereply"+post).click(function() { postcontent = mentions ? textarea.mentionsInput("getValue") : textarea.val(); if(postcontent) { $(this).remove(); $("#cancelreply"+post).remove(); textarea.after("Saving your reply"); if(mentions) { $("#commentsummary").mentionsInput("setValue", postcontent); } else { $("#commentsummary").val(postcontent); } $("#commentform input[name=replyid]").val(post); $("#commentsubmit").click(); } else { $(this).text("Please enter a comment"); } }); } return false; }); $(".games92136watch").click(function(){ $.achtung({message: "Only members can follow games. Sign up today and follow your favorites.", className: "achtungFail", timeout:5}); return false; }); $(".c76625d26ff7f0c55142db2c328da119watch").click(function(){ $.achtung({message: "Only members can follow games. Sign up today and follow your favorites.", className: "achtungFail", timeout:5}); if($(this).hasClass("button")) { $(this).addClass("buttonon"); } return false; }); $(".togglertxinfo").click(function(e){ if($(this).attr("href") == "#rtxremix") { localStorage.setItem("rtxtoggled", true); $("#rtxremix").show(); return true; } else { localStorage.removeItem("rtxtoggled"); $("#rtxremix").hide(); return false; } }); function cookieScript(e) { var status = CookieScript.instance.currentState().categories.includes("targeting") ? "false" : "true"; var cookies = CookieScript.instance.currentState().categories.includes("performance") ? "true" : "false"; var cookie_data = { npa : {status:status,cookies:cookies,version:"1.0.13",chosen:"true"}, expires : 365 }; Cookies.set("dfp-npa", cookie_data.npa, { expires: cookie_data.expires, secure: true }); if (typeof gtag === "function") { gtag("consent", "update", {"ad_storage": cookie_data.npa.status == "false" ? "granted" : "denied", "ad_user_data": cookie_data.npa.status == "false" ? "granted" : "denied", "ad_personalization": cookie_data.npa.status == "false" ? "granted" : "denied", "analytics_storage": cookie_data.npa.cookies == "true" ? "granted" : "denied"}); } if(cookie_data.npa.status == "false") { // personalize if (typeof permutive === "object") { permutive.consent({ "opt_in": true, "token": "Allow All" }); } } else { // don't personalize if (typeof permutive === "object") { permutive.consent({ "opt_in": false }); } Cookies.remove("permutive-id", { domain: "moddb.com", secure: true }); } } if(!Cookies.get("dfp-npa")) { Cookies.set("dfp-npa", {status:"false",cookies:"true",version:"1.0.13",chosen:"false"}, { expires: 60, secure: true }); } window.addEventListener("CookieScriptAcceptAll", cookieScript); window.addEventListener("CookieScriptAccept", cookieScript); window.addEventListener("CookieScriptReject", cookieScript); window.addEventListener("CookieScriptClose", cookieScript); $("a.thickbox").click(function() { $.colorbox({href:$(this).attr("href"), rel:$(this).attr("rel"), open:true, onOpen:function(){ $(".nextmediabox").hide(); }, onClosed:function(){ $(".nextmediabox").show(); }}); return false; }); });