<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daniel Rinaldi (TenaciousDan)</title>
    <description>The latest articles on DEV Community by Daniel Rinaldi (TenaciousDan) (@tenaciousdan).</description>
    <link>https://dev.to/tenaciousdan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4018344%2F1a9755e5-d536-447c-80df-757686e3e053.png</url>
      <title>DEV Community: Daniel Rinaldi (TenaciousDan)</title>
      <link>https://dev.to/tenaciousdan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tenaciousdan"/>
    <language>en</language>
    <item>
      <title>Unity Foundational Architecture: Smart Bootstrapping</title>
      <dc:creator>Daniel Rinaldi (TenaciousDan)</dc:creator>
      <pubDate>Tue, 07 Jul 2026 17:34:15 +0000</pubDate>
      <link>https://dev.to/tenaciousdan/unity-foundational-architecture-smart-bootstrapping-52pf</link>
      <guid>https://dev.to/tenaciousdan/unity-foundational-architecture-smart-bootstrapping-52pf</guid>
      <description>&lt;h3&gt;
  
  
  Table of Contents:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Understanding the Unity Initialization Lifecycle&lt;/li&gt;
&lt;li&gt;The RuntimeInitializeOnLoadMethod Attribute (And Its Limitations)&lt;/li&gt;
&lt;li&gt;The Solution: The Bootstrap Scene&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Let’s face it: out-of-the-box Unity is a fantastic engine, and it is built to cater to everyone. However, because of this it has a very basic out of the box workflow (press play to load the current scene). Any kind of logic that is related to bootstrapping (game setup, system initialization, etc.) or any specific control flow for your game is left in the hands of the developer and setting this up for every project you start can be a momentum killer.&lt;/p&gt;

&lt;p&gt;A game's foundation shouldn't rely on you starting from a specific scene in the Editor and clicking through menus or selecting a scene, nor should it rely on you manually dragging a massive GameManager prefab into every single scene in your project and then dealing with timing issues so that your bootstrapping systems initialize first. Today, I am laying down a workflow and talking about the necessary scripts needed so that you can hit play from any scene and have your bootstrapping and game initialization logic execute flawlessly every single time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Unity Initialization Lifecycle
&lt;/h2&gt;

&lt;p&gt;To build our own bootstrapping logic, we first have to understand exactly what happens when you press Play in the editor. Normally, Unity follows a strict execution order that is tied directly to the currently loaded scene(s) in the editor. This is how it goes after you hit the play button: &lt;/p&gt;

&lt;p&gt;The scene(s) are loaded into memory. This means that every GameObject and MonoBehaviour in the currently loaded scenes are created on the heap as well as any assets that are referenced from the scene objects. Awake() is called on every active MonoBehaviour in the scene(s). Then OnEnable() is called. Then Start() is called.&lt;/p&gt;

&lt;p&gt;If any of your gameplay logic relies on a GameManager, AudioManager, etc to be present, and those managers are initializing inside their own Awake() loops, you run into a classic race condition. Which script runs its Awake() first? If a gameplay script wins the race, it will try to access a manager that hasn't finished setting up yet, resulting in possible null reference exceptions or other bugs. &lt;/p&gt;

&lt;h2&gt;
  
  
  The RuntimeInitializeOnLoadMethod Attribute (And Its Limitations)
&lt;/h2&gt;

&lt;p&gt;So, how do we make it so that our bootstrapping logic always execute first before any of our gameplay logic runs? Well, you may have heard of Unity's &lt;code&gt;[RuntimeInitializeOnLoadMethod]&lt;/code&gt; attribute that allows us to "cut in line". Before any scene asset is loaded, before any GameObject initializes, and before any Awake() method is fired anywhere in your project, our bootstrapping code runs. This guarantees our core infrastructure is awake and waiting before the rest of the game even knows it exists. &lt;/p&gt;

&lt;p&gt;However, there are some restrictions to this approach. The target method for this attribute must be static, parameter-less, and inside a non-generic class. This means that if we want to inject some values into these bootstrap classes we are going to have issues. What we really want is the ability to serialize fields and use those values like we do with MonoBehaviours in our scenes but we also want our logic to always run first before any other gameplay logic. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: The Bootstrap Scene
&lt;/h2&gt;

&lt;p&gt;What we really want is the best of both worlds: the ability to use the Unity Inspector to configure our core systems, combined with a guarantee that this logic always runs first.&lt;/p&gt;

&lt;p&gt;The solution is simple: We create a dedicated "Bootstrap" scene that always loads first, which then instantly loads the actual scene we want to play. The only remaining hurdle is making this seamless in the Editor. We don't want to manually open the Bootstrap scene every time we want to test a tweak in Level 3. Luckily for us, Unity allows us to override the functionality of the Editor's play button so that we can force this workflow to behave flawlessly. (As for built games, we don't need to do anything extra other than set our Bootstrap scene as index 0 in the Build Settings).&lt;/p&gt;

&lt;p&gt;Let's take a look at how to set this up...&lt;/p&gt;

&lt;p&gt;First, let's create the Bootstrap scene. We'll create a regular scene asset and call it "Bootstrap". Next we will add this scene to the list of scenes in the build settings and set it to index 0 so that it is the first scene that your game loads when you launch the built executable.&lt;/p&gt;

&lt;p&gt;Ok, now that that's done, we need to override the play button to make the editor workflow smooth. We'll start by creating a static class called &lt;code&gt;EditorBootstrapScene.cs&lt;/code&gt; and placing the script under an &lt;code&gt;Editor&lt;/code&gt; folder (the folder name is important as we don't want to compile this script in a runtime build).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEditor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEditor.SceneManagement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine.SceneManagement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;TenaciousEditor.SceneManagement&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;/// A Bootstrap scene is a scene that is used for loading/bootstrapping systems on startup. &amp;lt;br /&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;/// The purpose of this class is to override the functionality of the play button in the editor&lt;/span&gt;
    &lt;span class="c1"&gt;/// to make sure that the Bootstrap scene is additively loaded before running the game in the Editor. &amp;lt;br /&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;/// This is convenient so that you don't need to always search for and additively load the bootstrap scene&lt;/span&gt;
    &lt;span class="c1"&gt;/// into the hierarchy when you open a new scene in the Editor.&lt;/span&gt;
    &lt;span class="c1"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;InitializeOnLoad&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EditorBootstrapScene&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;MENU_ITEM_BOOTSTRAP_SCENE_FOLDER&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Tenacious/SceneManagement/Editor Bootstrap Scene/"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;MENU_ITEM_LOAD_BOOTSTRAP_SCENE_ON_PLAY&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MENU_ITEM_BOOTSTRAP_SCENE_FOLDER&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"Load Bootstrap Scene On Play"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;MENU_ITEM_DONT_LOAD_BOOTSTRAP_SCENE_ON_PLAY&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MENU_ITEM_BOOTSTRAP_SCENE_FOLDER&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"Don't Load Bootstrap Scene On Play"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;MENU_ITEM_OPEN_BOOTSTRAP_SCENE&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MENU_ITEM_BOOTSTRAP_SCENE_FOLDER&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"Open Bootstrap Scene"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;EditorBootstrapScene&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ShouldLoadBootstrapSceneOnPlay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nf"&gt;RegisterCallbacks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;RegisterCallbacks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;EditorApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;playModeStateChanged&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;OnPlayModeChanged&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;EditorApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;playModeStateChanged&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;OnPlayModeChanged&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sceneLoaded&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;OnSceneLoaded&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sceneLoaded&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;OnSceneLoaded&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;UnregisterCallbacks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;EditorApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;playModeStateChanged&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;OnPlayModeChanged&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sceneLoaded&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;OnSceneLoaded&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;MenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MENU_ITEM_LOAD_BOOTSTRAP_SCENE_ON_PLAY&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;EnableLoadBootstrapSceneOnPlay&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;bootstrapScenePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EditorUtility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OpenFilePanel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Select Bootstrap Scene"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dataPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"unity"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;bootstrapScenePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bootstrapScenePath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dataPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Assets"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bootstrapScenePath&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;BootstrapScenePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bootstrapScenePath&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="n"&gt;ShouldLoadBootstrapSceneOnPlay&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;MenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MENU_ITEM_DONT_LOAD_BOOTSTRAP_SCENE_ON_PLAY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;EnableDontLoadBootstrapSceneOnPlayMenuItem&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ShouldLoadBootstrapSceneOnPlay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;MenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MENU_ITEM_DONT_LOAD_BOOTSTRAP_SCENE_ON_PLAY&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;DisableLoadBootstrapSceneOnPlay&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ShouldLoadBootstrapSceneOnPlay&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;MenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MENU_ITEM_OPEN_BOOTSTRAP_SCENE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;EnableOpenBootstrapScene&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ShouldLoadBootstrapSceneOnPlay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;MenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MENU_ITEM_OPEN_BOOTSTRAP_SCENE&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OpenBootstrapScene&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;EditorSceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OpenScene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BootstrapScenePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OpenSceneMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Additive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;ShouldLoadBootstrapSceneOnPlay&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;EditorBootstrapScenePrefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_loadBootstrapSceneOnPlay&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;set&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;EditorBootstrapScenePrefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_loadBootstrapSceneOnPlay&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="nf"&gt;RegisterCallbacks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt;
                    &lt;span class="nf"&gt;UnregisterCallbacks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;BootstrapScenePath&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;EditorBootstrapScenePrefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_bootstrapScenePath&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;EditorBootstrapScenePrefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_bootstrapScenePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnPlayModeChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PlayModeStateChange&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// TODO&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnSceneLoaded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Scene&lt;/span&gt; &lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoadSceneMode&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// TODO&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EditorSessionState&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SessionState&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;KEY_PREFIX&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PlayerSettings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;productGUID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EditorBootstrapScene&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;KEY_PREVIOUS_ACTIVE_SCENE_PATH&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;KEY_PREFIX&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ShouldLoadBootstrapSceneOnPlay&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_previousActiveScenePath&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_PREVIOUS_ACTIVE_SCENE_PATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BootstrapScenePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;SetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_PREVIOUS_ACTIVE_SCENE_PATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EditorBootstrapScenePrefs&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;KEY_PREFIX&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;PlayerSettings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;productGUID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EditorBootstrapScene&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LOAD_BOOTSTRAP_SCENE_ON_PLAY&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;KEY_PREFIX&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_loadBootstrapSceneOnPlay&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;BOOTSTRAP_SCENE_PATH&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;KEY_PREFIX&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_bootstrapScenePath&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;_loadBootstrapSceneOnPlay&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;EditorPrefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOAD_BOOTSTRAP_SCENE_ON_PLAY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;EditorPrefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LOAD_BOOTSTRAP_SCENE_ON_PLAY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_bootstrapScenePath&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;EditorPrefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BOOTSTRAP_SCENE_PATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;EditorPrefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BOOTSTRAP_SCENE_PATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code should add a menu item in the top toolbar that allows us to select and set a Bootstrap scene via a file menu dialog popup. Once set, we will save the file path to the bootstrap scene to the local EditorPrefs that (by the way) should not get pushed to git. Now let's finish writing the empty callback functions OnPlayModeChanged and OnSceneLoaded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnPlayModeChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PlayModeStateChange&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;ShouldLoadBootstrapSceneOnPlay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EditorApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isPlaying&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EditorApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isPlayingOrWillChangePlaymode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// user pressed the play button...&lt;/span&gt;
        &lt;span class="n"&gt;EditorSessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_previousActiveScenePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetActiveScene&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EditorSceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SaveCurrentModifiedScenesIfUserWantsTo&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;bootstrapScenePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BootstrapScenePath&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Scene&lt;/span&gt; &lt;span class="n"&gt;bootstrapScene&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;EditorSceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OpenScene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bootstrapScenePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OpenSceneMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Additive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="c1"&gt;// active scene is loaded first, so we set the active scene to be the bootstrap scene&lt;/span&gt;
                &lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetActiveScene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bootstrapScene&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;catch&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Bootstrap Scene not found: `&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bootstrapScenePath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;`"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;EditorApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isPlaying&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// user canceled the save operation...&lt;/span&gt;
            &lt;span class="n"&gt;EditorApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isPlaying&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// user pressed stop button or canceled play...&lt;/span&gt;
        &lt;span class="n"&gt;Scene&lt;/span&gt; &lt;span class="n"&gt;previousActiveScene&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetSceneByPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EditorSessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_previousActiveScenePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;previousActiveScene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetActiveScene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;previousActiveScene&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnSceneLoaded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Scene&lt;/span&gt; &lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LoadSceneMode&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EditorSessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_previousActiveScenePath&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EditorSessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_previousActiveScenePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// at this point the bootstrap scene was already loaded and Awake() methods were invoked, revert to previous active scene&lt;/span&gt;
        &lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetActiveScene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetSceneByPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EditorSessionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_previousActiveScenePath&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this code, we now have a way to set a bootstrap scene and then additively load it when the user presses play. We make sure to set the bootstrap scene as the active scene so that awake methods are prioritized in that scene in the first frame. Afterwards, we set the previously active scene back to being the active scene and then let the scene loading process continue as normal.&lt;/p&gt;

&lt;p&gt;So what now? Well, now we can add Singletons or Services we want to run on game start in order to initialize key systems in this new scene we created. It's important that we tell all the devs on the team to make sure that they set the Bootstrap scene in the editor if they want to test gameplay logic that requires that key game systems have already been setup and initialized. This is as simple as adding a note in the project's README about this.&lt;/p&gt;

&lt;p&gt;There is one last thing that we need to do. In a built game, if we set the bootstrap scene as scene index 0, nothing will happen. This is because we still need a script to load the actual first scene in a built game. To do that let's create a MonoBehaviour script called &lt;code&gt;Bootstrap.cs&lt;/code&gt; and let's make sure this is NOT placed inside an &lt;code&gt;Editor&lt;/code&gt; folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;UnityEngine.SceneManagement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Tenacious.SceneManagement&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;/// This script should be placed on a game object inside a Bootstrap Scene. &lt;/span&gt;
    &lt;span class="c1"&gt;/// In a build, this script will load the next scene (build index + 1) at the end of the first frame.&lt;/span&gt;
    &lt;span class="c1"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Bootstrap&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;StartCoroutine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;CR_LoadNextScene&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;IEnumerator&lt;/span&gt; &lt;span class="nf"&gt;CR_LoadNextScene&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;WaitForEndOfFrame&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="nf"&gt;LoadNextScene&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;LoadNextScene&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isEditor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sceneCount&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UnloadSceneAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;SceneManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LoadScene&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gameObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buildIndex&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this script created and attached to a GameObject in our Bootstrap scene, we now have it so that in a build, assuming the Bootstrap scene is loaded first, during the first frame we will call awake and start on all MonoBehaviours in the Bootstrap scene and after the first frame has finished we will load the next scene (bootstrap scene index + 1).&lt;/p&gt;

&lt;p&gt;Now we can add whatever game objects we want to the bootstrap scene and initialize whatever we need in one place. We also have dependency injection via Unity's &lt;code&gt;[SerializeField]&lt;/code&gt; if needed. In my next blog post we will discuss Single Instance Systems (Singletons/Services) which have single instances that are tied to the game instance itself.&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>gamedev</category>
      <category>architecture</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Unity Foundational Architecture: Project Scaffolding</title>
      <dc:creator>Daniel Rinaldi (TenaciousDan)</dc:creator>
      <pubDate>Tue, 07 Jul 2026 17:34:01 +0000</pubDate>
      <link>https://dev.to/tenaciousdan/unity-foundational-architecture-project-scaffolding-4gni</link>
      <guid>https://dev.to/tenaciousdan/unity-foundational-architecture-project-scaffolding-4gni</guid>
      <description>&lt;h3&gt;
  
  
  Table of Contents:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;
Scaffolding

&lt;ul&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;Project Settings&lt;/li&gt;
&lt;li&gt;Project Folder Structure&lt;/li&gt;
&lt;li&gt;TextMesh Pro&lt;/li&gt;
&lt;li&gt;Scenes&lt;/li&gt;
&lt;li&gt;Code Modules&lt;/li&gt;
&lt;li&gt;README&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Push the Initial Commit&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Great architecture in Unity is entirely about drawing the right boundaries. Whether you are building a view-first UI framework or completely decoupling your core logic from your visual representation, the success of those systems is dictated by your initial project setup and that poor scaffolding will fight you evry step of the way. In this article we are going to look at how to properly setup and structure a brand new Unity project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaffolding
&lt;/h2&gt;

&lt;p&gt;In this article, we are going to setup some basic scaffolding that most Unity projects will need (one way or another). Scaffolding is about setting up the foundational environment of a project. The goal is to handle all the repetitive, baseline setup so you can immediately start writing actual feature code.&lt;/p&gt;

&lt;p&gt;After creating a new Unity project, there's a few things that Unity devs do but we are going to focus on the shared setup process (we're skipping things that are only local like editor layouts, IDE setup, etc).&lt;/p&gt;

&lt;h3&gt;
  
  
  Git
&lt;/h3&gt;

&lt;p&gt;Next we'll create our &lt;code&gt;.gitignore&lt;/code&gt; and a &lt;code&gt;.gitattributes&lt;/code&gt; files.&lt;br&gt;&lt;br&gt;
For the &lt;code&gt;.gitignore&lt;/code&gt; we can use the following file which should be placed at the root of your project folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="c"&gt;##################################################
# Unity
##################################################
&lt;/span&gt;
&lt;span class="c"&gt;# Unity-generated folders
&lt;/span&gt;.&lt;span class="n"&gt;utmp&lt;/span&gt;/
/[&lt;span class="n"&gt;Ll&lt;/span&gt;]&lt;span class="n"&gt;ibrary&lt;/span&gt;/
/[&lt;span class="n"&gt;Ll&lt;/span&gt;]&lt;span class="n"&gt;ogs&lt;/span&gt;/
/[&lt;span class="n"&gt;Tt&lt;/span&gt;]&lt;span class="n"&gt;emp&lt;/span&gt;/
/[&lt;span class="n"&gt;Oo&lt;/span&gt;]&lt;span class="n"&gt;bj&lt;/span&gt;/
/[&lt;span class="n"&gt;Bb&lt;/span&gt;]&lt;span class="n"&gt;uild&lt;/span&gt;/
/[&lt;span class="n"&gt;Bb&lt;/span&gt;]&lt;span class="n"&gt;uilds&lt;/span&gt;/
/[&lt;span class="n"&gt;Uu&lt;/span&gt;]&lt;span class="n"&gt;ser&lt;/span&gt;[&lt;span class="n"&gt;Ss&lt;/span&gt;]&lt;span class="n"&gt;ettings&lt;/span&gt;/

&lt;span class="c"&gt;# Unity 6 : ignore recovery folder created upon restarting after a crash.
&lt;/span&gt;/[&lt;span class="n"&gt;Aa&lt;/span&gt;]&lt;span class="n"&gt;Assets&lt;/span&gt;/&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="n"&gt;Recovery&lt;/span&gt;/
/[&lt;span class="n"&gt;Aa&lt;/span&gt;]&lt;span class="n"&gt;Assets&lt;/span&gt;/&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="n"&gt;Recovery&lt;/span&gt;.&lt;span class="n"&gt;meta&lt;/span&gt;

&lt;span class="c"&gt;# ignore the asset store tools plugin
&lt;/span&gt;/[&lt;span class="n"&gt;Aa&lt;/span&gt;]&lt;span class="n"&gt;ssets&lt;/span&gt;/&lt;span class="n"&gt;AssetStoreTools&lt;/span&gt;*

&lt;span class="c"&gt;# Explicitly track Unity's package manifest and packages-lock json files
&lt;/span&gt;!**/[&lt;span class="n"&gt;Pp&lt;/span&gt;]&lt;span class="n"&gt;ackages&lt;/span&gt;/&lt;span class="n"&gt;manifest&lt;/span&gt;.&lt;span class="n"&gt;json&lt;/span&gt;
!**/[&lt;span class="n"&gt;Pp&lt;/span&gt;]&lt;span class="n"&gt;ackages&lt;/span&gt;/&lt;span class="n"&gt;packages&lt;/span&gt;-&lt;span class="n"&gt;lock&lt;/span&gt;.&lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="c"&gt;# Autogenerated VS/MD/Consulo solution and project files
&lt;/span&gt;&lt;span class="n"&gt;ExportedObj&lt;/span&gt;/
.&lt;span class="n"&gt;consulo&lt;/span&gt;/
*.&lt;span class="n"&gt;csproj&lt;/span&gt;
*.&lt;span class="n"&gt;unityproj&lt;/span&gt;
*.&lt;span class="n"&gt;sln&lt;/span&gt;
*.&lt;span class="n"&gt;suo&lt;/span&gt;
*.&lt;span class="n"&gt;tmp&lt;/span&gt;
*.&lt;span class="n"&gt;user&lt;/span&gt;
*.&lt;span class="n"&gt;userprefs&lt;/span&gt;
*.&lt;span class="n"&gt;pidb&lt;/span&gt;
*.&lt;span class="n"&gt;booproj&lt;/span&gt;
*.&lt;span class="n"&gt;svd&lt;/span&gt;
*.&lt;span class="n"&gt;pdb&lt;/span&gt;
*.&lt;span class="n"&gt;mdb&lt;/span&gt;
*.&lt;span class="n"&gt;opendb&lt;/span&gt;
*.&lt;span class="n"&gt;VC&lt;/span&gt;.&lt;span class="n"&gt;db&lt;/span&gt;

&lt;span class="c"&gt;# Unity3D generated meta files
&lt;/span&gt;*.&lt;span class="n"&gt;pidb&lt;/span&gt;.&lt;span class="n"&gt;meta&lt;/span&gt;
*.&lt;span class="n"&gt;pdb&lt;/span&gt;.&lt;span class="n"&gt;meta&lt;/span&gt;

&lt;span class="c"&gt;# MemoryCaptures can get excessive in size.
# They also could contain extremely sensitive data
&lt;/span&gt;/[&lt;span class="n"&gt;Mm&lt;/span&gt;]&lt;span class="n"&gt;emoryCaptures&lt;/span&gt;/

&lt;span class="c"&gt;# Recordings can get excessive in size
&lt;/span&gt;/[&lt;span class="n"&gt;Rr&lt;/span&gt;]&lt;span class="n"&gt;ecordings&lt;/span&gt;/

&lt;span class="c"&gt;# Gradle cache directory
&lt;/span&gt;.&lt;span class="n"&gt;gradle&lt;/span&gt;/

&lt;span class="c"&gt;# Unity3D generated file on crash reports
&lt;/span&gt;&lt;span class="n"&gt;sysinfo&lt;/span&gt;.&lt;span class="n"&gt;txt&lt;/span&gt;

&lt;span class="c"&gt;# Builds artifacts
&lt;/span&gt;*.&lt;span class="n"&gt;apk&lt;/span&gt;
*.&lt;span class="n"&gt;aab&lt;/span&gt;
*.&lt;span class="n"&gt;unitypackage&lt;/span&gt;
*.&lt;span class="n"&gt;app&lt;/span&gt;

&lt;span class="c"&gt;# Crashlytics generated file
&lt;/span&gt;&lt;span class="n"&gt;crashlytics&lt;/span&gt;-&lt;span class="n"&gt;build&lt;/span&gt;.&lt;span class="n"&gt;properties&lt;/span&gt;

&lt;span class="c"&gt;# Packed Addressables
&lt;/span&gt;/[&lt;span class="n"&gt;Aa&lt;/span&gt;]&lt;span class="n"&gt;ssets&lt;/span&gt;/[&lt;span class="n"&gt;Aa&lt;/span&gt;]&lt;span class="n"&gt;ddressable&lt;/span&gt;[&lt;span class="n"&gt;Aa&lt;/span&gt;]&lt;span class="n"&gt;ssets&lt;/span&gt;[&lt;span class="n"&gt;Dd&lt;/span&gt;]&lt;span class="n"&gt;ata&lt;/span&gt;/*/*.&lt;span class="n"&gt;bin&lt;/span&gt;*

&lt;span class="c"&gt;# Temporary auto-generated Android Assets
&lt;/span&gt;/[&lt;span class="n"&gt;Aa&lt;/span&gt;]&lt;span class="n"&gt;ssets&lt;/span&gt;/[&lt;span class="n"&gt;Ss&lt;/span&gt;]&lt;span class="n"&gt;treamingAssets&lt;/span&gt;/&lt;span class="n"&gt;aa&lt;/span&gt;.&lt;span class="n"&gt;meta&lt;/span&gt;
/[&lt;span class="n"&gt;Aa&lt;/span&gt;]&lt;span class="n"&gt;ssets&lt;/span&gt;/[&lt;span class="n"&gt;Ss&lt;/span&gt;]&lt;span class="n"&gt;treamingAssets&lt;/span&gt;/&lt;span class="n"&gt;aa&lt;/span&gt;/*

&lt;span class="c"&gt;##################################################
# IDEs
##################################################
&lt;/span&gt;
&lt;span class="c"&gt;# Rider
##################################################
&lt;/span&gt;/[&lt;span class="n"&gt;Aa&lt;/span&gt;]&lt;span class="n"&gt;ssets&lt;/span&gt;/&lt;span class="n"&gt;Plugins&lt;/span&gt;/&lt;span class="n"&gt;Editor&lt;/span&gt;/&lt;span class="n"&gt;JetBrains&lt;/span&gt;*
.&lt;span class="n"&gt;idea&lt;/span&gt;/

&lt;span class="c"&gt;# VS Code
##################################################
&lt;/span&gt;.&lt;span class="n"&gt;vscode&lt;/span&gt;/

&lt;span class="c"&gt;# Visual Studio
##################################################
&lt;/span&gt;.&lt;span class="n"&gt;vs&lt;/span&gt;/

&lt;span class="c"&gt;##################################################
# Custom
##################################################
&lt;/span&gt;
&lt;span class="c"&gt;# ignore any folder named 'gitignore' and its contents
&lt;/span&gt;&lt;span class="n"&gt;gitignore&lt;/span&gt;/
&lt;span class="n"&gt;gitignore&lt;/span&gt;.&lt;span class="n"&gt;meta&lt;/span&gt;

&lt;span class="c"&gt;# End of Custom ##################################
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;Custom&lt;/code&gt; section at the end. Here is where you can add custom ignore patterns. I added a pattern to ignore any folder called &lt;code&gt;gitignore&lt;/code&gt; in the project as a nice to have. This is so that devs can experiment with things locally without worrying about needing to discard/stash those changes so that they don't show up in another PR.&lt;/p&gt;

&lt;p&gt;Next we'll create the &lt;code&gt;.gitattributes&lt;/code&gt; file which is used to define how Git should track, format, and merge specific file types. But what's more important is its relation to &lt;a href="https://git-lfs.com/" rel="noopener noreferrer"&gt;Git LFS&lt;/a&gt;. Unity projects inherently contain massive binary assets like textures (.png, .psd), 3D models (.fbx, .obj), and audio clips (.wav, .mp3). Normal Git cannot handle these well and they will bloat your repository quickly. The .gitattributes file acts as the explicit instruction manual for &lt;a href="https://git-lfs.com/" rel="noopener noreferrer"&gt;Git LFS&lt;/a&gt;. It intercepts designated file extensions and flags those files to be uploaded to an external storage server (take note of all the lines ending in &lt;code&gt;lfs&lt;/code&gt;), replacing them in your standard repo with a tiny text pointer instead. Make sure that you enable &lt;a href="https://git-lfs.com/" rel="noopener noreferrer"&gt;Git LFS&lt;/a&gt; for your project. Anyways, here's the &lt;code&gt;.gitattributes&lt;/code&gt; file which should be placed at the root of your project folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="c"&gt;# Define macros (only works in top-level gitattributes files)
&lt;/span&gt;[&lt;span class="n"&gt;attr&lt;/span&gt;]&lt;span class="n"&gt;lfs&lt;/span&gt;               &lt;span class="n"&gt;filter&lt;/span&gt;=&lt;span class="n"&gt;lfs&lt;/span&gt; &lt;span class="n"&gt;diff&lt;/span&gt;=&lt;span class="n"&gt;lfs&lt;/span&gt; &lt;span class="n"&gt;merge&lt;/span&gt;=&lt;span class="n"&gt;lfs&lt;/span&gt; -&lt;span class="n"&gt;text&lt;/span&gt;
[&lt;span class="n"&gt;attr&lt;/span&gt;]&lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;json&lt;/span&gt;        &lt;span class="n"&gt;eol&lt;/span&gt;=&lt;span class="n"&gt;lf&lt;/span&gt; &lt;span class="n"&gt;linguist&lt;/span&gt;-&lt;span class="n"&gt;language&lt;/span&gt;=&lt;span class="n"&gt;json&lt;/span&gt;
[&lt;span class="n"&gt;attr&lt;/span&gt;]&lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;        &lt;span class="n"&gt;merge&lt;/span&gt;=&lt;span class="n"&gt;unityyamlmerge&lt;/span&gt; &lt;span class="n"&gt;eol&lt;/span&gt;=&lt;span class="n"&gt;lf&lt;/span&gt; &lt;span class="n"&gt;linguist&lt;/span&gt;-&lt;span class="n"&gt;language&lt;/span&gt;=&lt;span class="n"&gt;yaml&lt;/span&gt;

&lt;span class="c"&gt;# Ensure that text files that any contributor introduces to the repository have their line endings normalized
&lt;/span&gt;* &lt;span class="n"&gt;text&lt;/span&gt;=&lt;span class="n"&gt;auto&lt;/span&gt;

&lt;span class="c"&gt;# Unity source files
&lt;/span&gt;*.&lt;span class="n"&gt;cginc&lt;/span&gt;                 &lt;span class="n"&gt;text&lt;/span&gt;
*.&lt;span class="n"&gt;compute&lt;/span&gt;               &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;linguist&lt;/span&gt;-&lt;span class="n"&gt;language&lt;/span&gt;=&lt;span class="n"&gt;hlsl&lt;/span&gt;
*.&lt;span class="n"&gt;cs&lt;/span&gt;                    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;diff&lt;/span&gt;=&lt;span class="n"&gt;csharp&lt;/span&gt;
*.&lt;span class="n"&gt;hlsl&lt;/span&gt;                  &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;linguist&lt;/span&gt;-&lt;span class="n"&gt;language&lt;/span&gt;=&lt;span class="n"&gt;hlsl&lt;/span&gt;
*.&lt;span class="n"&gt;raytrace&lt;/span&gt;              &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;linguist&lt;/span&gt;-&lt;span class="n"&gt;language&lt;/span&gt;=&lt;span class="n"&gt;hlsl&lt;/span&gt;
*.&lt;span class="n"&gt;shader&lt;/span&gt;                &lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="c"&gt;# Unity JSON files
&lt;/span&gt;*.&lt;span class="n"&gt;asmdef&lt;/span&gt;                &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;json&lt;/span&gt;
*.&lt;span class="n"&gt;asmref&lt;/span&gt;                &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;json&lt;/span&gt;
*.&lt;span class="n"&gt;index&lt;/span&gt;                 &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;json&lt;/span&gt;
*.&lt;span class="n"&gt;inputactions&lt;/span&gt;          &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;json&lt;/span&gt;
*.&lt;span class="n"&gt;shadergraph&lt;/span&gt;           &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;json&lt;/span&gt;
*.&lt;span class="n"&gt;shadersubgraph&lt;/span&gt;        &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="c"&gt;# Unity UI Toolkit files
&lt;/span&gt;*.&lt;span class="n"&gt;tss&lt;/span&gt;                   &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;diff&lt;/span&gt;=&lt;span class="n"&gt;css&lt;/span&gt; &lt;span class="n"&gt;linguist&lt;/span&gt;-&lt;span class="n"&gt;language&lt;/span&gt;=&lt;span class="n"&gt;css&lt;/span&gt;
*.&lt;span class="n"&gt;uss&lt;/span&gt;                   &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;diff&lt;/span&gt;=&lt;span class="n"&gt;css&lt;/span&gt; &lt;span class="n"&gt;linguist&lt;/span&gt;-&lt;span class="n"&gt;language&lt;/span&gt;=&lt;span class="n"&gt;css&lt;/span&gt;
*.&lt;span class="n"&gt;uxml&lt;/span&gt;                  &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;linguist&lt;/span&gt;-&lt;span class="n"&gt;language&lt;/span&gt;=&lt;span class="n"&gt;xml&lt;/span&gt; &lt;span class="n"&gt;linguist&lt;/span&gt;-&lt;span class="n"&gt;detectable&lt;/span&gt;

&lt;span class="c"&gt;# Unity YAML files
&lt;/span&gt;*.&lt;span class="n"&gt;anim&lt;/span&gt;                  &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;asset&lt;/span&gt;                 &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;brush&lt;/span&gt;                 &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;controller&lt;/span&gt;            &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;flare&lt;/span&gt;                 &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;fontsettings&lt;/span&gt;          &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;giparams&lt;/span&gt;              &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;guiskin&lt;/span&gt;               &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;lighting&lt;/span&gt;              &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;mask&lt;/span&gt;                  &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;mat&lt;/span&gt;                   &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;meta&lt;/span&gt;                  &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;mixer&lt;/span&gt;                 &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;overrideController&lt;/span&gt;    &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;playable&lt;/span&gt;              &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;prefab&lt;/span&gt;                &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;preset&lt;/span&gt;                &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;renderTexture&lt;/span&gt;         &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;scenetemplate&lt;/span&gt;         &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;shadervariants&lt;/span&gt;        &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;signal&lt;/span&gt;                &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;spriteatlas&lt;/span&gt;           &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;spriteatlasv2&lt;/span&gt;         &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;terrainlayer&lt;/span&gt;          &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;unity&lt;/span&gt;                 &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;physicMaterial&lt;/span&gt;        &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;
*.&lt;span class="n"&gt;physicsMaterial2D&lt;/span&gt;     &lt;span class="n"&gt;unity&lt;/span&gt;-&lt;span class="n"&gt;yaml&lt;/span&gt;

&lt;span class="c"&gt;# Unity LFS
&lt;/span&gt;*.&lt;span class="n"&gt;cubemap&lt;/span&gt;               &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;unitypackage&lt;/span&gt;          &lt;span class="n"&gt;lfs&lt;/span&gt;

&lt;span class="c"&gt;## 3D models
&lt;/span&gt;*.&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="n"&gt;dm&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="n"&gt;ds&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;blend&lt;/span&gt;                 &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;blend1&lt;/span&gt;                &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;c4d&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;collada&lt;/span&gt;               &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;dae&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;dxf&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;FBX&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;fbx&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;jas&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;lws&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;lxo&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;ma&lt;/span&gt;                    &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;max&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;mb&lt;/span&gt;                    &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;obj&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;ply&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;skp&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;stl&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;ztl&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;

&lt;span class="c"&gt;## Audio
&lt;/span&gt;*.&lt;span class="n"&gt;aif&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;aiff&lt;/span&gt;                  &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;it&lt;/span&gt;                    &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;mod&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;mp3&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;ogg&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;s3m&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;wav&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;xm&lt;/span&gt;                    &lt;span class="n"&gt;lfs&lt;/span&gt;

&lt;span class="c"&gt;## Video
&lt;/span&gt;*.&lt;span class="n"&gt;asf&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;avi&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;flv&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;mov&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;mp4&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;mpeg&lt;/span&gt;                  &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;mpg&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;ogv&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;wmv&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;

&lt;span class="c"&gt;## Images
&lt;/span&gt;*.&lt;span class="n"&gt;bmp&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;exr&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;gif&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;hdr&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;iff&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;jpeg&lt;/span&gt;                  &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;jpg&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;pict&lt;/span&gt;                  &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;png&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;psd&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;tga&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;tif&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;tiff&lt;/span&gt;                  &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;webp&lt;/span&gt;                  &lt;span class="n"&gt;lfs&lt;/span&gt;

&lt;span class="c"&gt;## Compressed Archive
&lt;/span&gt;*.&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;                    &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;bz2&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;gz&lt;/span&gt;                    &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;rar&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;tar&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;zip&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;

&lt;span class="c"&gt;## Compiled Dynamic Library
&lt;/span&gt;*.&lt;span class="n"&gt;dll&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;pdb&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;so&lt;/span&gt;                    &lt;span class="n"&gt;lfs&lt;/span&gt;

&lt;span class="c"&gt;## Fonts
&lt;/span&gt;*.&lt;span class="n"&gt;otf&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;ttf&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;

&lt;span class="c"&gt;## Executable/Installer
&lt;/span&gt;*.&lt;span class="n"&gt;apk&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;
*.&lt;span class="n"&gt;exe&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;

&lt;span class="c"&gt;## Documents
&lt;/span&gt;*.&lt;span class="n"&gt;pdf&lt;/span&gt;                   &lt;span class="n"&gt;lfs&lt;/span&gt;

&lt;span class="c"&gt;## .a files (Static Libraries): These are archive files often used for compiled C++ static libraries, frequently used in Unity projects for iOS native plugins or specialized plug-in libraries.
&lt;/span&gt;*.&lt;span class="n"&gt;a&lt;/span&gt;                     &lt;span class="n"&gt;lfs&lt;/span&gt;

&lt;span class="c"&gt;## Spine export file for Unity
&lt;/span&gt;*.&lt;span class="n"&gt;skel&lt;/span&gt;.&lt;span class="n"&gt;bytes&lt;/span&gt;            &lt;span class="n"&gt;lfs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Project Settings
&lt;/h3&gt;

&lt;p&gt;You should configure any initial project settings in the Project Settings window which you can open by selecting &lt;code&gt;Edit &amp;gt; Project Settings...&lt;/code&gt; in the top toolbar. While many of the settings here are project specific there are a few that you should adjust right away.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Player&lt;/code&gt; settings: 

&lt;ul&gt;
&lt;li&gt;You should update the &lt;code&gt;Company Name&lt;/code&gt;, &lt;code&gt;Product Name&lt;/code&gt;, and &lt;code&gt;Version&lt;/code&gt; fields so that they are not set to the default.&lt;/li&gt;
&lt;li&gt;You should also configure the &lt;code&gt;Splash Image&lt;/code&gt;. I usually just set it to this (see image below) and simply append to the list of logos when a logo for the game is ready:
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6vj5d5lep8t5bzau7mne.png" alt="Splash Image Configuration" width="748" height="658"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Editor&lt;/code&gt; settings:

&lt;ul&gt;
&lt;li&gt;You should set &lt;code&gt;Asset Serialization &amp;gt; Mode&lt;/code&gt; to &lt;code&gt;Force Text&lt;/code&gt; to force YAML instead of binary for asset files. This makes it easier to work with Git and Unity YAML-Merge.&lt;/li&gt;
&lt;li&gt;You should also set &lt;code&gt;Enter Play Mode Settings &amp;gt; When entering Play Mode&lt;/code&gt; to &lt;code&gt;Reload Scene Only&lt;/code&gt; to enable fast enter play mode. This will be the default setting in Unity 6.5+ and moving forward as they are deprecating and removing the option to Reload Domain when entering Play Mode. This makes it so that Unity does not destroy the entire C# code domain state and does not reload any assemblies which means that static data, variables, events and memory are not reset when entering play mode in editor. The plus side is that this makes you write cleaner code and also makes entering play mode super-super quick!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project Folder Structure
&lt;/h3&gt;

&lt;p&gt;Let's start with folder structure. This is the folder hierarchy that I use for my projects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[PROJECT_ROOT]/
├── Assets/
│   ├── _Project/
│   │   ├── _Modules/
│   │   │   └── Default/
│   │   │       ├── _Runtime/
│   │   │       └── Editor/
│   │   ├── _Scenes/
│   │   ├── Art/
│   │   ├── Audio/
│   │   │   ├── Music/
│   │   │   └── Sounds/
│   │   ├── Resources/
│   │   ├── Sandbox/
│   │   ├── Settings/
│   │   └── StreamingAssets/
│   │       └── Videos/
│   ├── TextMesh Pro/
│   └── ...
├── Packages/
├── .gitignore
├── .gitattributes
├── README.md
└── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key take-aways from this folder structure is the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://docs.unity3d.com/6000.3/Documentation/Manual/SpecialFolders.html" rel="noopener noreferrer"&gt;Special Folders&lt;/a&gt; that Unity reserves that we have setup prematurely (Editor, Resources, StreamingAssets). Note that you can have multiple of some folders in your project and Unity will consider/group them all together when processing them.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;_&lt;/code&gt; prefix for some of the folder names is just so that Unity orders it first inside its parent folder in the project explorer which uses alphabetical sorting for folders.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;_Project&lt;/code&gt; folder where we have already setup a neat standard moving forward for how we separate and organize our project's code modules (more on that later) from other assets like &lt;code&gt;_Scenes&lt;/code&gt; (level design), &lt;code&gt;Art&lt;/code&gt;, &lt;code&gt;Settings&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;_Scenes&lt;/code&gt; folder, where we keep the scene files as well as any files related to a given scene. Usually I create a folder with the same name as the scene and place stuff like baked navmesh and lighting files there (unity will do this automatically for you as well when you bake navmesh or lighting).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Art&lt;/code&gt; folder. This folder is for artists only (no code). Many artists want to just focus on art and be able to have their own project structure for organization and this folder allows them to do that. Textures, images, 3D models, all go in here.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Audio&lt;/code&gt; folder. Again, this is a folder where audio engineers can have their own file organization. Although I usually impose a &lt;code&gt;Music&lt;/code&gt; and &lt;code&gt;Sounds&lt;/code&gt; subfolder so that my code can easily scan a single folder when generating assets that connect the audio to in-game systems (so I'll leave this up to you).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Sandbox&lt;/code&gt; folder. This is where devs can roughly test things and place files that might not ever be used in production if a feature they are prototyping is rejected. Essentially, this is where someone can prototype a feature. I usually create subfolders with the names of each dev in this folder so each dev has there own working directory.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Settings&lt;/code&gt; folder. This folder is to group all the settings/configuration files for the project. Things like &lt;code&gt;InputSystem&lt;/code&gt; (.inputactions file), &lt;code&gt;Localization&lt;/code&gt; (locales, tables, and settings), &lt;code&gt;URP Settings&lt;/code&gt; (URP Render Pipeline assets, etc),&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;TextMesh Pro&lt;/code&gt; and &lt;code&gt;Assets/...&lt;/code&gt; folders. These folders sit outside the &lt;code&gt;_Project&lt;/code&gt; folder and are mainly for external asset packages like the ones you'd download off the asset store. It may be tempting to group them under a &lt;code&gt;third party&lt;/code&gt; folder but I've seen some assets that assume they are placed at the root of the assets folder and if not placed there don't function properly as a result. While this is a very small minority of asset plugins, it's best to side with caution here. Besides, since we prefixed the project folder with &lt;code&gt;_&lt;/code&gt; these external assets will always end up sorted at the end of the project explorer window.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  TextMesh Pro
&lt;/h3&gt;

&lt;p&gt;In the editor toolbar menu at the top, select &lt;code&gt;Window &amp;gt; TextMeshPro &amp;gt; Import TMP Essential Resources&lt;/code&gt;. This will import the TextMesh Pro essential resources. This will also trigger when you add your first TMP Text component in a UI. You might want to configure a default font at some point but I'll leave that up to you. &lt;/p&gt;

&lt;h3&gt;
  
  
  Scenes
&lt;/h3&gt;

&lt;p&gt;There are at least 2-3 scenes that I create at the start of every project.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Bootstrap&lt;/code&gt; scene: This scene is the entry point of the application in a build and should be set as index 0 in the build settings scene list. For more information about bootstrapping see my other &lt;a href="https://dev.to/tenaciousdan/unity-foundational-architecture-smart-bootstrapping-52pf"&gt;article&lt;/a&gt;. If you prefer to use your own bootstrapping logic than you can skip creating this scene however I strongly advise reading the other article and setting up your bootstrapping logic using a scene.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Splash&lt;/code&gt; scene (optional): This scene is only needed if you want to have something more flashy as a splash screen other than the built in logo fades with a plain background (think animations or 3D scene or particle effects). If you implement this scene don't forget to add it as index 1 (after the bootstrap scene) in the build settings scene list.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Welcome&lt;/code&gt; scene: Every game has this, it's the first scene where the player has input agency and is usually reffered to as "the main menu". Here I usually just setup a UI view with the Game's title at the top and a basic vertical menu with some basic buttons which have some simple functionality. The 2 buttons I implement are &lt;code&gt;Play&lt;/code&gt; (brings you to another scene) and &lt;code&gt;Quit&lt;/code&gt; which calls &lt;code&gt;Application.Quit()&lt;/code&gt;. This scene should be set as index 2 (after the splash scene) in the build settings scene list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When creating scenes I also like to impose a structure to the scene hierarchy. To make it easier to keep the same initial hierarchy when creating scenes, I create a scene template via &lt;code&gt;RightClick in Project Window &amp;gt; Create &amp;gt; Scene &amp;gt; Scene Template&lt;/code&gt;. This will create a scenetemplate asset that you can point to a scene to use as the template. So create a regular scene and place it adjacent to the scenetemplate asset and then simply drag the scene into the &lt;code&gt;Template Scene&lt;/code&gt; field of the scenetemplate asset's inspector. Also make sure to check &lt;code&gt;Pin in New Scene Dialog&lt;/code&gt; so that our template stands out.  &lt;/p&gt;

&lt;p&gt;My basic scene template is as follows:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fraobufu9hkubkr9xp20d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fraobufu9hkubkr9xp20d.png" alt="Basic Scene Template" width="326" height="110"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Everything in &lt;code&gt;[]&lt;/code&gt; is at position &lt;code&gt;(0,0,0)&lt;/code&gt; and has zero rotation and a scale of &lt;code&gt;(1,1,1)&lt;/code&gt;. The &lt;code&gt;[Context]&lt;/code&gt; object and everything under it are mostly for contextual things like navmesh, players spawned at runtime, level specific managers, etc. The &lt;code&gt;[Environment]&lt;/code&gt; object is for the level designer and is meant to contain all the 3D models and gameobjects that make up the 3D world as well as any lights, post processing volumes, etc.&lt;br&gt;&lt;br&gt;
To use this Scene Template that we created, we just have to press &lt;code&gt;Ctrl+N&lt;/code&gt; in the Editor and we should see our scene template in the New Scene Dialog list.&lt;/p&gt;
&lt;h3&gt;
  
  
  Code Modules
&lt;/h3&gt;

&lt;p&gt;Every project can, at some point, have code that can be grouped into its own module and even if you don't have any initially it's good to set this structure up now. The &lt;code&gt;_Modules&lt;/code&gt; folder is where all your codebase will live. Each code module should be separated within its own folder and have assembly definitions to enforce separation of concerns and to ensure a clean dependency between modules and assemblies. I will not go over assembly definitions in this article but I will explain the one or two that every Unity dev uses whether they know it or not which is the "Default" hidden &lt;code&gt;Assembly-CSharp&lt;/code&gt; and &lt;code&gt;Assembly-CSharp-Editor&lt;/code&gt; assemblies.  &lt;/p&gt;

&lt;p&gt;The default &lt;code&gt;Assembly-CSharp&lt;/code&gt; assembly (which you may have already seen in your IDE) is the default assembly that any code under the &lt;code&gt;Assets/&lt;/code&gt; lives in. Unity sets this assembly up by default and automatically makes it depend on every single other assembly in the project. This assembly is also a "Runtime" assembly which is a term I use to mean that the code in this assembly is compiled and packaged in our built game. Basically any code we add under &lt;code&gt;_Modules/Default/Runtime/&lt;/code&gt; will be part of this default &lt;code&gt;Assembly-CSharp&lt;/code&gt; assembly, which is why the folders are structured this way.  &lt;/p&gt;

&lt;p&gt;You may have noticed that there is also an &lt;code&gt;Editor&lt;/code&gt; folder under the &lt;code&gt;_Modules/Default/&lt;/code&gt; folder. This is because if we write Editor code we do not want this code to be compiled and packaged with our built game, in fact Unity will throw errors when building if this is the case. By adding Editor specific scripts under this folder, Unity will automatically add them into a default &lt;code&gt;Assembly-CSharp-Editor&lt;/code&gt; assembly (which you also may have seen in your IDE before). This entire assembly is automatically excluded from all builds except for editor which means that the code here is not packaged with your game builds and Unity will not throw any errors. So you should use this folder for any Editor specific code.&lt;/p&gt;

&lt;p&gt;You can make other modules like a "Core" module which contains interfaces and common logic if you want but you'll have to create your own assembly definitions for that and that is a whole other topic. If you do create another module, you should follow the same folder structure where you create the module folder "Core" and under it create the "_Runtime" and "Editor" folders which will house their respective assembly definition files.&lt;/p&gt;
&lt;h3&gt;
  
  
  README
&lt;/h3&gt;

&lt;p&gt;Finally, you should create a README.md with instructions on how to clone the project and install it on your machine.&lt;br&gt;&lt;br&gt;
Here's a good starting point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# PROJECT_NAME&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_NAME&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;#project_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Installation&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;#installation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;    -&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Clone Project&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;#clone-project-using-git&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;#configuration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;    -&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Setup Custom Mergetool (optional)&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;#setup-custom-mergetool-optional&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Getting Started&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;#getting-started&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="gu"&gt;## Installation&lt;/span&gt;

&lt;span class="gu"&gt;### Clone Project Using Git&lt;/span&gt;

&lt;span class="p"&gt;```&lt;/span&gt;&lt;span class="nl"&gt;
&lt;/span&gt;cd [CHOOSE_A_DIRECTORY_TO_STORE_THE_REPO]
git clone [INSERT_URL_TO_GIT_REPO_HERE]
&lt;span class="p"&gt;```&lt;/span&gt;

Next, Continue to the &lt;span class="sb"&gt;`Git Configuration`&lt;/span&gt; section to configure git or just go straight to &lt;span class="sb"&gt;`Getting Started`&lt;/span&gt; section below.  

&lt;span class="gu"&gt;## Configuration&lt;/span&gt;

&lt;span class="gu"&gt;### Setup Custom Mergetool (optional)&lt;/span&gt;

UnityYAMLMerge.exe is a merge tool that aids with the merging of scene, prefab and asset files (and any other YAML files). It comes packaged with each installation of the Unity Editor, therefore if you upgrade the project version you should also update your custom merge tool to use the newer UnityYAMLMerge.exe for your version of Unity.  

You must tell Git to use UnityYAMLMerge.exe as a custom merge tool and also as a custom diff tool. It is located in the &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;UnityEditor installation folder&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://docs.unity3d.com/2021.3/Documentation/Manual/SmartMerge.html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; under &lt;span class="sb"&gt;`./Editor/Data/Tools/UnityYAMLMerge.exe`&lt;/span&gt;.  
On Windows this is located at &lt;span class="sb"&gt;`C:/Program Files/Unity/Hub/Editor/{EDITOR_VERSION}/Editor/Data/Tools/UnityYAMLMerge.exe`&lt;/span&gt;.  

Once you have setup Git to use UnityYAMLMerge, you must then tell UnityYAMLMerge what diff tool to use as a fallback. To do this, you simply need to edit &lt;span class="sb"&gt;`mergespecfile.txt`&lt;/span&gt; located adjacent (within the same folder) to the UnityYAMLMerge.exe file.  
Follow the instructions in this txt file to setup a fallback merge/diff tool.  

For more info on UnityYAML merge (Smart Merge) and setup with git or git GUIs see : https://docs.unity3d.com/2021.3/Documentation/Manual/SmartMerge.html  

&lt;span class="gu"&gt;## Getting Started  &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how I included a paragraph in the README about Unity YAML-Merge? That's because this is not something that you can do for the whole project. Each developer should be setting this up locally for every project that they are collaborating on. If you are working on a project and are arguing 90% of the time about who is currently modifying a scene or prefab file then you are using Unity wrong in my opinion. Unity YAML-Merge allows you to merge scene, prefab, and asset files without breaking or corrupting anything. There are some edge cases but from my experience they are far and in between and are generally not an issue in practical use when work is separated cleanly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Push the Initial Commit
&lt;/h2&gt;

&lt;p&gt;With all of the above done, you can stage all your changes and push the initial commit to your main branch.&lt;/p&gt;

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