{"id":304,"date":"2025-02-06T18:53:29","date_gmt":"2025-02-06T18:53:29","guid":{"rendered":"https:\/\/shrubbgames.com\/?p=304"},"modified":"2025-02-06T18:53:29","modified_gmt":"2025-02-06T18:53:29","slug":"vv-eekly-update-27-background-loading","status":"publish","type":"post","link":"https:\/\/shrubbgames.com\/?p=304","title":{"rendered":"VV Eekly Update #27 &#8211; Background Loading"},"content":{"rendered":"\n<p>Welcome back to your regular VV Eekly Update! I hope that everyone is having a lovely January, in this lovely year 2024, on this lovely VV-ednesday. What a good day for a VV Eekly Update! (whoops)<\/p>\n\n\n\n<p>Today, I have a tale of preloading optimizations, optimizing loading times, and, tragically, premature optimizations. (Spoiler alert!)<\/p>\n\n\n\n<p>Today&#8217;s post is a doozy, but if you manage to read to the end, you&#8217;ll get a sneak peak of a <em>very <strong>very<\/strong><\/em> exciting thing!! (Very!)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Preloading<\/h2>\n\n\n\n<p>Recently, I&#8217;ve noticed that starting <em>Vyn and Verdan<\/em> to test out features has started taking longer and longer. Previously, opening the game would take a second or two, but it started taking <em>multiple<\/em> seconds.<\/p>\n\n\n\n<p>Anyone who&#8217;s used a computer before knows that that&#8217;s the worst! I hate waiting. You hate waiting. Crucially, all of the other people who might open <em>Vyn and Verdan<\/em> probably hate waiting.<\/p>\n\n\n\n<p>So, I decided to debug why it took so long to load. Let&#8217;s walk through that.<\/p>\n\n\n\n<p>When you open a game using Godot, the engine loads whichever scene you set as your main scene. That scene typically has a few children &#8211; other scenes that are part of the main scene. It also loads what are called &#8220;<a href=\"https:\/\/docs.godotengine.org\/en\/stable\/tutorials\/scripting\/singletons_autoload.html\" title=\"\">autoloads<\/a>&#8221; &#8211; things that are always loaded and are always present everywhere. I&#8217;ve talked about them before in <a href=\"https:\/\/shrubbgames.com\/?p=202\" title=\"\">VV Eekly Update #11 &#8211; Godot Patterns<\/a>.<\/p>\n\n\n\n<p>Therefore, one of these must be the cause of the long loading time. It didn&#8217;t take too long to figure out &#8211; I have a long list of &#8220;preloaded data&#8221;. Basically, the engine loads this data into memory before the game even starts, so that the game doesn&#8217;t stutter in the middle of gameplay when things get loaded.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"638\" height=\"474\" src=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/image.png\" alt=\"\" class=\"wp-image-305\" srcset=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/image.png 638w, https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/image-300x223.png 300w\" sizes=\"(max-width: 638px) 100vw, 638px\" \/><\/figure>\n\n\n\n<p>There&#8217;s a lot here! But it makes a lot of sense for this to be the laggy element. As the game has grown in scope and with more and more data being preloaded, this would naturally take longer and longer.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Background Loading<\/h2>\n\n\n\n<p>The issue that I saw was that data would take too long to load, causing the game to be slow to launch. The standard solution is to load data in a background thread, which Godot even has a whole <a href=\"https:\/\/docs.godotengine.org\/en\/stable\/tutorials\/io\/background_loading.html\" title=\"\">tutorial<\/a> on! This can&#8217;t possibly be <em>that <\/em>hard, right?<\/p>\n\n\n\n<p>All in all, it wasn&#8217;t too hard. I did spend a few days working on it, but now I have a standard solution that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Allows for registering assets in one line of code per asset<\/li>\n\n\n\n<li>Creates a background thread<\/li>\n\n\n\n<li>Automatically starts loading assets when the game is started<\/li>\n\n\n\n<li>Uses a different background thread to maintain completion status<\/li>\n\n\n\n<li>Logs how long loading assets takes each time the game is started<\/li>\n\n\n\n<li>Automatically cleans everything up<\/li>\n<\/ul>\n\n\n\n<p>I do say it wasn&#8217;t too hard, but I did lean <em>hard<\/em> on my previous experience as a software engineer. This stuff would have been very difficult for an inexperienced programmer! I think the tutorial did a pretty good job of explaining the basics, however. Nonetheless, I was grateful that I already knew the intricacies of thread management!<\/p>\n\n\n\n<p>After I built this utility, <em>Vyn and Verdan<\/em> would open quickly to the starting screen, but then there would be a few seconds before the game could be played. Now that I had this utility, I could see that loading assets in the background took about ~6 seconds after the game was opened.<\/p>\n\n\n\n<p>My next question was: Can I reduce this loading time further?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Asset Sizes<\/h2>\n\n\n\n<p>Which asset in particular was taking long to load? To find out, I deleted each preloaded asset one by one to see if there was any outlier. Luckily, there was a HUGE outlier!<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var SCENE_LEVEL := preload(\"res:\/\/main\/level.tscn\")<\/code><\/pre>\n\n\n\n<p>Surprise, surprise. Loading the whole game level took a long time! Who would&#8217;ve guessed. Let&#8217;s take a look at what the level looks like.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"223\" height=\"371\" src=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/image-1.png\" alt=\"\" class=\"wp-image-306\" srcset=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/image-1.png 223w, https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/image-1-180x300.png 180w\" sizes=\"(max-width: 223px) 100vw, 223px\" \/><\/figure>\n\n\n\n<p>To keep going, I went into the level scene, and I deleted each child of the scene one by one. Surprisingly, the UI layer was actually the big outlier here! Let&#8217;s take a look at that UI layer.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"223\" height=\"254\" src=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/image-2.png\" alt=\"\" class=\"wp-image-307\"\/><\/figure>\n\n\n\n<p>In the UI layer, the effects was the big outlier. &#8220;Effects&#8221; are what I call the big screen special effects that happen in games. For example, the screen darkening with a heartbeat, the sun spots that appear after winning a level, and winds blowing left or right are all effects. You might be able to guess what I did next.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"226\" height=\"252\" src=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/image-3.png\" alt=\"\" class=\"wp-image-308\"\/><\/figure>\n\n\n\n<p>This was a little harder to figure out, but I eventually figured out that if I deleted both &#8220;SunSpots&#8221; and &#8220;Upwards&#8221;, then <em>Vyn and Verdan<\/em> would take ~2 seconds to load instead of the previous ~6 seconds. So, why was that?<\/p>\n\n\n\n<p>I poked around in the SunSpots file, and this jumped out at me!<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"217\" height=\"361\" src=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/godotsize-1.png\" alt=\"\" class=\"wp-image-310\" srcset=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/godotsize-1.png 217w, https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/godotsize-1-180x300.png 180w\" sizes=\"(max-width: 217px) 100vw, 217px\" \/><\/figure>\n\n\n\n<p>Don&#8217;t worry too much about the weird jaggy lines &#8211; the bottom line is the important bit. This was almost 16 MB! I immediately went to look at the sizes in the folder.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"763\" height=\"551\" src=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/sizes.png\" alt=\"\" class=\"wp-image-311\" srcset=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/sizes.png 763w, https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/sizes-300x217.png 300w\" sizes=\"(max-width: 763px) 100vw, 763px\" \/><\/figure>\n\n\n\n<p>Yup, there&#8217;s a clear correlation here. Most of these files are 2 KB, and SunSpots and Upwards were 64 MB each. For those keeping track at home, that&#8217;s an approximately 32,000 times difference!<\/p>\n\n\n\n<p>The reason that there&#8217;s a large image in there was because I was using a big image to say &#8220;spawn things all over the screen&#8221; for both SunSpots and Upwards. You can also see that Seasons and Empower are large. For those, I was saying &#8220;spawn things around the edge of the screen&#8221;.<\/p>\n\n\n\n<p>The &#8220;all over the screen&#8221; was an easy fix. There was an option that I had missed earlier that just let me say &#8220;a box this size&#8221;, which, by the way, takes MUCH less data than a large image.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"239\" height=\"260\" src=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/newgodotsize.png\" alt=\"\" class=\"wp-image-316\"\/><\/figure>\n\n\n\n<p>The &#8220;around the edges of the screen&#8221; was a little harder. For those, I ended up actually changing behavior and saying &#8220;a ring around the size of the screen&#8221;. Luckily, I think it might actually look better now &#8211; here&#8217;s the old and new behavior.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"961\" height=\"540\" src=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/old-seasons.gif\" alt=\"\" class=\"wp-image-312\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"961\" height=\"540\" src=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/new-seasons.gif\" alt=\"\" class=\"wp-image-313\"\/><\/figure>\n\n\n\n<p>And here&#8217;s the updated sizes in the folder:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"771\" height=\"555\" src=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/new-sizes.png\" alt=\"\" class=\"wp-image-314\" srcset=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/new-sizes.png 771w, https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/new-sizes-300x216.png 300w, https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/new-sizes-768x553.png 768w\" sizes=\"(max-width: 771px) 100vw, 771px\" \/><\/figure>\n\n\n\n<p>Nothing above 10 KB! *whew*<\/p>\n\n\n\n<p>After all of that, the background loading now takes <strong>0.8 s<\/strong> down from <strong>about 6 seconds<\/strong>. That&#8217;s a huge decrease! If it only took less than a second to load, then I don&#8217;t think I ever needed to implement background loading&#8230; That was certainly a premature optimization! But it&#8217;s OK &#8211; I&#8217;ll appreciate having this background loading utility in the future, and it certainly was the point of <em>Vyn and Verdan<\/em> for me to learn from this type of mistake.<\/p>\n\n\n\n<p>So that&#8217;s all for today! If you have any feedback, please post on the usual Disco &#8211; oh wait, did I forgot something? Haha I knew you wouldn&#8217;t let me forget!<\/p>\n\n\n\n<figure class=\"wp-block-image alignfull size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"568\" height=\"321\" src=\"https:\/\/shrubbgames.com\/wp-content\/uploads\/2025\/02\/intro-preview-2.gif\" alt=\"\" class=\"wp-image-321\"\/><\/figure>\n\n\n\n<p>Now, THAT is all for today! Look forward to the next VV Eekly Update, since it&#8217;s a very special update!!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Welcome back to your regular VV Eekly Update! I hope that everyone is having a lovely January, in this lovely year 2024, on this lovely VV-ednesday. What a good day for a VV Eekly Update! (whoops) Today, I have a tale of preloading optimizations, optimizing loading times, and, tragically, premature optimizations. (Spoiler alert!) Today&#8217;s post [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":73,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[3],"tags":[],"class_list":["post-304","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-vv-eekly-updates"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/shrubbgames.com\/index.php?rest_route=\/wp\/v2\/posts\/304"}],"collection":[{"href":"https:\/\/shrubbgames.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/shrubbgames.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/shrubbgames.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/shrubbgames.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=304"}],"version-history":[{"count":6,"href":"https:\/\/shrubbgames.com\/index.php?rest_route=\/wp\/v2\/posts\/304\/revisions"}],"predecessor-version":[{"id":324,"href":"https:\/\/shrubbgames.com\/index.php?rest_route=\/wp\/v2\/posts\/304\/revisions\/324"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/shrubbgames.com\/index.php?rest_route=\/wp\/v2\/media\/73"}],"wp:attachment":[{"href":"https:\/\/shrubbgames.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=304"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/shrubbgames.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=304"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/shrubbgames.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=304"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}