{"id":3263,"date":"2014-05-24T21:08:00","date_gmt":"2014-05-24T20:08:00","guid":{"rendered":"http:\/\/t-machine.org\/?p=3263"},"modified":"2014-05-24T21:10:19","modified_gmt":"2014-05-24T20:10:19","slug":"how-to-tidy-your-unity-code-by-putting-it-in-a-dll","status":"publish","type":"post","link":"http:\/\/new.t-machine.org\/index.php\/2014\/05\/24\/how-to-tidy-your-unity-code-by-putting-it-in-a-dll\/","title":{"rendered":"How to tidy your Unity code by putting it in a DLL"},"content":{"rendered":"<h2>The importance of Re-use<\/h2>\n<p>Here&#8217;s a story that may sound familiar:<\/p>\n<blockquote><p>\nYou downloaded Unity, watched some tutorials on YouTube, and had a physics &#8220;game&#8221; running the same day. Excited, you started writing the game you&#8217;ve always wanted to make. Possibly &#8211; bitten before when trying this with GameMaker etc &#8211; you thought to organize your source code: folders, subfolders, logically-named scripts, etc.<\/p>\n<p>Fast-forward a few months, and you have 50 scripts in 40 sub-folders, some of it re-usable, some of it hardcoded for your game. Hoooo-Kayyyy&#8230; Well, it&#8217;s not too bad. And then a new opportunity comes along &#8211; a paid contract, a game-jam, a collaboration with a friend &#8211; and you want to re-use some code from your main project. You look at the folder structure, you look at how intertwined it&#8217;s all become &#8230; and you weep.<\/p>\n<p>Without re-use, what seemed like an &#8220;easy&#8221; project becomes just a little too much work, and you never finish it. Back to square one :(.\n<\/p><\/blockquote>\n<h2>Code re-use in Unity<\/h2>\n<p>There are five major aspects to code re-use when making Unity apps. Most of these are shared with general programming, but these are the ones I&#8217;ve found *especially* important when doing Unity development.<\/p>\n<h3>Good names<\/h3>\n<p>The best way to get good at naming things in a program is to focus on &#8220;what makes a bad name&#8221;, and &#8220;Don&#8217;t do that&#8221;. e.g.<\/p>\n<ul>\n<li>If you have to open a Script to remember what it does &#8230; it has the wrong name.\n<li>If you keep typo&#8217;ing the script when referencing it in other scripts &#8230; it&#8217;s the wrong name\n<li>If your script is more than a thousand lines long &#8230; it&#8217;s the wrong name AND you&#8217;ve put too much junk in there; split it!\n<li>If you can&#8217;t find a script, because you can&#8217;t remember which folder it&#8217;s in &#8230; the folder name is wrong, AND the script name is wrong (should have been a name that forced you to put it in the right place first time!)\n<li>&#8230;etc\n<\/ul>\n<p>Renaming scripts in Unity is a minor pain: you rename it, then you have to close the file in MonoDevelop, re-open it, and (assuming it was a C# class) rename the class in source-code too. (I keep hoping latest Unity will do this automatically, but I&#8217;m a version behind at the moment).<\/p>\n<h3>We need Sub-folders. Lots of Sub-Folders<\/h3>\n<p><iframe loading=\"lazy\" width=\"640\" height=\"390\" src=\"\/\/www.youtube.com\/embed\/Y70vcs3oV14\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n<p>&#8230; you can never have too many. Give them good names, though!<\/p>\n<h3>De-couple your code<\/h3>\n<p>Ah, now it gets tricky. The art of decoupling takes much practice to master.<\/p>\n<p>Decoupling is why C# (and Java) has the &#8220;interface&#8221; keyword. The concept is much easier to understand after you cocked it up, written code you can&#8217;t re-use, because everything&#8217;s too inter-dependent.<\/p>\n<blockquote><p>\n&#8220;I can&#8217;t just copy\/paste that script to my new project, because it references 3 other scripts. Each of which &#8230; references another 12. ARGH!&#8221;\n<\/p><\/blockquote>\n<p>Unity itself doesn&#8217;t use Interfaces (though it really ought to!) &#8211; and you have to use a little ingenuity to use them yourself (Google it, it&#8217;s only a few small caveats). But C#-interfaces simply give you a compiler-compatible way of decoupling: you have to design your classes as decoupled to start with. Again, google this and ask around &#8211; it&#8217;s too big a topic for me to do justice to here!<\/p>\n<h3>Package your code, so you can re-use it<\/h3>\n<p>Libraries. This is why The God Of Programming invented Libraries. So, how do you do a Library in Unity?<\/p>\n<h2>Libraries in Unity: the easy DLL<\/h2>\n<p>There are two kinds of DLL&#8217;s:<\/p>\n<ol>\n<li>Real DLL&#8217;s, as used by Real Men, who write all their code in C++\n<li>Fake DLL&#8217;s, as used by the rest of us, who just want an easy life so we can focus on <strong>making our game<\/strong>\n<\/ol>\n<p>A DLL is a great way of packaging code &#8211; it&#8217;s a very widely-used standard. So, Unity uses DLL&#8217;s for this (good move) &#8211; but if you google &#8220;Unity make DLL&#8221; you&#8217;ll get distracted by the huge complexity and depth of C++\/Unity integration, and you don&#8217;t need any of it. Instead, you&#8217;ll be doing &#8220;DLL light&#8221;, which is easy.<\/p>\n<p>But, as with most Unity features, it&#8217;s almost entirely undocumented. And, out of the box, it will fail. For bonus points, Unity will give you completely the wrong error message when it goes wrong. Yay!<\/p>\n<h3>Step 1: write a Unity script in Unity<\/h3>\n<p>Do something simple. I wrote a class that makes random numbers, following XKCD&#8217;s advice:<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/imgs.xkcd.com\/comics\/random_number.png\"\/><\/p>\n<p>[csharp]<br \/>\nusing UnityEngine;<\/p>\n<p>\/** In Unity 3, you cannot have namespaces. So comment out this next line. Unity 4 is fine *\/<br \/>\nnamespace MyTestDLL<br \/>\n{<br \/>\n\tpublic class DLLClass<br \/>\n\t{<br \/>\n\t\tpublic static int GetRandom()<br \/>\n\t\t{<br \/>\n\t\t\treturn 4;<br \/>\n\t\t}<br \/>\n\t}<br \/>\n\/** In Unity 3, you cannot have namespaces. So comment out this next line. Unity 4 is fine *\/<br \/>\n}<br \/>\n[\/csharp]<\/p>\n<p>Make a second script that uses that first one, e.g.<br \/>\n[csharp]<br \/>\nusing UnityEngine;<\/p>\n<p>public class TestScript : MonoBehaviour<br \/>\n{<br \/>\n\tvoid Start()<br \/>\n\t{<br \/>\n\t\tprint( DLLClass.GetRandom() );<br \/>\n\t}<br \/>\n}<br \/>\n[\/csharp]<\/p>\n<p>&#8230;attach it to a GameObject, check it works.<\/p>\n<h3>Step 2: follow Unity&#8217;s docs on creating and using a DLL<\/h3>\n<p>You&#8217;d think this would be enough, but it isn&#8217;t. However, the docs are simple, direct, and I found them easy to follow.<\/p>\n<p>So <a href=\"http:\/\/docs.unity3d.com\/Documentation\/Manual\/UsingDLL.html\">http:\/\/docs.unity3d.com\/Documentation\/Manual\/UsingDLL.html = read this and do what it says<\/a><\/p>\n<p>NB: they write a slightly more complex script to use than mine, with but whatever. The idea is the same.<\/p>\n<h3>Step 3: Use the namespace, Luke. And Interfaces. And &#8230; <\/h3>\n<p>Now that your DLL is compiling\/building in MonoDevelop &#8230; you are no longer stuck with Unity&#8217;s arbitrary rules and restrictions! The world is yours!<\/p>\n<p>(so, even in Unity 3, you can now use the namespace. Which makes it MUCH easier to keep your code well-organized ;))<\/p>\n<h3>Step 4: What about the [square brackets]?<\/h3>\n<p>These Just Work &#8482; exactly as they did in Unity scripts. e.g.<\/p>\n<p>[csharp]<br \/>\nusing UnityEngine;<\/p>\n<p>namespace MyTestDLL<br \/>\n{<\/p>\n<p>\/** Hey! Look! Unity editor-features &#8230; coded outside of Unity *\/<br \/>\n[ExecuteInEditMode]<br \/>\n[System.Serializable]<br \/>\n\tpublic class DLLClass<br \/>\n\t{<br \/>\n&#8230;<br \/>\n[\/csharp]<\/p>\n<h3>Step 5: Editor extensions, editor scripts, editor GUIs, etc<\/h3>\n<p>This is where it breaks. If you had any Editor scripts (which, in Unity, <strong><em>MUST<\/em><\/strong> be stored in the &#8220;Editor&#8221; root folder, or one of its subfolders), you can include them in your DLL &#8211; but they won&#8217;t work.<\/p>\n<p>Worse, when you trigger them (e.g. by selecting a GameObject that did custom editor rendering), you&#8217;ll get:<\/p>\n<blockquote><p>\nError: multi-object editing not supported !\n<\/p><\/blockquote>\n<p>&#8230;at least, you do in Unity 3.x. Fixed in 4.x, I suspect? But I haven&#8217;t gone back to try it since I fixed the bug :).<\/p>\n<p>There is some mumbo-jumbo on the internet (and Unity forums) about complicated workarounds, notably courtesy of AngryAnt (with a <a href=\"http:\/\/angryant.com\/2014\/01\/03\/Unity-and-net-assemblies\/\">Jan 2014 post here, with some extra info worth reading<\/a> but NOT required!). But these are long-since outdated and unnecessary. The fix is very simple: we must create TWO DLL&#8217;s!<\/p>\n<ol>\n<li>DLL #1: the one we already had\n<li>DLL #2: will contain ONLY the editor-scripts, and we&#8217;ll drag\/drop it into Unity&#8217;s &#8220;Editor&#8221; folder.\n<\/ol>\n<p>This is extremely logical, simple, and easy to remember. And it works beautifully! But .. how?<\/p>\n<h4>Step 5a: Upgrade MonoDevelop project to output not one, but two, DLL&#8217;s<\/h4>\n<p>First, right-click on the top-most item in MonoDevelop&#8217;s &#8220;Solution&#8221; panel, and select &#8220;Add New Project&#8230;&#8221;:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/t-machine.org\/wp-content\/uploads\/Screen-Shot-2014-05-24-at-20.54.53.png\" alt=\"Screen Shot 2014-05-24 at 20.54.53\" width=\"533\" height=\"420\" class=\"aligncenter size-full wp-image-3264\" srcset=\"https:\/\/t-machine.org\/wp-content\/uploads\/Screen-Shot-2014-05-24-at-20.54.53.png 533w, https:\/\/t-machine.org\/wp-content\/uploads\/Screen-Shot-2014-05-24-at-20.54.53-150x118.png 150w, https:\/\/t-machine.org\/wp-content\/uploads\/Screen-Shot-2014-05-24-at-20.54.53-300x236.png 300w\" sizes=\"(max-width: 533px) 100vw, 533px\" \/><\/p>\n<p>As you did earlier, choose &#8220;Library (C#)&#8221;. I recommend naming this &#8220;SomethingSomethingEditorScripts&#8221; (where &#8220;SomethingSomething&#8221; is your library name, which you used for the first DLL).<\/p>\n<p>Second, you need to edit the References (as you did with first DLL), and this time repeat the steps and add ALL of:<\/p>\n<ul>\n<li>UnityEngine.dll\n<li>UnityEditor.dll\n<li>&#8230;\n<li>AND: instead of the &#8220;.Net Assembly&#8221; tab, use the &#8220;Projects&#8221; tab and select your main DLL\/library. It should be the only option\n<\/ul>\n<p>That gives you something like this:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/t-machine.org\/wp-content\/uploads\/Screen-Shot-2014-05-24-at-20.58.22.png\" alt=\"Screen Shot 2014-05-24 at 20.58.22\" width=\"261\" height=\"390\" class=\"aligncenter size-full wp-image-3265\" srcset=\"https:\/\/t-machine.org\/wp-content\/uploads\/Screen-Shot-2014-05-24-at-20.58.22.png 261w, https:\/\/t-machine.org\/wp-content\/uploads\/Screen-Shot-2014-05-24-at-20.58.22-100x150.png 100w, https:\/\/t-machine.org\/wp-content\/uploads\/Screen-Shot-2014-05-24-at-20.58.22-200x300.png 200w\" sizes=\"(max-width: 261px) 100vw, 261px\" \/><\/p>\n<p>&#8230;see how I have two &#8220;projects&#8221; in MonoDevelop, one which just uses normal Unity stuff, the other which additionally uses Unity Editor stuff? And the second one &#8220;references&#8221; the first, so it can see\/use\/create the classes and methods from the first one.<\/p>\n<h4>Step 5b: Put the DLL&#8217;s in different places<\/h4>\n<p>Build, and find the output files. The first project\/DLL will still only be making one DLL, but the folder for the SECOND project\/DLL will conveniently build BOTH projects and contain BOTH DLL&#8217;s.<\/p>\n<p>Make sure you put one DLL &#8220;anywhere except Editor&#8221; and the other one &#8220;in Editor, or a subfolder of Editor&#8221;.<\/p>\n<p>Finally, create some GameObject&#8217;s, open up the DLL&#8217;s in Unity&#8217;s Project view (expand the triangle) and drag\/drop the Scripts onto your objects as desired. Click on them in the Scene view, and all your OnGUI, OnGizmos etc methods should run exactly as normal.<\/p>\n<h3>Step 6: Rejoice!<\/h3>\n<p>Now you can share your code with other Unity projects simply by drag\/dropping the 2 x DLL&#8217;s into a new Unity project. BOOM!<\/p>\n<p>Beautiful! Easy, simple, impossible-to-screw-up ;). That&#8217;s how I like my code re-use&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The importance of Re-use Here&#8217;s a story that may sound familiar: You downloaded Unity, watched some tutorials on YouTube, and had a physics &#8220;game&#8221; running the same day. Excited, you started writing the game you&#8217;ve always wanted to make. Possibly &#8211; bitten before when trying this with GameMaker etc &#8211; you thought to organize your [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20,67,69],"tags":[],"_links":{"self":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/3263"}],"collection":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/comments?post=3263"}],"version-history":[{"count":3,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/3263\/revisions"}],"predecessor-version":[{"id":3268,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/3263\/revisions\/3268"}],"wp:attachment":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/media?parent=3263"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/categories?post=3263"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/tags?post=3263"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}