{"id":53914,"date":"2022-02-24T06:00:24","date_gmt":"2022-02-24T11:00:24","guid":{"rendered":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=53914"},"modified":"2022-02-24T10:00:18","modified_gmt":"2022-02-24T15:00:18","slug":"lets-make-a-spaceship-part-2-homeworld-bound","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=53914","title":{"rendered":"Let&#8217;s Make a Spaceship Part 2: Homeworld Bound"},"content":{"rendered":"<p>You may remember that <a href=\"?p=53830\">last week<\/a> I made a spaceship model. I think I could do better if I were to have another go at it, but this model is good enough for now:<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/modship10.jpg' width=100% alt='' title=''\/><\/div><div class='mouseover-alt'><\/div><\/p>\n<p>I didn&#8217;t mention it last time, but this isn&#8217;t a single ship model. Instead it&#8217;s built from modular pieces, and those pieces only cover the starboard side of the ship. I can then flip the pieces around if I want to put them on the port side. This means I can make the ship asymmetrical if I like. Also, I could make it arbitrarily longer by copying sections.<\/p>\n<p>Before we scrub this model and start over, I want to see it in motion. Now, if I was building physical models, then I could hold this thing in my hand and run around the room while making spaceship noises.\u00a0<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/modship2-1.jpg' width=100% alt='Here&apos;s a picture of some kid playing with a spaceship. I don&apos;t know where it&apos;s from. Some indie game, probably.' title='Here&apos;s a picture of some kid playing with a spaceship. I don&apos;t know where it&apos;s from. Some indie game, probably.'\/><\/div><div class='mouseover-alt'>Here&apos;s a picture of some kid playing with a spaceship. I don&apos;t know where it&apos;s from. Some indie game, probably.<\/div><\/p>\n<p>But since this model is just data, we&#8217;re going to have to settle for animating it on the computer. I <b>could<\/b> use Blender for this, but I&#8217;m more comfortable with Unity. So let&#8217;s import my model there.\u00a0<\/p>\n<p>First I have to create a new Unity project:<\/p>\n<p><!--more--><\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/modship2-2.jpg' width=100% alt='' title=''\/><\/div><div class='mouseover-alt'><\/div><\/p>\n<p>Let&#8217;s talk about these options:<\/p>\n<ol>\n<li>2D &#8211; I don&#8217;t make 2D games, so I never use this.\u00a0<\/li>\n<li>3D &#8211; This is the default I use for most unity projects. If you&#8217;ve ever looked at a game and thought, &#8220;This looks like it was made with Unity&#8221;, then it was probably built using this template. The lighting model is designed to be mostly idiot-proof, which has the downside of looking a bit bland.<\/li>\n<li>3D With Extras &#8211; Same as above, but with some example assets to show new users how things work.<\/li>\n<li>High Definition RP &#8211; This is the fancy-pants Unity setup for projects that want to use cutting-edge rendering techniques and are going for a more AAA look.\u00a0<\/li>\n<li>Universal Render Pipeline &#8211; This template sets the graphics to work almost anywhere, including mobiles and ancient PCs. Good if you&#8217;re doing mobile development. Bad if you&#8217;re picky about visuals.<\/li>\n<\/ol>\n<p>I usually go for #2, but what the heck? Let&#8217;s shove this model into the fancy-pants HDRP and see what it looks like&#8230;<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/modship2-3.jpg' width=100% alt='' title=''\/><\/div><div class='mouseover-alt'><\/div><\/p>\n<p>Oh hey. Bloom lighting? That&#8217;s cool. I guess that&#8217;s enabled by default here. In my projects I normally have to jump through a bunch of hoops to add bloom.<\/p>\n<p>This looks cool, but I&#8217;d like to see it in a proper space setting. Let me take two minutes and whip up a cheap space-backdrop&#8230;<\/p>\n<p>(Almost an hour passes.)<\/p>\n<p>Wow. The HDRP<span class='snote' title='1'>High Definition Render Pipeline. The &#8220;fancy pants&#8221; graphics.<\/span> looks better, but it&#8217;s also almost an order of magnitude more complex to set up. The various lighting systems are all interlinked: Ambient light, atmospheric scattering, reflections, post-processing \/ color grading, global directional light, and background image. This is probably really handy when you&#8217;re trying to set up a terrestrial scene, but it&#8217;s a huge pain in the ass when you want to turn off half of these features. Like, it took me twenty minutes to find the settings to get it to stop drawing a horizon.<\/p>\n<p>Anyway, once I have the settings wrangled I toss a 3D skybox over the scene.<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/modship2-4.jpg' width=100% alt='' title=''\/><\/div><div class='mouseover-alt'><\/div><\/p>\n<p>Okay, there&#8217;s <b>still<\/b> some sort of horizon being drawn. I have no idea why or how. There are a dozen different dialog boxes that control this stuff, and they all have a dozen or so settings, and I&#8217;m pretty sure I&#8217;ve tried everything.\u00a0<\/p>\n<p>This was supposed to be the mega-easy part, so it&#8217;s mildly infuriating that I can&#8217;t get it to render this very simple thing the way I want. I feel like this entire sky \/ fog \/ ambient \/ sky system is way more spread out than it needs to be. There are a couple of dialogs that don&#8217;t seem to do anything, and from reading the docs I get the sense that I&#8217;m seeing some middle-point between the &#8220;old way&#8221; and some yet-incomplete &#8220;new way&#8221; of setting up your scene in the HDRP.\u00a0<\/p>\n<p>Whatever. I just wanted some stars behind my spaceship for the next step. I&#8217;m content to live with this goofy space-horizon for now.\u00a0<\/p>\n<p>I want some smaller ships around. I jump back to Blender and model something that might generously be called a flying triangle. It looks like it was drawn by a child, but I don&#8217;t really care. I just want some small fighters to fly around and I don&#8217;t plan on looking at them up close.<\/p>\n<p>I whip up some code for a fighter. Now, this ship would just be a speck moving around the scene and that probably wouldn&#8217;t be very interesting. But I remember that way back in early aughts, the game Homeworld helped you visualize the motion of all the ships by having them leave glowing trails.\u00a0<\/p>\n<p>As luck would have it, Unity has a built-in &#8220;Trail Renderer&#8221;. I just attach it to the back of my fighter and tell it how long (in seconds) I want the trail to be. That&#8217;s it. Unity does everything else. If the ship moves faster, the trail will naturally get longer.\u00a0<\/p>\n<p>I add a handful of these ships to the scene and let them swoop around randomly.<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/modship2-5.jpg' width=100% alt='' title=''\/><\/div><div class='mouseover-alt'><\/div><\/p>\n<p>That&#8217;s pretty fun!<\/p>\n<p>This is giving the ship the sense of scale I was hoping for. The ship feels more like a carrier now, and less like a space bus.<\/p>\n<p>So&#8230; since I made these fighters. Why not make them fight?<\/p>\n<p>I add the concept of &#8220;teams&#8221;, and I make two squads of fighters: Red Team and Blue Team.\u00a0<\/p>\n<p>Now, in any of my pre-Unity projects, making dogfighting AI would have been a massive pain in the ass. Not difficult per se, just long and tedious. There&#8217;s a ton of code you need for moving and &#8220;thinking&#8221; in 3D space.\u00a0<\/p>\n<p>But with Unity, all of that work is already done. Pages and pages of code can be expressed in one or two lines. For example&#8230;<\/p>\n<pre lang=\"csharp\">\r\n\r\n\u00a0 \u00a0 transform.forward = Vector3.Lerp (transform.forward, ai_desired_heading, 0.02f);\r\n\r\n\u00a0 \u00a0 transform.position += transform.forward * speed;\r\n\r\n<\/pre>\n<p>Every single object in Unity has a &#8220;transform&#8221;. This structure keeps track of the object&#8217;s local orientation: The &#8220;forward&#8221; value always contains the vector of where the fighter&#8217;s nose is pointing, regardless of the fighter&#8217;s position in space. It also has an &#8220;up&#8221; vector, which would point out of the cockpit. It would be &#8220;up&#8221; according to the pilot, ignoring what&#8217;s going on outside. The transform also keeps track of where the object is and some other key facts about its behavior in the world.<\/p>\n<p>All of that work is done for me. All of those numbers are already calculated and ready for me to use when I need them, so I don&#8217;t have to write code for tracking that stuff myself.<\/p>\n<p>The first line of the code above takes two vectors: The way I&#8217;m pointing<span class='snote' title='2'>transform.forward<\/span>, and the direction the nose of the fighter <b>would<\/b> be pointing if I was aiming directly at my enemy.<span class='snote' title='3'>ai_desired_heading<\/span> It then calculates a vector between these values. The final value &#8211; 0.02 &#8211; tells it how far between these values to go.\u00a0<\/p>\n<p>This line boils down to: &#8220;Turn 2% of the way towards my target.&#8221;<\/p>\n<p>Two percent doesn&#8217;t sound like much, but keep in mind that this is done per frame. It&#8217;s going to do this at least 30 times per second, which can result in some pretty sharp turns. A value like ten percent will result in ships doing near-instant turns, which looks not awesome.<\/p>\n<p>Now, if I was trying to make a game, then I&#8217;d want something a little more sensible and balanced. Maybe I&#8217;d put an upper limit on how many degrees you can turn per second or whatever. But I just want the fighters to put on a show, so I don&#8217;t mind if they make lots of wide looping turns.<\/p>\n<p>The second line of code just shoves the ship forward according to its current speed.<\/p>\n<p>In my old C++ projects, this would be pages of code. But here in Unity land, I&#8217;m doing all of this complicated movement stuff with just 2 lines.<\/p>\n<p>I give the fighters the ability to fire lasers at each other. The result:<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/modship2-6.jpg' width=100% alt='' title=''\/><\/div><div class='mouseover-alt'><\/div><\/p>\n<p>Now, at this point in the project I decide to take a break. So I alt-tab over to YouTube and randomly stumble on the <a href=\"https:\/\/www.youtube.com\/watch?v=pacXW5eZb9w\">announcement for Homeworld 3<\/a>.<\/p>\n<p>The series has been dormant for years. I&#8217;m doing a project that roughly copies the superficial look of <em>Homeworld<\/em>, and suddenly I hear that a sequel is coming.\u00a0<\/p>\n<p>I realize it&#8217;s a small, inconsequential coincidence. But it was still quite a shock for me in the moment.\u00a0<\/p>\n<p>I should do a project to recreate the look of Half-Life and see if anything happens.<\/p>\n<p>EDIT: As requested, here&#8217;s an animated GIF of the action&#8230;<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/modship2-animated.gif' width=100% alt='' title=''\/><\/div><div class='mouseover-alt'><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>You may remember that last week I made a spaceship model. I think I could do better if I were to have another go at it, but this model is good enough for now: I didn&#8217;t mention it last time, but this isn&#8217;t a single ship model. Instead it&#8217;s built from modular pieces, and those [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[],"class_list":["post-53914","post","type-post","status-publish","format-standard","hentry","category-projects"],"_links":{"self":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/53914","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=53914"}],"version-history":[{"count":8,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/53914\/revisions"}],"predecessor-version":[{"id":53923,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/53914\/revisions\/53923"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=53914"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=53914"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=53914"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}