{"id":2143,"date":"2018-01-02T20:42:57","date_gmt":"2018-01-02T11:42:57","guid":{"rendered":"https:\/\/www.codedojo.com\/?p=2143"},"modified":"2018-02-19T21:38:19","modified_gmt":"2018-02-19T12:38:19","slug":"how-to-do-your-unity-builds-in-the-background","status":"publish","type":"post","link":"https:\/\/www.codedojo.com\/?p=2143","title":{"rendered":"How to do your Unity builds in the background"},"content":{"rendered":"<p>If you&#8217;ve looked at my <a href=\"https:\/\/www.codedojo.com\/?p=2091\">recent Unity-related posts<\/a> and downloaded the projects, you might have noticed I have .bat files like CreateAndUploadWebGLBuild.bat in there to cleanly create final versions easily.<\/p>\n<p>Great.\u00a0 But if you run this .bat file while you are working on the game with the Unity editor, you&#8217;ll get this error:<\/p>\n<pre>Aborting batchmode due to failure:\r\nFatal Error! It looks like another Unity instance is running with this project open.\r\n\r\nMultiple Unity instances cannot open the same project.<\/pre>\n<p>Ugh.\u00a0 WebGL builds are especially are incredible slow, so this is a big productivity waster if you&#8217;re doing a lot of WebGL testing.\u00a0 (If you work at a big company and waiting for builds is your favorite time to make coffee and catch up on reddit, well, close this page right now and hope your boss never reads this!)<\/p>\n<h1>Cloud Build?<\/h1>\n<p>Maybe you could use Unity&#8217;s Cloud Build but there are some down sides:<\/p>\n<ul>\n<li>Cost $9 a month?<\/li>\n<li>Requires that you commit each change to a cvs such as svn, perforce, or git<\/li>\n<li>I doubt it can do custom post build commands such as code signing, building a final installer, or rscying files to a linux server and restarting the process.\u00a0 I guess you could do those things yourself when the build is done, but heck, why not just handle the build yourself from the start.<\/li>\n<li>Requires that all your assets are also on cvs (?)<\/li>\n<\/ul>\n<h1>The DIY way<\/h1>\n<p>So let&#8217;s do it old school with &#8230; yep, you guessed it&#8230; even more .bat files!\u00a0 The secret is very simple, Unity will allow you to build in the background if the project directory is different.<\/p>\n<p>You just need to copy your entire project to a temporary folder, then run Unity.exe with parms to do a headless build like normal.<\/p>\n<p>So when you are in a good place with your project and would like to start a background build, hit Ctrl-S to save, then run your &#8220;<strong>CopyToTempDirAndBuild.bat<\/strong>&#8221; file.<\/p>\n<p>After a couple seconds the initial copy is done and it&#8217;s safe to continue working while the build is happening in the temp directory &#8211; any changes will not be in the temp directory, so your build in progress won&#8217;t be affected.\u00a0 So you can keep working away, without ever closing your main unity editor window.<\/p>\n<p>It&#8217;s not especially tricky to do, but here are some .bat files to look at as an example that could be tweaked.<\/p>\n<p>To copy a directory tree to a temp dir: (it assumes the .bat is run from the directory that&#8217;s going to be copied)<\/p>\n<p><strong>CloneToTempDir.bat<\/strong><\/p>\n<pre>:this sets some info about the project, for example, it causes %APP_NAME% to hold our main directory name\r\ncall app_info_setup.bat\r\n\r\nrmdir ..\\%APP_NAME%Temp%1 \/S \/Q\r\necho Cloning %APP_NAME% to temp dir %APP_NAME%Temp%1...\r\nmkdir ..\\%APP_NAME%Temp%1\r\nxcopy . ..\\%APP_NAME%Temp%1\\ \/E \/F \/Y \/EXCLUDE:%cd%\\CloneExclusionList.txt<\/pre>\n<p>Note:\u00a0 You may wonder why I&#8217;m being repetitive and using &#8220;Temp&#8221; everywhere instead of including it in a variable.\u00a0 It&#8217;s because you NEVER, NEVER use things like rmdir with only a variable if you can help it, because at some point, that variable is going to be set incorrectly.\u00a0 It might be\u00a0 .. or \/ or something and you&#8217;ll delete your whole hard drive.\u00a0 Safety first.<\/p>\n<p>Another note: <strong>%cd%<\/strong> is a DOS trick to get the current full directory<\/p>\n<p><strong>CloneExclusionList.txt<\/strong> contains dirs we don&#8217;t want to waste time copying:<\/p>\n<pre>Temp\\\r\nLibrary\\\r\nbuild\\win\r\nbuild\\linux\r\nbuild\\web\\Build<\/pre>\n<p><strong>BuildAndUploadWebGLInClonedDir.bat<\/strong><\/p>\n<pre>:this sets some info about the project, for example, it causes %APP_NAME% to hold our main directory name\r\ncall app_info_setup.bat\r\n:Setting no pause causes our .bat files to not do pause commands when they are done\r\nset NO_PAUSE=1\r\n:First, let's customize the directory name we're going to close to, by adding a postfix to make it unique\r\nSET CLONE_DIR_POSTFIX=WebGL\r\n:Now let's actually make it, we'll pass in the postfix as a parm\r\ncall CloneToTempDir.bat %CLONE_DIR_POSTFIX%\r\n\r\n:Move to build dir\r\ncd ..\/%APP_NAME%Temp%CLONE_DIR_POSTFIX%\r\n:Do the actual build\r\ncall BuildWebGL.bat\r\ncall UploadWebGLRsync.bat\r\n:Move back out of it\r\ncd ..\r\n:Delete the temp dir we were just using\r\nrmdir %APP_NAME%Temp%CLONE_DIR_POSTFIX% \/S \/Q\r\npause<\/pre>\n<p>This calls <strong>CloneToTempDir.bat<\/strong> with the parm &#8220;WebGL&#8221; which gets appended to the &lt;AppName&gt;Temp dir.<\/p>\n<p>It then &#8220;calls&#8221; (this means run another .bat, and come back when it&#8217;s done) .bats to create the webgl build and also upload it to the website.<\/p>\n<p>It then destroys the temp directory completely, a good idea because Unity will mark it as the last project and you don&#8217;t want to accidently work on that directory later.<\/p>\n<h1>Parallel Builds<\/h1>\n<p>If you&#8217;ve got 16 threads sitting around like I do, it might make sense to build MORE THAN ONE version at a time. (now you see why I use a custom temp dir name for each build)<\/p>\n<p>Apparently, Unity doesn&#8217;t care how many simultaneous builds you&#8217;re doing on a single computer, as long as its license is valid. (I&#8217;m using a pro license)<\/p>\n<p>The key to running parallel builds is to use the &#8220;start&#8221; command instead of &#8220;call&#8221;. This means &#8220;run this, but instead of waiting, just continue running the rest of this .bat file&#8221;.<\/p>\n<p><strong>MakeEverythingInCloneDirs.bat<\/strong><\/p>\n<pre>start BuildAndUploadWebGLInClonedDir.bat\r\nstart BuildAndUploadLinux64InClonedDir.bat<\/pre>\n<p>So, including the Unity editor you have open, when this is run you&#8217;ll have THREE instances of Unity running on the same computer at once.\u00a0 It all works fine!<\/p>\n<h1>Continuous integration as a background operation on the same computer you develop on<\/h1>\n<p>If you add a &#8220;goto :start&#8221; at the bottom of your .bat and a &#8220;:start&#8221; label at the top, you can &#8220;clone and build&#8221; non-stop all day.\u00a0 I don&#8217;t see this as very useful as it&#8217;s going to break all the time as we&#8217;re not doing controlled commits with a cvs but I thought I&#8217;d throw that there.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you&#8217;ve looked at my recent Unity-related posts and downloaded the projects, you might have noticed I have .bat files like CreateAndUploadWebGLBuild.bat in there to cleanly create final versions easily. Great.\u00a0 But if you run this .bat file while you are working on the game with the Unity editor, you&#8217;ll get this error: Aborting batchmode [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,21],"tags":[],"class_list":["post-2143","post","type-post","status-publish","format-standard","hentry","category-tech-tips","category-unity"],"_links":{"self":[{"href":"https:\/\/www.codedojo.com\/index.php?rest_route=\/wp\/v2\/posts\/2143","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.codedojo.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.codedojo.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.codedojo.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.codedojo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2143"}],"version-history":[{"count":2,"href":"https:\/\/www.codedojo.com\/index.php?rest_route=\/wp\/v2\/posts\/2143\/revisions"}],"predecessor-version":[{"id":2183,"href":"https:\/\/www.codedojo.com\/index.php?rest_route=\/wp\/v2\/posts\/2143\/revisions\/2183"}],"wp:attachment":[{"href":"https:\/\/www.codedojo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2143"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.codedojo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2143"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.codedojo.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2143"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}