{"id":350,"date":"2021-05-01T15:35:19","date_gmt":"2021-05-01T15:35:19","guid":{"rendered":"https:\/\/bronsonzgeb.com\/?p=350"},"modified":"2021-05-01T15:35:20","modified_gmt":"2021-05-01T15:35:20","slug":"unity-architecture-pattern-structured-prefabs","status":"publish","type":"post","link":"https:\/\/bronsonzgeb.com\/index.php\/2021\/05\/01\/unity-architecture-pattern-structured-prefabs\/","title":{"rendered":"Unity Architecture Pattern: Structured Prefabs"},"content":{"rendered":"\n<p>This article shows a powerful Unity pattern that I&#8217;m calling Structured prefabs. Structured prefabs are a pattern I use to simplify prefab initialization and reduce bugs. They help to indicate the intention of the creator to other developers and lead to overall better maintainability.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What is a structured prefab?<\/h2>\n\n\n\n<p>Like I mentioned, a structured prefab is a pattern I use to reduce bugs and increase maintainability for all my prefabs. The idea is to add a component at the root of every prefab to identify it, and give it structure. This component often has the same name as the prefab itself, but not always. Sometimes this component won&#8217;t contain any code, sometimes it&#8217;ll only contain serialized fields, and sometimes it&#8217;ll be a full-blown MonoBehaviour with behaviours.<\/p>\n\n\n\n<p>So let&#8217;s explore all the benefits of this pattern, starting with references.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prefab References<\/h2>\n\n\n\n<p>More often than not, I see developers reference prefabs with generic <code>GameObject<\/code> fields like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class Game : MonoBehaviour {\n    public GameObject playerPrefab;\n}<\/code><\/pre>\n\n\n\n<p>There are two problems with this approach. First of all, as a developer working on the project, you&#8217;ve given me no indication of what you expect the player prefab to be. Does it require specific components to work? Most likely, yes. What developers should do instead is reference prefabs by a component, like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class Game : MonoBehaviour {\n    public Player playerPrefab;\n}<\/code><\/pre>\n\n\n\n<p>When you do it that way, you know that at the very least, the player prefab needs a <code>MonoBehaviour<\/code> of type <code>Player<\/code> at its root. What&#8217;s more, if you do this, the Inspector won&#8217;t even let you assign a prefab that\u00a0<em>doesn&#8217;t<\/em>\u00a0have a <code>Player<\/code> component on its root. You can&#8217;t accidentally assign the wrong prefab (well, you can, but the wrong prefab will have a <code>Player<\/code> component on it as well, at least). By the way, when I talk about the root, I mean the <code>GameObject<\/code> at the top of the prefab&#8217;s hierarchy, rather than buried inside the prefab.<\/p>\n\n\n\n<p>Now I&#8217;ll show how this subtle change massively improves your code&#8217;s reliability.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prefab Instantiation<\/h2>\n\n\n\n<p>This next bit is my favourite part. When you instantiate a Prefab using a generic <code>GameObject<\/code> type, the function returns a <code>GameObject<\/code>. Usually, the next step is to use <code>GetComponent<\/code> to retrieve the components you care about like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class GameManager : MonoBehaviour\n{\n\tpublic GameObject playerPrefab;\n\n\tvoid Start()\n\t{\n\t\tGameObject playerGo = Instantiate(playerPrefab);\n\t\tPlayer player = playerGo.GetComponent&lt;Player>();\n\t}\n}<\/code><\/pre>\n\n\n\n<p>Instantiating prefabs this way is pretty dangerous because there&#8217;s no guarantee the <code>Player<\/code> component will be there, and then your whole game breaks. But, did you know that if you call <code>Instantiate<\/code> using a reference to a <code>Player<\/code> component, it&#8217;ll return the <code>Player<\/code> component instead:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class GameManager : MonoBehaviour\n{\n\tpublic Player playerPrefab;\n\n\tvoid Start()\n\t{\n\t\tPlayer player = Instantiate(playerPrefab);\n\t}\n}<\/code><\/pre>\n\n\n\n<p>When you do it this way, you know with absolute certainty that you have a <code>Player<\/code> component (unless playerPrefab is null). By the way, if you use the main loop pattern from my previous article, and you avoid unnecessary null checks, you&#8217;ll know for sure that a null reference on initialization is due to not assigning something in the Inspector. Think of all the hours of your life you wasted chasing null reference errors. Now you can take that time back for the rest of your life. Spend that newly found time with your family and loved ones.<\/p>\n\n\n\n<p>Now that we&#8217;ve solved prefab references and instantiation let&#8217;s cover the last piece of the puzzle: prefab initialization.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prefab Initialization<\/h2>\n\n\n\n<p>After instantiating a prefab, you often need to initialize it before using it. You could wait for the Awake and Start methods to be called, but then you have to rely on a collection of loose initialization functions to run in an undefined order before your prefab is fully initialized. In my experience, a much simpler approach is to give your root component an initialization function that you call explicitly. For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class GameManager : MonoBehaviour\n{\n\tpublic Player playerPrefab;\n\n\tvoid Start()\n\t{\n\t\tPlayer player = Instantiate(playerPrefab);\n\t\tplayer.OnCreated(this);\n\t}\n}<\/code><\/pre>\n\n\n\n<p>By the way, you might notice I passed <code>this<\/code> into my <code>OnCreated<\/code> function. That&#8217;s because I give my objects a reference to their parent object to simplify lifetime management. It&#8217;s the owner&#8217;s job to manage any <code>GameObjects<\/code> that it creates, so having a reference to your parent makes it easier to ask to be cleaned up and destroyed. If you don&#8217;t know what I&#8217;m talking about, I recommend reading my previous article on the main loop pattern to understand how I structure my projects.<\/p>\n\n\n\n<p>Anyway, let&#8217;s get back to talking about initialization. We&#8217;ve already seen how we can remove <code>GetComponent<\/code>, <code>Start<\/code> and <code>Awake<\/code>, and make our code less error-prone, right? Well, we can take those same approaches and use them on our root component as well. In other words, rather than use <code>GetComponent<\/code> inside our <code>Player<\/code> <code>MonoBehaviour<\/code>, we can reference everything we need directly.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class Player : MonoBehaviour\n{\n\tGameManager _gameManager;\n\tpublic CharacterController characterController;\n\tpublic Animator animator;\n\tpublic Health health;\n\t\/\/etc...\n\t\n\tpublic void OnCreated(GameManager gameManager)\n\t{\n\t\t_gameManager = gameManager;\n\t\t\/\/call OnCreated on all the custom components...\n\t\thealth.OnCreated(this);\n\t}\n}<\/code><\/pre>\n\n\n\n<p>With that:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>We\u00a0<em>probably<\/em>\u00a0don&#8217;t have to use <code>GetComponent<\/code> ever again.\u00a0<\/li><li>Any null references on initialization are due to something not being assigned in the Inspector. By the way, this is a reasonable error because it shows us we&#8217;re not using the object as intended, so don&#8217;t suppress it.<\/li><li>We don&#8217;t have to deal with <code>Awake<\/code> and <code>Start<\/code> methods that create spaghetti code.<\/li><\/ul>\n\n\n\n<p>So now we&#8217;ve seen all the benefits that the Structured Prefab pattern has, from improved references, instantiation and initialization, to cleaner code and greater maintainability.<\/p>\n\n\n\n<p><strong><strong>If you liked this article,\u00a0<\/strong><a rel=\"noreferrer noopener\" target=\"_blank\" href=\"https:\/\/bronsonzgeb.com\/index.php\/join-my-mailing-list\/\"><strong>join my mailing list<\/strong><\/a><strong>\u00a0to be notified whenever a new post comes out. As a Mailing list subscriber, you could ask me to cover specific topics. So if you&#8217;d like me to write about something else,\u00a0<\/strong><a rel=\"noreferrer noopener\" target=\"_blank\" href=\"https:\/\/bronsonzgeb.com\/index.php\/join-my-mailing-list\/\"><strong>join my mailing list<\/strong><\/a><strong>\u00a0anyway and ask me.<\/strong><\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article shows a powerful Unity pattern that I&#8217;m calling Structured prefabs. Structured prefabs are a pattern I use to simplify prefab initialization and reduce bugs. They help to indicate the intention of the creator to other developers and lead to overall better maintainability. What is a structured prefab? Like I mentioned, a structured prefab [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":352,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[28,1],"tags":[30,5],"class_list":["post-350","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-architecture","category-unity-programming","tag-architecture","tag-unity"],"_links":{"self":[{"href":"https:\/\/bronsonzgeb.com\/index.php\/wp-json\/wp\/v2\/posts\/350","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bronsonzgeb.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bronsonzgeb.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bronsonzgeb.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bronsonzgeb.com\/index.php\/wp-json\/wp\/v2\/comments?post=350"}],"version-history":[{"count":1,"href":"https:\/\/bronsonzgeb.com\/index.php\/wp-json\/wp\/v2\/posts\/350\/revisions"}],"predecessor-version":[{"id":351,"href":"https:\/\/bronsonzgeb.com\/index.php\/wp-json\/wp\/v2\/posts\/350\/revisions\/351"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/bronsonzgeb.com\/index.php\/wp-json\/wp\/v2\/media\/352"}],"wp:attachment":[{"href":"https:\/\/bronsonzgeb.com\/index.php\/wp-json\/wp\/v2\/media?parent=350"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bronsonzgeb.com\/index.php\/wp-json\/wp\/v2\/categories?post=350"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bronsonzgeb.com\/index.php\/wp-json\/wp\/v2\/tags?post=350"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}