tag:akbiggs.silvrback.com,2005:/feedAlexander Biggs2015-11-18T06:40:04+11:00tag:akbiggs.silvrback.com,2005:Article/196992015-11-18T06:40:04+11:002018-08-09T00:46:37+10:00Unity Devs, stop using GameObject.Find!<h1 id="the-problem">The problem</h1>
<p><a href="https://unity3d.com/">Unity</a> offers several approaches for resolving a reference to a GameObject in the scene. A common choice is to use the object&#39;s name, either with the <a href="http://docs.unity3d.com/ScriptReference/GameObject.Find.html">GameObject.Find</a> method, which will look through all the objects in the scene, or by searching through the names of another GameObject&#39;s children for a match. Both of these options are bad practices.</p>
<p>Why? Well, let&#39;s look at a small example. Here&#39;s a script that makes some text display how many objects are inside the scene&#39;s UI canvas.</p>
<div class="highlight"><pre><span class="k">using</span> <span class="nn">UnityEngine</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">UnityEngine.UI</span><span class="p">;</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">ShowNumberOfCanvasChildren</span> <span class="p">:</span> <span class="n">MonoBehaviour</span>
<span class="p">{</span>
<span class="k">private</span> <span class="n">GameObject</span> <span class="n">_canvas</span><span class="p">;</span>
<span class="k">private</span> <span class="n">Text</span> <span class="n">_childText</span><span class="p">;</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">Start</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// grab an object in the scene called Canvas</span>
<span class="n">_canvas</span> <span class="p">=</span> <span class="n">GameObject</span><span class="p">.</span><span class="n">Find</span><span class="p">(</span><span class="s">&quot;Canvas&quot;</span><span class="p">);</span>
<span class="c1">// and grab some text in a child of the object</span>
<span class="c1">// that this script is attached to</span>
<span class="n">_childText</span> <span class="p">=</span> <span class="k">this</span><span class="p">.</span><span class="n">transform</span><span class="p">.</span><span class="n">FindChild</span><span class="p">(</span><span class="s">&quot;ChildText&quot;</span><span class="p">).</span><span class="n">GetComponent</span><span class="p">&lt;</span><span class="n">Text</span><span class="p">&gt;();</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">Update</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">// on every frame, modify that text</span>
<span class="n">_childText</span><span class="p">.</span><span class="n">text</span> <span class="p">=</span> <span class="s">&quot;Canvas child count: &quot;</span> <span class="p">+</span> <span class="n">_canvas</span><span class="p">.</span><span class="n">transform</span><span class="p">.</span><span class="n">childCount</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>This script introduces a number of problems:</p>
<ol>
<li><strong>I don&#39;t know if those objects actually exist under those names.</strong> What if I typo&#39;d &quot;Canvas&quot; as &quot;Camvas&quot;? What if the &quot;ChildText&quot; was called &quot;ChildTextObject&quot; instead? My compiler won&#39;t give me any support with these string constants, so I won&#39;t have any idea until I run the app and my script breaks.</li>
<li><strong>I can&#39;t change my scene layout without breaking this script.</strong> If I change the child text&#39;s parent, or move the text component into the parent instead of keeping the component inside the child, my script will no longer be able to find these objects, causing the application to throw errors.</li>
<li><strong>I can&#39;t rename objects freely.</strong> If I realize later that &quot;ChildText&quot; is a vague name, I might rename it inside the inspector without checking any scripts beforehand. This simple and seemingly harmless act will be violently punished with a torrent of NullReferenceExceptions.</li>
</ol>
<p>All of these issues are symptomatic of a disease in your codebase: <strong>The dependencies for your scripts are hidden away instead of being stated outright.</strong> When you attach your script, you have no idea what its requirements are. This prevents you from knowing whether or not that script can be reused throughout the codebase or if it will only work within a specific context. This breaks the whole idea that <a href="https://unity3d.com/learn/tutorials/modules/intermediate/scripting/coding-practices">your script should be a reusable component with only a single responsibility</a>.</p>
<p>This is the way your script will appear inside the inspector after you attach it to some object.</p>
<p><img alt="The inspector won&#x27;t tell you anything about what your script needs to work." src="https://silvrback.s3.amazonaws.com/uploads/53cbd6e2-1687-4a2c-8501-188187156cd3/unclear_dependencies_large.JPG" /></p>
<p>We just see at the bottom-right that it is a script, with no extra information given.</p>
<p>When I attach a script that looks like this, I think: &quot;Uhh...I guess this will work? Maybe?&quot;, and then I run my game and more often than not the whole thing will blow up in my face. This happens because I have no clue what context my script needs to work properly. Soon the developers on your team will be petrified of touching anything in the scene, worried that any small modification will break some random script.</p>
<h1 id="a-better-approach">A better approach</h1>
<p>Instead of using object names that are hidden away in our script to resolve our dependencies, let&#39;s show our dependencies in the inspector instead. This way, we know exactly what a script needs when we attach it. To do this, let&#39;s make our fields public.</p>
<div class="highlight"><pre><span class="k">using</span> <span class="nn">UnityEngine</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">UnityEngine.UI</span><span class="p">;</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">ShowNumberOfCanvasChildren</span> <span class="p">:</span> <span class="n">MonoBehaviour</span>
<span class="p">{</span>
<span class="k">public</span> <span class="n">GameObject</span> <span class="n">Canvas</span><span class="p">;</span>
<span class="k">public</span> <span class="n">Text</span> <span class="n">NumChildrenText</span><span class="p">;</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">Update</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">NumChildrenText</span><span class="p">.</span><span class="n">text</span> <span class="p">=</span> <span class="s">&quot;Canvas child count: &quot;</span> <span class="p">+</span> <span class="n">Canvas</span><span class="p">.</span><span class="n">transform</span><span class="p">.</span><span class="n">childCount</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>Alternatively, if you dislike making things public(<a href="http://programmers.stackexchange.com/a/143739">and you should</a>), you can use the <a href="http://docs.unity3d.com/ScriptReference/SerializeField.html">SerializeField</a> attribute instead to make your private variables available to edit in the inspector. The documentation seems to discourage using SerializeField with an explicit note that you will never <em>need</em> to use it, but I can&#39;t come up with any reason why you <em>shouldn&#39;t</em>.</p>
<div class="highlight"><pre><span class="k">using</span> <span class="nn">UnityEngine</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">UnityEngine.UI</span><span class="p">;</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">ShowNumberOfCanvasChildren</span> <span class="p">:</span> <span class="n">MonoBehaviour</span>
<span class="p">{</span>
<span class="na"> [SerializeField]</span> <span class="k">private</span> <span class="n">GameObject</span> <span class="n">_canvas</span><span class="p">;</span>
<span class="na"> [SerializeField]</span> <span class="k">private</span> <span class="n">Text</span> <span class="n">_numChildrenText</span><span class="p">;</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">Update</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">_numChildrenText</span><span class="p">.</span><span class="n">text</span> <span class="p">=</span> <span class="s">&quot;Canvas child count: &quot;</span> <span class="p">+</span> <span class="n">_canvas</span><span class="p">.</span><span class="n">transform</span><span class="p">.</span><span class="n">childCount</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>Whichever option we choose, here is how the script will appear when we attach it in the inspector after these changes:</p>
<p><img alt="The inspector shows us our dependencies, and that they have not been connected yet." src="https://silvrback.s3.amazonaws.com/uploads/3fea4696-61a0-4bdf-9af2-61e12953462a/stated_dependencies_unwired_large.JPG" /></p>
<p>Nice, now we see that our script relies on two things: the canvas and some text to display the number of children with. The inspector also tells us that those dependencies have not been hooked up yet. We can do that by dragging and dropping the corresponding objects into these fields.</p>
<p><img alt="We wire the dependencies to our object." src="https://silvrback.s3.amazonaws.com/uploads/0ec81385-a374-4097-add2-cdc670d4a663/wiring_dependencies_large.gif" /></p>
<p>Even better, when we need to change our scene around later, Unity helps make the process as painless as possible, keeping the references hooked up when objects are renamed and moved around.</p>
<p><img alt="Example gif of moving things around preserving references" src="https://silvrback.s3.amazonaws.com/uploads/c2db3469-56af-4fb8-8a15-96c8b333b1f9/changing_scene_keeps_dependencies_wired_large.gif" /></p>
<p>This is awesome! Freed from these string bindings, we can now work on our app with confidence instead of fear. Remember this the next time you see GameObject.Find in your codebase.</p>
<p><a href="https://www.reddit.com/r/gamedev/comments/3t74w4/unity_devs_should_stop_using_gameobjectfind/">Discussion can be found on the r/gamedev subreddit</a>.</p>
Alexander Biggstag:akbiggs.silvrback.com,2005:Article/47542014-06-03T15:13:30+10:002018-08-09T00:25:16+10:00The Wall<p>It happens at every hackathon. Progress slows down, finishing basic functionality takes forever, the list of requirements grows and grows while motivation decreases, and eventually you stop and think:</p>
<blockquote>
<p>That&#39;s it, we&#39;re screwed.</p>
</blockquote>
<p>Resist the temptation to throw in the towel and don&#39;t ditch the event. The most valuable experience to be gained isn&#39;t from the app you make or the technologies you learn, it&#39;s from sticking things through and turning a situation that seems hopeless on its head.</p>
<p>To pick yourself up you need to figure out what&#39;s bringing things down. There are a few common causes:</p>
<ol>
<li><p>The app isn&#39;t functional several hours in. Progress is slow or ideas that seemed simple to implement are blocked by bugs.</p>
<p>Debugging can sap the energy out of any developer. The standard advice applies(use a debugger, reduce the amount of code until you isolate the issue), but sometimes it&#39;s best to work around the problem, either with a hack that hides away the issue or simply fakes the required functionality. This helps to keep your momentum and leaves you with more time to work on the app&#39;s presentation.</p>
<p>Focusing too hard on writing good code is another blocker. Good code is the product of careful thinking and continuous reiteration, both difficult to manage under tight time constraints. Completing tasks quickly without worrying about code quality instead can be refreshing and motivating. Hackathons are perfect for testing a previously written engine&#39;s adaptability but are not well-suited towards writing a new one.</p></li>
<li><p>As you work, the idea behind the app feels less and less interesting until it seems worthless.</p>
<p>When you lose interest in the idea, try to remember what initially excited you: the aspect that grabs you on a personal level. Developing while personally invested keeps your mind engaged and makes your passion come across in the final product.</p></li>
<li><p>The deadline is looming and your hack isn&#39;t impressive enough to win. It feels like showing the app to other hackers would just be embarrassing.</p>
<p>Don&#39;t worry about it. Anyone experienced with hackathons has their fair share of incomplete and unfulfilled hacks under their belt, each of which helped them to grow and become a better, more focused developer. They&#39;ve also struggled with the same problems you&#39;re going through and empathize with your situation. Just enjoy the thrill of last-minute hacking and remember that the kind of inspiration that makes a mediocre app into a fantastic one can strike at any moment.</p></li>
</ol>
<p>As a last piece of general advice for staying motivated, go to sleep when your focus runs out and you feel exhausted. The mentality that hackathons require all-nighters is poisonous and hurts the quality of your hack. Take on ideas that are small enough in scope to afford rest and use the extra energy to finish the job. Your teammates and your body will thank you.</p>
<p>Completing a hackathon brings an unmatched sense of accomplishment to cherish and remember. Push through your demotivation and earn it.</p>
Alexander Biggstag:akbiggs.silvrback.com,2005:Article/43702014-05-27T15:38:46+10:002018-04-25T09:12:24+10:00Obsession<p>I originally posted this rant <a href="http://pastebin.com/3RSUzfDk">on Pastebin</a> and <a href="https://news.ycombinator.com/item?id=5616786">submitted it to Hacker News</a> at the end of my third year of university, after which I went on a year-long internship. I am no longer ashamed to admit that I wrote this, even if it is a bit melodramatic, so I&#39;m reposting it here.</p>
<hr>
<p>I have driven myself mad over my marks.</p>
<p>When I was in high school, I deluded myself into believing that although I was doing poorly in most subjects, I was among the better students in my class. I believed that my low marks could be explained away by my lack of interest in my studies, and that I could reach the top at any moment just by beginning to exert the smallest amount of effort. The rest of the students in the class were easy enough to group into try-hards who cared too much and losers who cared too little.</p>
<p>This worked well enough for me back then, and although I did not get into the university that I had always dreamed of, I was accepted into one that was good enough for my standards at the time. I heard time and time again that the school was a competitive one, but strongly believed due to my self-confidence that I could keep up my same work ethic and still succeed, as I had before.</p>
<p>I did not. I failed an enriched theory of computation course despite mighty boasts to the teacher about how interested in and motivated I was about the subject material.</p>
<p>After this experience, more reserved about my own abilities, I began to put more effort into my classes. And almost the same, I came close to failing a few classes and did mediocre on the rest. Meanwhile, my friends&#39; marks soared higher than ever, competing and collaborating with each other for the top grades in the class.</p>
<p>Seeing this, I became frustrated, and decided to throw all of myself into my classes. I deleted all the video games off my computer and blocked the social networking and news sites I had been browsing, eliminating what I perceived as the obstacles in my path towards success. Surely now that I was fully engaged, I would crush them, and show them once and for all that I was of the same blood, a top student excelling at every subject I touched.</p>
<p>I am not the same as them.</p>
<p>The students who obtain top grades in classes have an ability to focus like no other. Although they take breaks to enjoy the day and socialize, they do not confuse these activities with performing good work. When they sit down at the computer, they don&#39;t interrupt themselves with chats or social networks, but only with matters that are relevant to what they&#39;re studying, such as helping out other students or asking questions to their peers.</p>
<p>Under pressure, they excel where I break. They handle stress by pushing forward and filling in the gaps that remain in their knowledge through whatever means possible, while I spend the day bedridden and panic-stricken by my own insecurities.</p>
<p>Regardless of whether or not they like or dislike the material, they break the challenge of studying for a test or completing an assignment into small problems, working away until they know, not think, but absolutely know that they are ready. In contrast, I trick myself into believing that I am prepared where I lack practice, and I lose marks where it matters the most.</p>
<p>It was an insult for me to think that I was ever anything like them. In my drive to show them up, I have broken myself with grief and anxiety comparing my marks to theirs, and I have alienated them through irrational, envious hate. With my final two exams of university next week, I understand now that I was a fool for having confidence in myself and my abilities without reason. I should have put the effort in first and should have only allowed myself to gain confidence through the results that followed.</p>
<p>I only hope that those who read this might catch themselves in time to avoid making the same mistake.</p>
<hr>
<p>It&#39;s worth noting that my view on myself changed dramatically after this time. The company I proceeded to work at helped boost my self-esteem and taught me that while having high standards is a good thing, I shouldn&#39;t be so harsh on myself even when I struggle to achieve them. I no longer see myself as a failure when the outcome of a class or project is disappointing; instead, I take it as a sign that there are aspects of my personality I still need to work on to achieve my goals.</p>
Alexander Biggs