{"id":78,"date":"2026-09-30T15:21:10","date_gmt":"2026-09-30T15:21:10","guid":{"rendered":"https:\/\/courses.etc.cmu.edu\/53-353\/?p=78"},"modified":"2026-09-30T15:21:10","modified_gmt":"2026-09-30T15:21:10","slug":"lesson-6-astral-attackers-3","status":"publish","type":"post","link":"https:\/\/courses.etc.cmu.edu\/53-353\/index.php\/2026\/09\/30\/lesson-6-astral-attackers-3\/","title":{"rendered":"Lesson 6: Astral Attackers 3"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">This week, we take the pieces of a game and assemble them into a full game, complete with a fully compiled executable.  We will examine Unity&#8217;s Scene Management system, take a deeper dive into the User Interface (UI) by setting up a menu with custom buttons, get hands-on with the Build process, and finally look at how we can manipulate color and materials programmatically to create cool visual effects.  Let&#8217;s go! <\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Part 1: Scene Management<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1A: Introduction to the SceneManager<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In the early days of gaming, developers would divide a game up into small chunks called&nbsp;<strong>\u201clevels\u201d<\/strong>.&nbsp; &nbsp;While they were useful for players to measure their progress, their real purpose was to minimize the amount of data a game had to hold in memory in order to be playable.&nbsp; &nbsp;Even today, as games allow us to explore cities, countries, worlds, galaxies\u2026 the \u201clevel\u201d is commonly used as a way to divide up content.&nbsp; It would be silly to hold the final boss battle of a game in active memory when a player is hours away from encountering it.&nbsp; &nbsp;Each draw call would have to consider every polygon in the entire game, every object and behavior would have to be set just so.&nbsp; In short, it would be chaos.&nbsp; Computationally expensive chaos.&nbsp; Why spend all of those cycles considering things that are hours away from use?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So instead we break up our game into smaller chunks and these load into memory when they are needed, hence the \u201cloading\u201d screen that so many games have.&nbsp; (You may be thinking \u201cbut what about sandbox games?\u201d&nbsp; Well, those are divided into smaller areas as well \u2013 and not just areas, even objects inside those areas have various levels of detail that can be called up.&nbsp; The loading of that content happens in the background, and will swap places with a lower quality model when ready, usually fading between the two so as to disguise the effect and not distract the eye.&nbsp; Most often this happens in the distance, and the game is using predictive algorithms to determine which content you are most likely to need yet and start to load it.)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When Unity was first created, they&nbsp;also included a level system, which became known as&nbsp;<strong>Scenes.&nbsp;&nbsp;<\/strong>You will recognize this today as the format that we save our files in.&nbsp; Scenes have evolved to be much much more than just game levels, and are frequently seen used for other cases such as UI screens\/menus, code and asset loading, and animated cutscenes.&nbsp; Sometimes entire games will be saved as scenes.&nbsp; &nbsp;Projects (the things we open when we launch Unity, and where our Assets and such are stored) can contain multiple scenes, and when we build our game we will designate which of the scenes we create will be included in the build.&nbsp; (This is particularly useful when you\u2019re working on branches or variations of your game \u2013 you can simply swap one out for another if you need to!)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For the demo, I copy our basic scene and create two new &#8220;Levels&#8221; (named <strong>Level01 <\/strong>and <strong>Level02<\/strong>) that will serve as our gameplay, and then create a new empty scene (<strong>Menu<\/strong>) that will serve as our Title Menu UI for the game.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"408\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-3-1024x408.png\" alt=\"\" class=\"wp-image-79\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-3-1024x408.png 1024w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-3-300x119.png 300w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-3-768x306.png 768w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-3.png 1077w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Creating the &#8220;Start&#8221; Button<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Unity\u2019s UI buttons are easy to generate by going to\u00a0<strong>Create > UI > Button<\/strong>\u00a0or in the top menu\u00a0<strong>GameObject > UI > Button<\/strong>.\u00a0 This will create a new button object as a child of the Canvas object (which will also be created if you don\u2019t already have one).\u00a0 Buttons consist of two parts, the\u00a0<strong>Button<\/strong>\u00a0object, and a child\u00a0<strong>Text<\/strong>\u00a0object.\u00a0 \u00a0The Button object has two Components to note \u2013 the \u201cImage (Script)\u201d component where you define the look of your button, and the \u201cButton (Script)\u201d component where you can define the behaviors and transitions of the buttons.\u00a0 Details for how to use this are covered in the next section.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now for the complicated part \u2013 adding an action to your button.&nbsp; Buttons have an \u201cOnClick()\u201d message that they send when a user clicks them but accessing them is not as simple as accessing collider messages.&nbsp; At the bottom of the \u201cButton (Script)\u201d component you will see an \u201cOnClick()\u201d panel that is empty.&nbsp; If you click the \u201c+\u201d button it will create a new action.&nbsp; This action requires an object to be associated with it in order to access its scripted functions.&nbsp; &nbsp;You can add a script to the Button object, but then you will have to self-associate the button with itself.&nbsp; &nbsp;<strong>NOTE: The object HAS to be an object currently in the hierarchy.&nbsp; Linking to a prefab does not work.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In class, I created an empty game object (&#8220;MenuScriptObject&#8221;) and added a script (also called &#8220;MenuScript\u201d) which contained a single function that we would use to move to the next scene (&#8220;btn_StartTheGame&#8221;).  In the&nbsp;<strong>OnClick( )&nbsp;<\/strong>menu I associate the script object and select a function from the dropdown on the right by going to the specific component \u201ctitlescript\u201d and selecting the function I want to use.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"587\" height=\"52\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-4.png\" alt=\"\" class=\"wp-image-80\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-4.png 587w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-4-300x27.png 300w\" sizes=\"auto, (max-width: 587px) 100vw, 587px\" \/><\/figure>\n\n\n\n<p class=\"has-very-light-gray-background-color has-background has-small-font-size wp-block-paragraph\"><strong>NOTE:<\/strong>&nbsp; Any function that will be accessed by a Button must be PUBLIC, and VOID.&nbsp; It can only take up to one (1) parameter.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">The Scene Manager<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Now that we have a button in place, let\u2019s connect some scenes.&nbsp; I\u2019m going to make my \u201cMenuScript\u201d handle our first scene jump.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First, I have to add a new library to the code, so I start the file by adding this line:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\nusing UnityEngine.SceneManagement;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Now we can access the scene management commands.&nbsp; &nbsp;I can create a button command, so looking at our button example above to make us jump to level 1, I create the following in button script.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\n    public void btn_StartTheGame()\n    {\n        SceneManager.LoadScene(&quot;Level01&quot;);\n    }\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Again, please note that this must public and void for the editor to see it.&nbsp; Here, ours takes no arguments.&nbsp; &nbsp; And the command itself is rather simple \u2013 we run the&nbsp;<strong>LoadScene ( )<\/strong>&nbsp;function and pass in the string name of our level.&nbsp; &nbsp;We can also pass in an integer that corresponds with the scene index.&nbsp; Speaking of\u2026<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Adding Scenes to the Build<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">In order to load scenes, Unity has to have those scenes associated with the build.\u00a0 You can do this by going to\u00a0<strong>File > Build Profiles<\/strong>, and dragging the scenes you will be using from the Asset panel into the <strong>Scene List<\/strong>.\u00a0 Notice that when you add a scene, it also assigns it an indexed location.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"623\" height=\"252\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2024\/10\/image.png\" alt=\"\" class=\"wp-image-524\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2024\/10\/image.png 623w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2024\/10\/image-300x121.png 300w\" sizes=\"auto, (max-width: 623px) 100vw, 623px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Once you have associated the scenes, you can close the window.&nbsp; (There is no save button to worry about, your changes are automatically registered.)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1B: Building a &#8220;Level Manager&#8221;<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Our next step is to create a &#8220;LevelManager&#8221; script that will be included on one object within each level. This script will hold our SceneManagement calls, and each level&#8217;s instance will hold information about the level itself, and where to go next.  We will make this a script a <strong>singleton<\/strong> to provide easy access for other objects (like our GameManager), but there will only ever be one of these objects in a level &#8211; it will appear and disappear with the scene itself &#8211; so we do not need to worry about testing for a pre-existing version of the manager.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We create variables to hold the current level name (to be used by the level&#8217;s UI when we first enter the scene) and a variable that holds the name of the next scene (so that our script knows where to go next once the player beats the level).   We replace our GameManager&#8217;s success state with a call to <strong>LevelManager.S.GoToNextRound( )<\/strong> and now we move to the next level automatically.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\n\npublic class LevelManager : MonoBehaviour\n{\n    public static LevelManager Larry;\n\n    public string levelName; \/\/ string to display at level start\n    public string nextScene; \/\/ name of the scene we move to if successful\n\n    private void Awake()\n    {\n        Larry = this; \/\/ singleton definition\n    }\n    public void GoToNextRound()\n    {\n        SceneManager.LoadScene(nextScene);\n    }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Once we have completed our script, we place LevelManager objects in both of our scenes and test the results.  In our Level02 scene, we set our &#8220;next scene&#8221; to &#8220;Menu&#8221;, which will return us to the main screen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1C: Don&#8217;t Destroy on Load<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Now that we are using the LevelManager to progress to the next level when the player wins, can we also use it to manage the process when the player loses?  Yes, but it comes with some new complications that require us to rethink our GameManager and game flow logic.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Restarting the Level<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">In the past lesson, we spent a lot of time having our GameManager reset the level to the same condition as when we first entered the scene.  A fantastically convenient (and conveniently lazy) way to eliminate these steps is to simply <strong>reload the scene itself<\/strong>.  This way the GameManager does not need to be at all aware of what enemy objects should spawn, or what the range and speed of the player should be, or where shields should go!  This only works if you&#8217;re treating levels as a non-persistent environment, where all objects completely respawn to the original state, but for classic arcade games this was definitely the case.    We accomplish this lazy sorcery within our LevelManager like so:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\n    public void RestartLevel()\n    {\n        \/\/ reload this scene\n        SceneManager.LoadScene(SceneManager.GetActiveScene().name);\n    }\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Here, we load a scene that happens to be the one we are currently in. How do we know that? Because we use <strong>GetActiveScene( )<\/strong> to return details about the current scene that we are in.  After our GameManager passes through its &#8220;Oops&#8221; state, it deducts a life, tells the LevelManager to load itself, and voila&#8230; instant round reset!<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Staying Alive (aka Don&#8217;t Destroy Me Bro&#8230;)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The reset worked wonderfully, but we have created a new issue &#8211; our GameManager was also destroyed with our scene. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Most aspects of our game can simply disappear between scenes, but our GameManager is pretty important!  It holds a lot of critical information such as our score and the number of lives remaining.  In other word, the important attributes of our game that transcend the individual level and are of importance to the game.   We made sure to include this prefab in both of our scenes, because we cannot play without it&#8230;  but we also don&#8217;t want to destroy it with our scene, or if we can bring it along, overwrite it when the next instance arrives with a new scene. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To accomplish this, we spare GameManager from an untimely deletion by adding the following line to the&nbsp;<strong>Start ( )<\/strong>&nbsp;function in the GameManager script.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\n DontDestroyOnLoad (this);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\"><strong>DontDestroyOnLoad&nbsp;( )<\/strong>&nbsp;preserves a game object across transitions.&nbsp; It actually creates a little side scene in the Hierarchy and moves the object into it during runtime, as seen below:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"308\" height=\"111\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-18.png\" alt=\"\" class=\"wp-image-368\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-18.png 308w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-18-300x108.png 300w\" sizes=\"auto, (max-width: 308px) 100vw, 308px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Now when we jump scenes, this object remains, and our score persists as we play through.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"318\" height=\"111\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-19.png\" alt=\"\" class=\"wp-image-369\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-19.png 318w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-19-300x105.png 300w\" sizes=\"auto, (max-width: 318px) 100vw, 318px\" \/><figcaption class=\"wp-element-caption\">Still with us?<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">But\u2026 (you knew there would a &#8220;but&#8221;, didn\u2019t you?)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For our game to run correctly, we need to have GameManager running in every scene. This means that either we would ALWAYS have to start our game from the very beginning in the scene where we first instantiate it and play all the way through \u2013 not fun, especially when we just want to test one tiny thing in level 5 \u2013 OR we have to find a way to include it in EVERY scene. To address this, we make our Game Manager into a prefab, and drop an instance of this prefab into every level.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You may remember in our previous class, I discussed the &#8220;two manager&#8221; situation, where a new manager comes onto the floor (into existence in the scene) and checks for a previous instance.  If a previous instance exists, it simply destroys itself.  <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And so, we build in a check in our Game Manager start script that checks to see if any instance of the singleton exists.&nbsp; If none exists, great \u2013 we\u2019re first to the party and we set up shop.&nbsp; But if there is already a singleton defined, we kill this instance of the manager as it is not needed.&nbsp; The script for that looks like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\n    private void Awake()\n    {\n        if (Gary)\n        {\n            Destroy(this.gameObject);  \n            \/\/ Singleton already exists, remove this instance\n        } else { \n            Gary = this;  \/\/ Singleton Definition\n        }\n    }\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Here we check for the existence of another version of GameManager.&nbsp; If none exists, GameManager.S will return \u201cnull\u201d.&nbsp; If not null, someone is already here.&nbsp; We destroy this new version, and we submit a \u201creturn\u201d command, which exits our script rather than continuing on.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once we\u2019ve passed our null-check, the script is still executing so we know we must be the one true game manager. We assign Singleton status and then in the&nbsp;<strong>Start( )&nbsp;<\/strong>method we declare our intention to live forever.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Bringing the UI<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">The next issue that we encounter is that our UI references are severed when we move frome one scene to the next.  Even though they are similarly named, these UI elements are NOT the same elements that our GameManager is familiar with.   Those were destroyed with the rest of the scene.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There are solutions for this, we could run a &#8220;Find&#8221; if the reference were not intact, or have  UI Manager associated in each screen (even our Level Manager could do double duty in this regard).   <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But an even easier (lazier) way is to simply <strong>make the UI elements a child of our GameManager object<\/strong>.   Now when a fresh GameManager enters the scene and finds that another GameManager already exists, it will destroy not only itself, but its child objects as well, taking the detached UI with it.   The UI from our earlier level is safely preserved down in DontDestroyOnLoad Land.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1D: Updating our Game Flow<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Now that we have our scene resetting itself and our LevelManager moving us between levels, it is time to update our flow diagram so that we can have LevelManager and GameManager communicate more effectively.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"968\" height=\"666\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-5.png\" alt=\"\" class=\"wp-image-81\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-5.png 968w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-5-300x206.png 300w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-5-768x528.png 768w\" sizes=\"auto, (max-width: 968px) 100vw, 968px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">If a pre-existing GameManager enters our scene, it simply continues to exist &#8211; the <strong>Start( ) <\/strong>command will not be run on this again, and it is unaware that a new scene has begun.  Our LevelManager instance, on the other hand, will be brand new with each scene load and so we can use <strong>LevelManager.Start( )<\/strong> to trigger the mechanism that moves us into the pre-rounds state.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\n    private void Start()\n    {\n        GameManager.Gary.LevelStarted();\n    }\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">In our GameManager, we set up a corresponding function to handle the call to start the level. To further complicate things, I want to announce the level name when we first arrive, but not if we were killed and respawning &#8211; in that case we should just proceed to gameplay.   The <strong>LevelStarted( )<\/strong> command is called by the new scene&#8217;s <strong>LevelManager <\/strong>when it spawns.   That serves as the cue for our GameManager to find the new <strong>MotherShip <\/strong>object, and to run its <strong>GetReady( )<\/strong> script.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\n    public void LevelStarted()\n    {\n        \/\/ get the mother ship script\n        currentMotherShip = FindFirstObjectByType&lt;MotherShipScript&gt;();\n\n        \/\/ go to the get ready state\n        StartCoroutine(GetReady());\n    }\n\n\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\"> We add the following lines to <strong>GetReady( )<\/strong> to create a welcome message if this is the first time we have loaded this level.  The value &#8220;currentLevel&#8221; holds the level name as a string, and will compare it against the <strong>LevelManager<\/strong> &#8220;levelName&#8221; variable.  &#8211; if they do not match, this must be a new level, and so we display the level&#8217;s name for a few seconds before progressing. If they do match, this is not our first time through and we progress directly to the remainder of the <strong>GetReady( )<\/strong> script;<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\n...\n\n        \/\/ is this the first time we are in this level? \n        if (currentLevel != LevelManager.Larry.levelName)\n        {\n            messageOverlay.enabled = true;\n            messageOverlay.text = LevelManager.Larry.levelName;\n\n            yield return new WaitForSeconds(2f);\n\n            \/\/ update the current level\n            currentLevel = LevelManager.Larry.levelName;\n        }\n\n...\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\">Destroying that which Does Not Destroy<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">One final issue to address with our game flow is &#8220;what happens to the GameObject when we DO want to destroy it?&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If we complete our game and return to the &#8220;Menu&#8221; scene, you will notice that the <strong>GameManager <\/strong>is still alive with the UI in the <strong>DontDestroyOnLoad <\/strong>scene. Thankfully this is easy to resolve &#8211; we simply destroy the object manually. In this case we will use our MenuScript to detect the rogue manager and delete it.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\n    private void Start()\n    {\n        if (GameManager.Gary)\n        {\n            Destroy(GameManager.Gary.gameObject);\n        }   \n    }\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Part 2: UI Systems<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Rather than go step-by-step through the workshop, here I present a reference for the UI system as this is applicable for most projects.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"canvas\">UI: Canvas<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When you create your first UI element, Unity will automatically create a Canvas object inside of your scene, along with the \u201cEventSystem\u201d object that you can ignore for now.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The&nbsp;<strong>Canvas&nbsp;<\/strong>is the two-dimensional object that holds your user interface objects. Text, buttons, images, sliders, dropdowns\u2026 all of these UI type objects need to be contained inside of a Canvas object. All objects on the canvas are placed using the&nbsp;<strong>Rect Transform<\/strong>, a method of rectangular transformation for 2D objects. A Rect Transform defines a rectangle of pixel dimensions W (width) and H (height), and the offsets X and Y measuring the distance the pivot of the object should be placed from the \u201canchor\u201d. The anchor is a method of defining how it should be offset from it\u2019s parent object, and can be placed at a normalized value horizontally or vertically. The Anchor presets give you options for placement from the Top, Middle, or Bottom vertically, or Left, Center, or Right horizontally. These presets work similarly to text alignment in a word document or spreadsheet cell.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There are two settings inside the Canvas object which are particularly important for setting up your UI. The first is the&nbsp;<strong>Render Mode<\/strong>&nbsp;inside the Canvas component. There are three modes available:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u201cScreen Space \u2013 Overlay\u201d<\/strong>&nbsp;is the default setting and will be your most common use case. This setting causes the canvas objects to be drawn over top of your content on the screen. The canvas will cover the entire area of your screen, and resize if your window resizes. This is similar to the concept of \u201ccompositing\u201d video by adding graphics overtop of a video feed. The two do not interact visually at all.<\/li>\n\n\n\n<li><strong>\u201cScreenSpace \u2013 Camera\u201d&nbsp;<\/strong>works similar to the Overlay method, however it sets the screen out at a distance from the camera, and the camera\u2019s perspective will apply, as opposed to the overlay\u2019s planar projection style.<\/li>\n\n\n\n<li><strong>\u201cWorld Space\u201d<\/strong>&nbsp;creates a canvas object in the scene, as opposed to an overlay. This object is a rectangle but has a transform (and thus a position and orientation) within the environment itself. This is what is commonly referred to as a \u201cdiagetic\u201d interface, in that it exists within the world itself, rather than just from the perspective of the player\/observer.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The Unity Manual has&nbsp;<a href=\"https:\/\/docs.unity3d.com\/Manual\/UICanvas.html\">more descriptions and examples<\/a>&nbsp;of these modes.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"422\" height=\"127\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-20.png\" alt=\"\" class=\"wp-image-370\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-20.png 422w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-20-300x90.png 300w\" sizes=\"auto, (max-width: 422px) 100vw, 422px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The&nbsp;<strong>Canvas Scaler<\/strong>&nbsp;controls the way in which objects will respond to different window sizes. You may have noticed that often that the size and placement of UI objects in your game window do not match their size and placement when you run the game at full screen. This is because the&nbsp;<strong>Canvas Scaler<\/strong>&nbsp;is set by default to&nbsp;<strong>Constant Pixel Size.&nbsp;<\/strong>In this mode, objects retain their width and height values, unaffected by the larger screen. I recommend using the second option,&nbsp;<strong>Scale With Screen<\/strong>&nbsp;which will scale the size and positioning of UI objects up and down with the game screen size, thus preserving your layout as it appears in your editor.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"panels\">UI: Panels<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you want to group your buttons into a more formal menu, you can use the&nbsp;<strong>Panel<\/strong>&nbsp;object. This simply creates a UI Image object, but one that has a background that mimics the button background, only more transparent. By default, the Panel will fill the screen, but by changing the Rect Transform you can resize it and make objects children of this object.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Panels are an easy way to collect buttons and other UI elements into one place, and can be activated and deactivated. This can be useful for making menus that slide up or over, or populating a tabbed menu. Panels are also useful for gathering UI elements into one location, and for providing contrast for the UI elements against the game view itself.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Unity&#8217;s default panel uses the rounded rectangle UI Sprite to soften it&#8217;s edges.  If you would prefer to use a solid color, just set the <strong>Source Image<\/strong> setting to &#8220;None&#8221;.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"418\" height=\"217\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-21.png\" alt=\"\" class=\"wp-image-371\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-21.png 418w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-21-300x156.png 300w\" sizes=\"auto, (max-width: 418px) 100vw, 418px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"buttons\">UI: Buttons<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\">Creating Buttons<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">To create a button, select&nbsp;<strong>Create &gt; UI &gt; Button<\/strong>. This will generate a simple grey button with black text on your screen, and place it in your&nbsp;<strong>Canvas<\/strong>. (If you have not created a Canvas yet, Unity will generate one for you.)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can use the&nbsp;<strong>Rect Transform<\/strong>&nbsp;to position the object. Clicking the Anchor diagram will call up the Anchor Presets option. Note the modifiers listed at the top for the Shift \/ Alt keys. Pressing \u201cShift-Alt\u201d and clicking the center object will move your button to the middle of the screen.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"260\" height=\"300\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-22.png\" alt=\"\" class=\"wp-image-372\"\/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The text of your button is actually a separate text object \u2013 to change the text, find the button object in your hierarchy, and expand it to see the child objects (in this case a \u201cText\u201d object) and edit the value in the Text field.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"buttonaction\">Button Actions<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">To assign a function to a button, you must first have an object in your scene that has a script with a&nbsp;<strong>public<\/strong>&nbsp;function. In this case, we are accessing the \u201cUIScript\u201d class that has been attached to the \u201cUIManager\u201d object and lives in the scene.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With the button selected, look at the \u201cButton\u201d component and find the&nbsp;<strong>On Click ( )&nbsp;<\/strong>panel a the bottom.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"396\" height=\"109\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-23.png\" alt=\"\" class=\"wp-image-373\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-23.png 396w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-23-300x83.png 300w\" sizes=\"auto, (max-width: 396px) 100vw, 396px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Click the&nbsp;<strong>\u201c+\u201d<\/strong>&nbsp;symbol to add a new On Click action. You\u2019ll see an empty Object field.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"396\" height=\"102\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-24.png\" alt=\"\" class=\"wp-image-374\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-24.png 396w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-24-300x77.png 300w\" sizes=\"auto, (max-width: 396px) 100vw, 396px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Drag the object that with the script or component that contains the method you want to trigger with this button into the Object field.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next, click the dropdown (currently showing \u201cNo Function\u201d) and select the script or component, and then the function you want to run.  Now the button press will call that function when clicked.  Button Actions can also have up to one parameter.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"399\" height=\"108\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-26.png\" alt=\"\" class=\"wp-image-376\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-26.png 399w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-26-300x81.png 300w\" sizes=\"auto, (max-width: 399px) 100vw, 399px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"buttonsound\">Button Sounds<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">We can use the same On Click ( ) panel to emit a sound when a button is pressed. We created an empty object and added an audio clip to it, which generated an <strong>AudioSource<\/strong> component.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the <strong>OnClick( ) <\/strong> section of our button we add another action, this time adding our sound object, then setting the function dropdown to <strong>AudioSource &gt; Play( )<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">AudioSource is exposed because it is a component of the object, and the Play( ) command is available publicly.   Another handy tool is the <strong>AudioSource &gt; PlayOneShot( )<\/strong> method, which lets us play a single pass of an audioClip.   Selecting this opens another field of the AudioClip type, and we can drag that directly from our Assets folder into the field, and now it will make that noise when clicked. <\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"398\" height=\"74\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-27.png\" alt=\"\" class=\"wp-image-377\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-27.png 398w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-27-300x56.png 300w\" sizes=\"auto, (max-width: 398px) 100vw, 398px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"buttoncustom\">Button Sprites (Color &amp; Image)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">One way to change the visual appearance of your game is to edit the color of the buttons to move away from the default light gray button that Unity provides. In the Button\u2019s&nbsp;<strong>Image<\/strong>&nbsp;component, you can set the&nbsp;<strong>Color<\/strong>&nbsp;value to customize the appearance. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <strong>Button<\/strong> component gives you access to the states of the button so that you can provide feedback for selections, presses, and active vs. inactive states.   The default Button object uses <strong>Color Tint<\/strong> as the method for changing these states, which provides a subtle adjustment to the overall brightness of the button image (but not the text object)<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"416\" height=\"283\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-28.png\" alt=\"\" class=\"wp-image-378\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-28.png 416w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2023\/10\/image-28-300x204.png 300w\" sizes=\"auto, (max-width: 416px) 100vw, 416px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Another way to customize this is to create your own custom button states using <strong>sprites<\/strong>.  If you ever created your own buttons to build a website, this process will feel familiar &#8211; you generate similar images for each and then swap their placement when in the various states.  We will look more at this in the next project.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Button Navigation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You may have noticed that when we have a button selected, we can use the arrow keys to cycle through the selected option.   This is thanks to the <strong>Navigation<\/strong> system.  By default, Navigation is set to &#8220;Automatic&#8221;, which means that Unity will try to figure out the logic for itself.   Sometimes this logic does not make a great deal of sense, so if you want to see what is going on, click the Visualize button and you will see a flow diagram appear between your UI elements.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The yellow arrows indicate where the selected state will transition when a horizontal or vertical button is pressed.  If you want to set these yourself rather than rely on Unity&#8217;s automatic setting, open the dropdown and deactivate the items so that only &#8220;Explicit&#8221; is selected, then you can define the object by dragging it into each directional slot.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Part 3: Building the Executable<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">At last, the time has come to build our project &#8211; to take it from the Unity editor and turn it into a completely independent application that we can play and share.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When we &#8220;build&#8221; the game, Unity will combine all of our code, all of the assets and packages that we use in the game, and all of it&#8217;s underlying systems and combine them into an application (if you are running MacOS) or an executable and a series of support files and folders (if you are running on Windows).   Unity is also capable of building to other platforms such as Linux, Android, iOS, PS4, XBox, and HTML5.  That&#8217;s one of the advantages of working with Unity &#8211; the platform specific instructions and abstractions are already built in, making it easy to publish cross platform games.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When you are ready to publish your game, you will want to open the <strong>Build Profiles <\/strong>panel (<strong>File > Build Profiles <\/strong>).<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"898\" height=\"680\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2024\/10\/image-1.png\" alt=\"\" class=\"wp-image-530\" style=\"width:566px;height:auto\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2024\/10\/image-1.png 898w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2024\/10\/image-1-300x227.png 300w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2024\/10\/image-1-768x582.png 768w\" sizes=\"auto, (max-width: 898px) 100vw, 898px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The first thing to do is to add your current scene to the build, by clicking the <strong>Add Open Scenes<\/strong> button. This will bring your current scene into the build process. Games can have many scenes, but the build process will only include those that are listed in the <strong>Scenes List<\/strong> panel.   Also note the number to the right &#8211; these scenes have an index number defined by order in this process, that can be used to jump to the next or previous scene. This is the <strong>buildIndex<\/strong> that can be used as an identifying option by the <strong>SceneManager<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next, check your <strong>Platform Settings<\/strong> to make sure you are building towards the appropriate target.  This will be set to the platform you targeted when opening the Editor (the Target setting in Unity Hub).  If you change this now, Unity may need to reload the project.   For this project, use whatever platform you are currently on &#8211; Windows or Mac.  While it is possible for one platform to build for the other, we will not get into that in this class.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One final step &#8211; open the <strong>Player Settings<\/strong> panel by clicking the button in the lower left.  This will open up the Project Settings panel to the Player Settings tab.  The important items to know about in here are the Company and Product name, the Icon, and the Resolution.  By default, applications are set to run as Fullscreen.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"737\" height=\"426\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2024\/10\/image-2.png\" alt=\"\" class=\"wp-image-532\" style=\"width:579px;height:auto\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2024\/10\/image-2.png 737w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2024\/10\/image-2-300x173.png 300w\" sizes=\"auto, (max-width: 737px) 100vw, 737px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Once you are ready to publish your game and your settings are correct, click the&nbsp;<strong>Build&nbsp;<\/strong>or&nbsp;<strong>Build and Run<\/strong>&nbsp;button.  Unity will ask you for a location to save this.  If you are building for the Windows platform, you will want to create a new folder to contain the various files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then you&#8217;ll have to wait for a few moments while Unity does its thing.&nbsp; Now is the time where your game engine takes all of your code and objects and compiles them into raw game code and zipped binaries of data.&nbsp; Often this process is short, mostly just compressing files, but if you generating baked lighting and light\/reflection probes as part of the build process this may extend the time required to complete this.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The end result will be either an Application (Mac) or an Executable (Windows) .&nbsp; If you publish for Windows, you will get an\u201c.exe\u201d file and a \u201cData\u201d folder.  (And a few other folders&#8230; and a UnityCrashHandler.exe)&nbsp; &nbsp;You need to include these files and folders as they contain contain relevant components &#8211; for instance, &#8220;Data&#8221; holds all of your assets.&nbsp; &nbsp;(Apple users don\u2019t have to worry about this, as both their executable and data are both inside the \u201capplication\u201d container, BUT you should still zip your .app files as they are really just folder structures, and when you post an uncompressed .app to a cloud service like Box it never quite comes back out the way it went in.)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And that\u2019s it!&nbsp; Now you have a self contained game.&nbsp; Congratulations!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Part 4: Controlling Color with MeshRenderer<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">White boxes falling from the sky is a beautiful site, but it would look even better if the debris appeared to change color.  In this section we are going to look at how to access the &#8220;color&#8221; property of an object programmatically using the Mesh Renderer component.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Every 3D mesh object in our scene has a\u00a0<strong>Mesh Renderer<\/strong>\u00a0component that includes properties about how this will be visualized. Included in this is the\u00a0<strong>Materials<\/strong>\u00a0channel that holds the material to be applied to this mesh. (Actually, <strong>materials<\/strong>\u2026 meshes can have multiple materials applied to the same object). <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We can access the material properties from the <strong>MeshRenderer <\/strong>component, which is (confusingly) named \/ retrieved as <strong>Renderer<\/strong>.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\nRenderer thisRenderer = GetComponent&lt;Renderer&gt;();\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">We can change colors of materials by passing in a <strong>Color<\/strong> value. The&nbsp;<strong>Color<\/strong>&nbsp;type is similar in structure to a&nbsp;<strong>Vector3<\/strong>, but instead of (x, y, z) values, it holds (r, g, b, a) values, each one a float corresponding to the Red, Green, Blue and Alpha (transparency) channels. (If you\u2019ve never heard of rgb values to define colors, check out the&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/RGB_color_model\">Wikipedia entry on the RGB color model<\/a>.)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Also like the\u00a0<strong>Vector3<\/strong>\u00a0format, the\u00a0<strong>Color<\/strong>\u00a0type has some preset values, like\u00a0<strong>Color.red<\/strong>\u00a0or\u00a0<strong>Color.black<\/strong>. You can read more about these and the methods of the\u00a0<strong>Color<\/strong>\u00a0type in the\u00a0<a href=\"https:\/\/docs.unity3d.com\/ScriptReference\/Color.html\">Unity script API.<\/a> We can also declare a public <strong>Color<\/strong> variable and our editor will provide us with a color swatch and color selection menu.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Declaring a public <strong>Color<\/strong> value in  your class will give you a color swatch in your inspector, which makes picking colors much more convenient. <\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"453\" height=\"163\" src=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2024\/10\/image-3.png\" alt=\"\" class=\"wp-image-535\" srcset=\"https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2024\/10\/image-3.png 453w, https:\/\/courses.etc.cmu.edu\/53-353\/wp-content\/uploads\/2024\/10\/image-3-300x108.png 300w\" sizes=\"auto, (max-width: 453px) 100vw, 453px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">To change the color of our object, we can update the Renderer&#8217;s <strong>material <\/strong>with code like so: <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\nthisRenderer.material.color = Color.red;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">This will update the value of them main color channel for that object&#8217;s material.  It is important to note that this does not update the source material itself, only this individual instance. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We can also update the color of a specific channel in the shader using <strong>Material.SetColor( )<\/strong> and the channel name.  The main color of an object (often referred to as the &#8220;Albedo&#8221; color) is addressed as <strong>&#8220;_Color&#8221;<\/strong> for the built-in render pipeline, and as <strong>&#8220;_BaseColor&#8221; <\/strong>for the Universal Render Pipeline.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\nthisRenderer.material.SetColor(&quot;_Color&quot;, Color.red);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">This can also be used to edit other channels, such as the &#8220;Emission&#8221; channel (which makes your object glow).  In order to use this setting, you must first enable the channel like so: <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nthisRenderer.material.EnableKeyword(&quot;_EMISSION&quot;);  \/\/ you only need to do this once for the material\n\nthisRenderer.material.SetColor(&quot;_EmissionColor&quot;, Color.magenta);\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">In the video, both of these methods of color changing are demonstrated, as well as a &#8220;color transition&#8221; script that uses a Coroutine to move from one color value to another. <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; gutter: false; title: ; quick-code: false; notranslate\" title=\"\">\nprivate IEnumerator ColorTransition()\n    {\n        \/\/ set things at our start color\n        SetColor(startColor);\n        \/\/ start a timer\n        float currentTime = 0f;\n\n        \/\/ loop until transition is complete\n        while (currentTime &lt; transitionDuration)\n        {\n            \/\/ get my lerp amount\n            float lerpAmount = currentTime \/ transitionDuration;\n\n            \/\/ get my color value\n            Color lerpedColor = Color.Lerp(startColor, endColor, lerpAmount);\n\n            \/\/ set the color\n            SetColor(lerpedColor);\n\n            if (includeChildren)\n            {\n                SetColor(childRenders, lerpedColor);\n            }\n\n            \/\/ increment my timer\n            currentTime += Time.deltaTime;\n\n            \/\/ yield \n            yield return new WaitForEndOfFrame();\n\n        }\n        \/\/ make sure we got all the way there\n        SetColor(endColor);\n\n    }\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Here we use the <strong>Lerp<\/strong> command (which is a shmoosh of the phrase <strong><span style=\"text-decoration: underline;\">L<\/span><\/strong>inear Int<strong><span style=\"text-decoration: underline;\">erp<\/span><\/strong>olation) to return a color that falls between these values.  In order to pass in a value of our progress along the transition, we compare a &#8220;currentTime&#8221; value against a &#8220;duration&#8221; value to get the percentage completed, and pass that to our <strong>Color.Lerp( )<\/strong> command.  <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We also use a different type of yield for our coroutine &#8211; <strong>WaitForEndOfFrame( )<\/strong> which will yield and resume at the next frame.   <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We created a similar but looping effect using <strong>Mathf.PingPong( )<\/strong> to create a continual pulsing between two values over a set duration.  <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n    void Update()\n    {\n        if (renderer)\n        {\n            \/\/ pulse the object\n            Color lerpedColor = Color.Lerp(Color.black, pulseColor, Mathf.PingPong(Time.time, 1f));\n\n            \/\/ put this in the emission channel\n            renderer.material.SetColor(&quot;_EmissionColor&quot;, lerpedColor);\n        }\n    }\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Part 5: Animated Materials<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Description coming soon. <\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<pre class=\"wp-block-preformatted\">MenuScript.cs<\/pre>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; quick-code: false; notranslate\" title=\"\">\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\nusing System;\n\npublic class MenuScript : MonoBehaviour\n{\n    void Start()\n    {\n        \/\/ if the game manager still exists, get rid of it\n        if (GameManager.Gary)\n        {\n            Destroy(GameManager.Gary.gameObject); \/\/ destroy the instance\n        }\n    }\n\n    public void btn_StartTheGame()\n    {\n        SceneManager.LoadScene(&quot;Level01&quot;);\n    }\n\n    public void btn_GoToMenu()\n    {\n        SceneManager.LoadScene(&quot;MenuScene&quot;);\n    }\n\n    public void btn_GoToScene(string sceneName)\n    {\n        SceneManager.LoadScene(sceneName);\n    }\n\n\n    public void btn_Quit()\n    {\n        \/\/ tell the app to quit\n        Application.Quit();\n    }\n}\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<pre class=\"wp-block-preformatted\">LevelManager.cs<\/pre>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; quick-code: false; notranslate\" title=\"\">\nusing UnityEngine;\nusing UnityEngine.SceneManagement;\n\npublic class LevelManager : MonoBehaviour\n{\n    public static LevelManager Larry;\n\n    \/\/ scene info\n    public string levelName;\n    public string nextLevel;\n\n    void Awake()\n    {\n        Larry = this; \/\/ define the singleton\n    }\n\n    \/\/ Start is called once before the first execution of Update after the MonoBehaviour is created\n    void Start()\n    {\n        \/\/ cue the start of level\n        GameManager.Gary.LevelStarted();\n    }\n\n    public void GoToNextLevel()\n    {\n        \/\/ load the next level\n        SceneManager.LoadScene(nextLevel);\n    }\n\n    public void ReloadLevel()\n    {\n        \/\/ get the scene we are currently in, and reload it. \n        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);\n    }\n\n    private void OnDestroy()\n    {\n        if (Larry == this)\n        {\n            Larry = null; \/\/ clear the static reference\n        }\n    }\n}\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<pre class=\"wp-block-preformatted\">GameManager.cs<\/pre>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; quick-code: false; notranslate\" title=\"\">\nusing UnityEngine;\nusing TMPro;\nusing System.Collections;\n\npublic enum GameState {Menu, PreRound, Playing, PostRound, GameOver}\n\npublic class GameManager : MonoBehaviour\n{\n    \/\/ game variables\n    private int score;\n    private int livesRemaining;\n    private int LIVES_AT_START = 3;\n\n    \/\/ Game Manager Singleton\n    public static GameManager Gary;\n\n    public GameState state = GameState.Menu;\n\n    \/\/ UI Variables\n    public TextMeshProUGUI messageOverlay, livesText, scoreText;\n\n    \/\/ game objects\n    private MotherShipScript currentMotherShip;\n\n    \/\/ level info\n    public string currentLevel;\n\n    void Awake()\n    {\n        \/\/ check for an existing singleton\n        if (Gary)\n        {\n            \/\/ a singleton already exists\n            Destroy(this.gameObject);\n        }\n        else\n        {\n            \/\/ no singleton exists\n            Gary = this; \/\/ singleton definition\n            DontDestroyOnLoad(this.gameObject); \/\/ keep this alive in a pocket scene\n        }\n    }\n\n    \/\/ Start is called once before the first execution of Update after the MonoBehaviour is created\n    void Start()\n    {\n        \/\/ set up the initial game\n        StartANewGame();\n    }\n\n    private void StartANewGame()\n    {\n        \/\/ set the state\n        state = GameState.Menu;\n        \/\/ stop the music, if still playing\n        SoundManager.Steve.StopTheMusic();\n\n        \/\/ reset our score\n        score = 0;\n\n        \/\/ reset our lives\n        livesRemaining = LIVES_AT_START;\n\n        \/\/ update the UI\n        UpdateLivesUI();\n        UpdateScoreUI();\n\n        \/\/ Reset the Round\n        \/\/ ResetRound();\n    }\n\n    public void LevelStarted()\n    {\n        \/\/ get the mother ship script\n        currentMotherShip = FindFirstObjectByType&lt;MotherShipScript&gt;();\n\n        \/\/ go to the get ready state\n        StartCoroutine(GetReady());\n    }\n\n    private IEnumerator GetReady()\n    {\n        \/\/ enter preround state\n        state = GameState.PreRound;\n\n        \/\/ is this the first time we are in this level? \n        if (currentLevel != LevelManager.Larry.levelName)\n        {\n            messageOverlay.enabled = true;\n            messageOverlay.text = LevelManager.Larry.levelName;\n\n            yield return new WaitForSeconds(2f);\n\n            \/\/ update the current level\n            currentLevel = LevelManager.Larry.levelName;\n        }\n\n        \/\/ set the message\n        messageOverlay.enabled = true;\n        messageOverlay.text = &quot;Get Ready!!!&quot;;\n\n        \/\/ start the music\n        SoundManager.Steve.StartTheMusic();\n\n        \/\/ wait for 3 seconds\n        yield return new WaitForSeconds(3.0f);\n\n        \/\/ turn off the messages\n        messageOverlay.enabled = false;\n\n        StartRound();\n    }\n\n    private void StartRound()\n    {\n        \/\/ move to the playing state\n        state = GameState.Playing;\n\n        \/\/ tell the mothership to start the attack\n        currentMotherShip.StartTheAttack();\n    }\n\n    public void PlayerWasDestroyed()\n    {\n\n        \/\/ sound manager to stop all sounds and play the explosion\n        SoundManager.Steve.PlayerExplosionSequence();\n\n        \/\/ stop the attack\n        currentMotherShip.StopTheAttack();\n\n        \/\/ post round state\n        StartCoroutine(OopsState());\n    }\n\n    private IEnumerator OopsState()\n    {\n        \/\/ move to the post round state\n        state = GameState.PostRound;\n\n        \/\/ lose a life\n        livesRemaining--;\n        UpdateLivesUI();\n\n        \/\/ put up a message\n        messageOverlay.enabled = true;\n        messageOverlay.text = &quot;You Failed.&quot;;\n\n        \/\/ wait for 2s\n        yield return new WaitForSeconds(2f);\n\n        \/\/ do we have any lives left? \n        if (livesRemaining &gt; 0)\n        {\n            \/\/ reset the round\n            \/\/ ResetRound();\n\n            \/\/ reload the level\n            LevelManager.Larry.ReloadLevel();\n\n        }\n        else\n        {\n            \/\/ go to the gameover state\n            GameOverLose();\n\n        }\n    }\n\n    public void AddScore(int value)\n    {\n        \/\/ add the value to the score\n        score += value;\n        UpdateScoreUI();\n\n        \/\/ check at end of frame\n        StartCoroutine(CheckEnemiesRemaining());\n    }\n\n    private void UpdateLivesUI()\n    {\n        \/\/ update the lives UI\n        livesText.text = &quot;Lives: &quot; + livesRemaining;\n    }\n\n    private void UpdateScoreUI()\n    {\n        \/\/ update the score UI\n        scoreText.text = &quot;Score: &quot; + score.ToString(&quot;0000&quot;);\n\n    }\n\n    private void GameOverLose()\n    {\n        \/\/ you lost the game\n        state = GameState.GameOver;\n\n        messageOverlay.enabled = true;\n        messageOverlay.text = &quot;You Lost...\\nPress \\&quot;R\\&quot; to Restart&quot;;\n    }\n\n    private void GameOverWin()\n    {\n        \/\/ stop the action\n        currentMotherShip.StopTheAttack();\n\n        \/\/ you won the game\n        state = GameState.GameOver;\n        messageOverlay.enabled = true;\n        messageOverlay.text = &quot;You Won!!!\\nPress \\&quot;R\\&quot; to Restart&quot;;\n    }\n\n    private IEnumerator RoundWin()\n    {\n        state = GameState.PostRound;\n\n        \/\/ put up a good job message\n        messageOverlay.enabled = true;\n        messageOverlay.text = &quot;Round Cleared!&quot;;\n\n        yield return new WaitForSeconds(2f);\n\n        \/\/ time to go to the next level\n        LevelManager.Larry.GoToNextLevel();\n    }\n\n    private IEnumerator CheckEnemiesRemaining()\n    {\n        yield return new WaitForEndOfFrame();\n        if (currentMotherShip.transform.childCount == 0)\n        {\n            \/\/ round is over\n            StartCoroutine(RoundWin());\n        }\n    }\n}\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<pre class=\"wp-block-preformatted\">ColorDemoScript.cs<\/pre>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; quick-code: false; notranslate\" title=\"\">\nusing UnityEngine;\nusing System.Collections;\n\npublic class ColorDemoScript : MonoBehaviour\n{\n    private Renderer renderer;\n    public Color startColor = Color.white;\n    public Color endColor = Color.white;\n\n    public float transitionDuration;\n\n    public Color pulseColor = Color.black;\n\n    public bool includeChildren;\n\n    public Renderer&#x5B;] childRenders;\n\n    \/\/ Start is called once before the first execution of Update after the MonoBehaviour is created\n    void Start()\n    {\n        \/\/ get the renderer\n        renderer = GetComponent&lt;Renderer&gt;();\n\n        \/\/ set the color\n        \/\/ renderer.material.color = Color.red;\n        \/\/ renderer.material.color = new Color(0.5f, 0f, 1f);\n        \/\/ renderer.material.color = startColor;\n        SetColor(startColor);\n\n        if (includeChildren)\n        {\n            childRenders = GetComponentsInChildren&lt;Renderer&gt;();\n            SetColor(childRenders, startColor);\n        }\n\n        StartCoroutine(ColorTransition());\n\n        \/\/ activate the emission channel\n        if (renderer) { renderer.material.EnableKeyword(&quot;_EMISSION&quot;); }\n    }\n\n    \/\/ Update is called once per frame\n    void Update()\n    {\n        if (renderer)\n        {\n            \/\/ pulse the object\n            Color lerpedColor = Color.Lerp(Color.black, pulseColor, Mathf.PingPong(Time.time, 1f));\n\n            \/\/ put this in the emission channel\n            renderer.material.SetColor(&quot;_EmissionColor&quot;, lerpedColor);\n        }\n    }\n\n    private IEnumerator ColorTransition()\n    {\n        \/\/ set things at our start color\n        SetColor(startColor);\n        \/\/ start a timer\n        float currentTime = 0f;\n\n        \/\/ loop until transition is complete\n        while (currentTime &lt; transitionDuration)\n        {\n            \/\/ get my lerp amount\n            float lerpAmount = currentTime \/ transitionDuration;\n\n            \/\/ get my color value\n            Color lerpedColor = Color.Lerp(startColor, endColor, lerpAmount);\n\n            \/\/ set the color\n            SetColor(lerpedColor);\n\n            if (includeChildren)\n            {\n                SetColor(childRenders, lerpedColor);\n            }\n\n            \/\/ increment my timer\n            currentTime += Time.deltaTime;\n\n            \/\/ yield \n            yield return new WaitForEndOfFrame();\n        }\n        \/\/ make sure we got all the way there\n        SetColor(endColor);\n    }\n\n    private void SetColor(Color colorVal)\n    {\n        if (renderer)\n        {\n            renderer.material.color = colorVal;\n        }\n    }\n\n    private void SetColor(Renderer&#x5B;] theseRenders, Color colorVal)\n    {\n        foreach (Renderer thisRender in theseRenders)\n        {\n            thisRender.material.color = colorVal;\n        }\n    }\n}\n\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<pre class=\"wp-block-preformatted\">DebrisEffect.cs<\/pre>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; quick-code: false; notranslate\" title=\"\">\nusing UnityEngine;\nusing System.Collections;\n\npublic class DebrisEffect : MonoBehaviour\n{\n    private Renderer renderer;\n\n    &#x5B;Header(&quot;Color Settings&quot;)]\n    public Color startColor = Color.white;\n    public Color endColor = Color.white;\n\n    &#x5B;Header(&quot;Debris Timing&quot;)]\n    public float colorShiftDuration;\n    public float fadeDelay;\n    public float fadeDuration;\n\n    &#x5B;Header(&quot;Optional Items&quot;)]\n    public Material materialOverride;\n\n    \/\/ Start is called once before the first execution of Update after the MonoBehaviour is created\n    void Awake()\n    {\n        renderer = GetComponent&lt;Renderer&gt;();\n    }\n\n    public void StartDebrisEffect()\n    {\n        StartCoroutine(DebrisSequence());\n    }\n\n    private IEnumerator DebrisSequence()\n    {\n        \/\/ PART 1: color transition\n        SetColor(startColor);\n        \/\/ set my timer\n        float currentTime = 0f;\n\n        \/\/ transition the color\n        while (currentTime &lt; colorShiftDuration)\n        {\n            \/\/ get the lerp value\n            float lerpAmount = currentTime \/ colorShiftDuration;\n            \/\/ get the lerp color\n            Color lerpColor = Color.Lerp(startColor, endColor, lerpAmount);\n            \/\/ set the color\n            SetColor(lerpColor);\n\n            \/\/ inc timer\n            currentTime += Time.deltaTime;\n            \/\/ yield\n            yield return new WaitForEndOfFrame();\n        }\n\n        \/\/ make sure transiton completed\n        SetColor(endColor);\n\n        \/\/ PART 2: wait to fade\n        yield return new WaitForSeconds(fadeDelay);\n\n        \/\/ PART 3: Fade Object\n        currentTime = 0f;\n\n        while (currentTime &lt; fadeDuration)\n        {\n            \/\/ get the lerp value\n            float lerpAmount = currentTime \/ fadeDuration;\n            \/\/ get the lerp color\n            Color lerpColor = Color.Lerp(endColor, Color.clear, lerpAmount);\n            \/\/ set the color\n            SetColor(lerpColor);\n            \/\/ inc timer\n            currentTime += Time.deltaTime;\n            \/\/ yield\n            yield return new WaitForEndOfFrame();\n        }\n\n        \/\/ PART 4: Destroy the object\n        Destroy(this.gameObject);\n    }\n\n\n    private void SetColor(Color colorVal)\n    {\n        renderer.material.color = colorVal;\n    }\n\n    public void SetMaterial(Material thisMat)\n    {\n        renderer.material = thisMat;\n    }\n}\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<pre class=\"wp-block-preformatted\">DebrisSettings.cs<\/pre>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; quick-code: false; notranslate\" title=\"\">\nusing UnityEngine;\n\npublic class DebrisSettings : MonoBehaviour\n{\n    &#x5B;Header(&quot;Color Settings&quot;)]\n\n    &#x5B;Header(&quot;Start Color Range&quot;)]\n    public Color startColor1 = Color.white;\n    public Color startColor2 = Color.white;\n\n    &#x5B;Header(&quot;End Color Range&quot;)]\n    public Color endColor1 = Color.white;\n    public Color endColor2 = Color.white;\n\n    &#x5B;Header(&quot;Debris Timing&quot;)]\n\n    &#x5B;Header(&quot;Color Duration&quot;)]\n    &#x5B;Range(0f, 10f)]\n    public float colorShiftDuration;\n    &#x5B;Range(0, 2f)]\n    public float colorShiftDelta;\n\n    &#x5B;Header(&quot;Fade Delay Time&quot;)]\n    &#x5B;Range(2f, 10f)]\n    public float fadeDelay;\n    &#x5B;Range(0, 2f)]\n    public float fadeDelayDelta;\n\n    &#x5B;Header(&quot;Fade Duration Time&quot;)]\n    &#x5B;Range(1f, 5f)]\n    public float fadeDuration;\n    &#x5B;Range(0, 1f)]\n    public float fadeDurationDelta;\n\n    &#x5B;Header(&quot;Optional Items&quot;)]\n    public Material materialOverride;\n\n    public void ConfigureDebris(GameObject thisObj)\n    {\n        \/\/ get the object&#039;s debris effect script\n        DebrisEffect debris = thisObj.GetComponent&lt;DebrisEffect&gt;();\n\n        if (debris == null)\n        {\n            debris = thisObj.AddComponent&lt;DebrisEffect&gt;();\n        }\n\n        \/\/ override the values\n        debris.startColor = GetRandomColor(startColor1, startColor2);\n        debris.endColor = GetRandomColor(endColor1, endColor2);\n\n        \/\/ randomize the value for this chunkj\n        debris.colorShiftDuration = colorShiftDuration + Random.Range(-colorShiftDelta, colorShiftDelta);\n        debris.fadeDelay = fadeDelay + Random.Range(-fadeDelayDelta, fadeDelayDelta);\n        debris.fadeDuration = fadeDuration + Random.Range(-fadeDurationDelta, fadeDurationDelta);\n\n        if (materialOverride) { debris.SetMaterial(materialOverride); }\n\n        \/\/ ready to strat\n        debris.StartDebrisEffect();\n\n    }\n\n    private Color GetRandomColor(Color val1, Color val2)\n    {\n        \/\/ set up the color values\n        float h1, s1, v1;\n        float h2, s2, v2;\n\n        Color.RGBToHSV(val1, out h1, out s1, out v1);\n        Color.RGBToHSV(val2, out h2, out s2, out v2);\n\n\n        Color selectedColor = Random.ColorHSV(h1, h2, s1, s2, v1, v2);\n\n        return selectedColor;\n    }\n}\n<\/pre><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<pre class=\"wp-block-preformatted\">EnemyScript.cs<\/pre>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; quick-code: false; notranslate\" title=\"\">\nusing UnityEngine;\n\npublic class EnemyScript : MonoBehaviour\n{\n    public GameObject bombPrefab;\n\n    public int scoreValue;\n\n    &#x5B;Header(&quot;Enemy Swap Frames&quot;)]\n    public GameObject enemyFrame1;\n    public GameObject enemyFrame2;\n    public GameObject enemyFrameExplode;\n\n    &#x5B;Header(&quot;Explosion Parameters&quot;)]\n    public float explosionForce;\n    public float explosionRadius;\n\n    private DebrisSettings debrisManager;\n\n    \/\/ Start is called once before the first execution of Update after the MonoBehaviour is created\n    void Start()\n    {\n        \/\/ turning on the first frame, turning off the others\n        enemyFrame1.SetActive(true);\n        enemyFrame2.SetActive(false);\n        enemyFrameExplode.SetActive(false);\n\n        debrisManager = GetComponent&lt;DebrisSettings&gt;();\n    }\n\n    \/\/ Update is called once per frame\n    void Update()\n    {\n        \/\/ test code to drop a bomb\n        if (Input.GetKeyDown(KeyCode.B))\n        {\n            DropABomb();\n        }\n\n        if (Input.GetKeyDown(KeyCode.P))\n        {\n            SwapFrames();\n        }\n\n        if (Input.GetKeyDown(KeyCode.E))\n        {\n            MakeExplosion();\n        }\n    }\n\n    public void SwapFrames()\n    {\n        \/\/ reverse the active values of frames 1 &amp; 2\n        enemyFrame1.SetActive(!enemyFrame1.activeSelf);\n        enemyFrame2.SetActive(!enemyFrame2.activeSelf);\n    }\n\n    public void DropABomb()\n    {\n        \/\/ instantiate a bomb at this position (but slightly below)\n        Instantiate(bombPrefab, (transform.position + Vector3.down), Quaternion.identity);\n    }\n\n    void OnCollisionEnter(Collision collision)\n    {\n        \/\/ was it a bullet that hit us?\n        if (collision.transform.tag == &quot;PlayerBullet&quot;)\n        {\n            \/\/ destroy the bullet\n            Destroy(collision.gameObject);\n\n            \/\/ destroy this object\n            Destroy(this.gameObject);\n\n            \/\/ make the explosion\n            MakeExplosion();\n\n            \/\/ make the explosion sound\n            SoundManager.Steve.MakeEnemyExplosionSound();\n\n            \/\/ tell the game manager to count the score\n            GameManager.Gary.AddScore(scoreValue);\n        }\n    }\n\n    private void MakeExplosion()\n    {\n        \/\/ turn off the animation frames\n        \/\/ turn on the explosion frame\n\n        enemyFrame1.SetActive(false);\n        enemyFrame2.SetActive(false);\n        enemyFrameExplode.SetActive(true);\n\n        \/\/ get all of the rigidbodies\n        Rigidbody&#x5B;] enemyBlocks = GetComponentsInChildren&lt;Rigidbody&gt;();\n\n        \/\/ for each one\n        foreach (Rigidbody block in enemyBlocks)\n        {\n            \/\/ add the explosive force\n            block.AddExplosionForce(explosionForce, (transform.position + Vector3.back), explosionRadius, 0f, ForceMode.Impulse);\n\n            \/\/ tell the debris settings to adjust this object. \n            debrisManager.ConfigureDebris(block.gameObject);\n\n        }\n\n         \/\/ make the explode frame an orphan\n        enemyFrameExplode.transform.parent = null;       \n    }\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This week, we take the pieces of a game and assemble them into a full game, complete with a fully compiled executable. We will examine Unity&#8217;s Scene Management system, take a deeper dive into the User Interface (UI) by setting up a menu with custom buttons, get hands-on with the Build process, and finally look [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-78","post","type-post","status-publish","format-standard","hentry","category-recap"],"blocksy_meta":"","featured_image_urls":{"full":"","thumbnail":"","medium":"","medium_large":"","large":"","1536x1536":"","2048x2048":""},"post_excerpt_stackable":"<p>This week, we take the pieces of a game and assemble them into a full game, complete with a fully compiled executable. We will examine Unity&#8217;s Scene Management system, take a deeper dive into the User Interface (UI) by setting up a menu with custom buttons, get hands-on with the Build process, and finally look at how we can manipulate color and materials programmatically to create cool visual effects. Let&#8217;s go! Part 1: Scene Management 1A: Introduction to the SceneManager In the early days of gaming, developers would divide a game up into small chunks called&nbsp;\u201clevels\u201d.&nbsp; &nbsp;While they were useful&hellip;<\/p>\n","category_list":"<a href=\"https:\/\/courses.etc.cmu.edu\/53-353\/index.php\/category\/recap\/\" rel=\"category tag\">Course Recap<\/a>","author_info":{"name":"Tom Corbett","url":"https:\/\/courses.etc.cmu.edu\/53-353\/index.php\/author\/tcorbett\/"},"comments_num":"0 comments","_links":{"self":[{"href":"https:\/\/courses.etc.cmu.edu\/53-353\/index.php\/wp-json\/wp\/v2\/posts\/78","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/courses.etc.cmu.edu\/53-353\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/courses.etc.cmu.edu\/53-353\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/courses.etc.cmu.edu\/53-353\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/courses.etc.cmu.edu\/53-353\/index.php\/wp-json\/wp\/v2\/comments?post=78"}],"version-history":[{"count":15,"href":"https:\/\/courses.etc.cmu.edu\/53-353\/index.php\/wp-json\/wp\/v2\/posts\/78\/revisions"}],"predecessor-version":[{"id":539,"href":"https:\/\/courses.etc.cmu.edu\/53-353\/index.php\/wp-json\/wp\/v2\/posts\/78\/revisions\/539"}],"wp:attachment":[{"href":"https:\/\/courses.etc.cmu.edu\/53-353\/index.php\/wp-json\/wp\/v2\/media?parent=78"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/courses.etc.cmu.edu\/53-353\/index.php\/wp-json\/wp\/v2\/categories?post=78"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/courses.etc.cmu.edu\/53-353\/index.php\/wp-json\/wp\/v2\/tags?post=78"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}