{"id":39,"date":"2016-01-28T11:48:37","date_gmt":"2016-01-28T11:48:37","guid":{"rendered":"http:\/\/matthew.somewhatunlikely.com\/?p=39"},"modified":"2016-01-28T11:48:37","modified_gmt":"2016-01-28T11:48:37","slug":"unity-troubleshooting-ii","status":"publish","type":"post","link":"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/","title":{"rendered":"Unity Troubleshooting II"},"content":{"rendered":"\n<p>Some more Unity 3D tips that I need to write down while I remember them. (You might be interested in the <a href=\"\/unity-troubleshooting\/\">previous ones<\/a>.)<\/p>\n\n\n\n<p>TL;DR: Don&#8217;t forget to use Time.deltaTime for per-second change. Content Size Fitters update late, so read their properties at end of frame.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h3 class=\"wp-block-heading\">It Changes Too Quickly<\/h3>\n\n\n\n<p>When you&#8217;re pondering the deepest mysteries of your game, it&#8217;s easy to make the most obvious mistakes. Right? (Or is that just me?)<\/p>\n\n\n\n<p>Suppose you want to change a quantity at a particular rate, in units per second. (Many of you are ahead of me now that I&#8217;ve been explicit about the units. Just make sure you&#8217;re thinking that way when you implement your rates.)<br>Your code might look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void Update() {\n    quantity += rate;\n}<\/code><\/pre>\n\n\n\n<p>You should probably clamp quantity, and maybe wrap it in a condition (e.g. I suspect, but don&#8217;t know, that it&#8217;s faster to check whether quantity &lt; cap, rather than going ahead and increasing against the clamp). But the general principle is there.<\/p>\n\n\n\n<p>Then you find that quantity changes much\u00a0faster than you intended. That&#8217;s because you intended this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void Update() {\n    quantity += rate * Time.deltaTime;\n}<\/code><\/pre>\n\n\n\n<p>Time.deltaTime is the number of seconds since the last frame. You may find it counter-intuitive to <em>multiply<\/em> something that is too large, but unless you have serious performance issues, Time.deltaTime will be small (in the region of 0.02, perhaps).<\/p>\n\n\n\n<p>With this change you&#8217;ve gone from increasing quantity at rate-per-frame to increasing it at rate-per-second, not only making it a more manageable quantity, but also making it consistent (since frames aren&#8217;t of constant duration).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Content Size Fitter vs. Reading RectTransforms<\/h3>\n\n\n\n<p>I steered clear of the 4.6 Unity UI for some time, haunted by my experiences in different versions. I even chose HTML5 for one prototype, because I assumed that outputting HTML would be a nice short-cut for testing a UI-heavy concept.<br>Never again.<\/p>\n\n\n\n<p>The layout support, including layout groups and content size fitters, does neat things, and generally the fact that it doesn&#8217;t show you how isn&#8217;t a problem. But one day I wanted to position tooltips properly; making sure they were entirely within the screen, that sort of frivolity.<\/p>\n\n\n\n<p>I started out like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>T InitTooltip&lt;T&gt;(T prefab) where T : MonoBehaviour {\n    T tt = Instantiate(prefab);\n    tt.transform.position = initialPosition;\n    \/\/ ... Check bounds and reposition if necessary ...\n    return tt;\n}\nvoid Show(<em>signature specifies tooltip type<\/em>) {\n    SpecificTooltip stt = InitTooltip(specificPrefab);\n    stt.Init(stuff); \/\/ Populate\n    canvasGroup.alpha = 1;\n}<\/code><\/pre>\n\n\n\n<p>Aside 1: It feels as though there should be better way of showing\/hiding UI than canvasGroup.alpha, but until you can disable CanvasRenderer I don&#8217;t know what it is. You can set the GameObject inactive, but make sure you store a reference to it first, because finding inactive objects can be a pain.<\/p>\n\n\n\n<p>Asside 2: You might guess at this stage that I like generics. You&#8217;ve be so very right.<br>It doesn&#8217;t work. I logged several properties of the RectTransform and generally found them to be empty, as though the rect was of zero size. And of course, it was, because the prefab tooltip is empty (with zero size) and specificTooltip.Init(stuff) is what gives it its content.<\/p>\n\n\n\n<p>So I moved the repositioning into a new method, to be called after the tooltip content has been initialised. This was a pain, because I&#8217;d hoped for the individual Show methods (of which I have several) to minimise both code reuse and knowledge of the process of building tooltips. In order to get it to happen after Init(), each Show() had to include and explicit call to Reposition().<\/p>\n\n\n\n<p>But even that didn&#8217;t work. I got annoyed, sighed a lot and probably annoyed my girlfriend (since by this stage I&#8217;ve worked well into the evening). This morning I had a brainwave: what if content size fitter needed\u00a0longer, and still wasn&#8217;t ready yet?<\/p>\n\n\n\n<p>So I put the reposition in a coroutine, and now the solution looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>T InitTooltip&lt;T&gt;(T prefab) {\n    T tt = Instantiate(prefab);\n    tt.transform.position = initialPosition;\n    StartCoroutine(FinalisePosition());\n    return tt;\n}\nIEnumerator FinalisePosition() {\n    yield return new WaitForEndOfFrame();\n    \/\/ ... Test bounds and reposition ...\n    canvasGroup.alpha = 1;\n}\nvoid Show(<em>signature specifies tooltip type<\/em>) {\n    SpecificTooltip stt = InitTooltip(specificPrefab);\n    stt.Init(stuff); \/\/ Populate\n}<\/code><\/pre>\n\n\n\n<p>If you haven&#8217;t met <a rel=\"noopener\" href=\"http:\/\/docs.unity3d.com\/Manual\/Coroutines.html\" target=\"_blank\">Coroutines<\/a> before, read the manual page; they&#8217;re pretty handy. This one stops immediately, to be resumed at the end of the frame, which it turns out is long enough for the content size fitter to have decided how big it is (which I guess is done in LateUpdate(), or a dedicated GUI loop).<\/p>\n\n\n\n<p>There&#8217;s a gotcha here, in that the tooltip now has time to appear in the wrong position before the deferred positioning happens. You&#8217;ll notice that I&#8217;ve left setting the canvasGroup.alpha until after the reposition, so nobody sees it in the old position.<\/p>\n\n\n\n<p>It&#8217;s also tidied up my code, since InitTooltip() can invoke the coroutine, to happen after the specific Init(), without the Show() methods knowing anything about it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Epilogue<\/h3>\n\n\n\n<p>I daresay I&#8217;ll make more Unity mistakes for you to avoid, soon. Perhaps I&#8217;ll have put in a proper code format plugin by then.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Some more Unity 3D tips that I need to write down while I remember them. (You might be interested in the previous ones.) TL;DR: Don&#8217;t forget to use Time.deltaTime for per-second change. Content Size Fitters update late, so read their properties at end of frame.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-39","post","type-post","status-publish","format-standard","hentry","category-game-coding"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.2 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Unity Troubleshooting II - Somewhat Unlikely<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Unity Troubleshooting II - Somewhat Unlikely\" \/>\n<meta property=\"og:description\" content=\"Some more Unity 3D tips that I need to write down while I remember them. (You might be interested in the previous ones.) TL;DR: Don&#8217;t forget to use Time.deltaTime for per-second change. Content Size Fitters update late, so read their properties at end of frame.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/\" \/>\n<meta property=\"og:site_name\" content=\"Somewhat Unlikely\" \/>\n<meta property=\"article:published_time\" content=\"2016-01-28T11:48:37+00:00\" \/>\n<meta name=\"author\" content=\"Matthew\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Matthew\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/\"},\"author\":{\"name\":\"Matthew\",\"@id\":\"https:\/\/somewhatunlikely.com\/#\/schema\/person\/d529b804e1b6ef169c7a8928c3984bab\"},\"headline\":\"Unity Troubleshooting II\",\"datePublished\":\"2016-01-28T11:48:37+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/\"},\"wordCount\":781,\"articleSection\":[\"Game Coding\"],\"inLanguage\":\"en-GB\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/\",\"url\":\"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/\",\"name\":\"Unity Troubleshooting II - Somewhat Unlikely\",\"isPartOf\":{\"@id\":\"https:\/\/somewhatunlikely.com\/#website\"},\"datePublished\":\"2016-01-28T11:48:37+00:00\",\"author\":{\"@id\":\"https:\/\/somewhatunlikely.com\/#\/schema\/person\/d529b804e1b6ef169c7a8928c3984bab\"},\"breadcrumb\":{\"@id\":\"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/somewhatunlikely.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Unity Troubleshooting II\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/somewhatunlikely.com\/#website\",\"url\":\"https:\/\/somewhatunlikely.com\/\",\"name\":\"Somewhat Unlikely\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/somewhatunlikely.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/somewhatunlikely.com\/#\/schema\/person\/d529b804e1b6ef169c7a8928c3984bab\",\"name\":\"Matthew\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/2c7353448acc49602ade2930a18c0900956671c700cfb333234f0188b99108d6?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/2c7353448acc49602ade2930a18c0900956671c700cfb333234f0188b99108d6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/2c7353448acc49602ade2930a18c0900956671c700cfb333234f0188b99108d6?s=96&d=mm&r=g\",\"caption\":\"Matthew\"},\"url\":\"https:\/\/somewhatunlikely.com\/index.php\/author\/matthew\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Unity Troubleshooting II - Somewhat Unlikely","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/","og_locale":"en_GB","og_type":"article","og_title":"Unity Troubleshooting II - Somewhat Unlikely","og_description":"Some more Unity 3D tips that I need to write down while I remember them. (You might be interested in the previous ones.) TL;DR: Don&#8217;t forget to use Time.deltaTime for per-second change. Content Size Fitters update late, so read their properties at end of frame.","og_url":"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/","og_site_name":"Somewhat Unlikely","article_published_time":"2016-01-28T11:48:37+00:00","author":"Matthew","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Matthew","Estimated reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/#article","isPartOf":{"@id":"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/"},"author":{"name":"Matthew","@id":"https:\/\/somewhatunlikely.com\/#\/schema\/person\/d529b804e1b6ef169c7a8928c3984bab"},"headline":"Unity Troubleshooting II","datePublished":"2016-01-28T11:48:37+00:00","mainEntityOfPage":{"@id":"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/"},"wordCount":781,"articleSection":["Game Coding"],"inLanguage":"en-GB"},{"@type":"WebPage","@id":"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/","url":"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/","name":"Unity Troubleshooting II - Somewhat Unlikely","isPartOf":{"@id":"https:\/\/somewhatunlikely.com\/#website"},"datePublished":"2016-01-28T11:48:37+00:00","author":{"@id":"https:\/\/somewhatunlikely.com\/#\/schema\/person\/d529b804e1b6ef169c7a8928c3984bab"},"breadcrumb":{"@id":"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/somewhatunlikely.com\/index.php\/2016\/01\/28\/unity-troubleshooting-ii\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/somewhatunlikely.com\/"},{"@type":"ListItem","position":2,"name":"Unity Troubleshooting II"}]},{"@type":"WebSite","@id":"https:\/\/somewhatunlikely.com\/#website","url":"https:\/\/somewhatunlikely.com\/","name":"Somewhat Unlikely","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/somewhatunlikely.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Person","@id":"https:\/\/somewhatunlikely.com\/#\/schema\/person\/d529b804e1b6ef169c7a8928c3984bab","name":"Matthew","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/secure.gravatar.com\/avatar\/2c7353448acc49602ade2930a18c0900956671c700cfb333234f0188b99108d6?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/2c7353448acc49602ade2930a18c0900956671c700cfb333234f0188b99108d6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/2c7353448acc49602ade2930a18c0900956671c700cfb333234f0188b99108d6?s=96&d=mm&r=g","caption":"Matthew"},"url":"https:\/\/somewhatunlikely.com\/index.php\/author\/matthew\/"}]}},"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/somewhatunlikely.com\/index.php\/wp-json\/wp\/v2\/posts\/39","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/somewhatunlikely.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/somewhatunlikely.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/somewhatunlikely.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/somewhatunlikely.com\/index.php\/wp-json\/wp\/v2\/comments?post=39"}],"version-history":[{"count":0,"href":"https:\/\/somewhatunlikely.com\/index.php\/wp-json\/wp\/v2\/posts\/39\/revisions"}],"wp:attachment":[{"href":"https:\/\/somewhatunlikely.com\/index.php\/wp-json\/wp\/v2\/media?parent=39"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/somewhatunlikely.com\/index.php\/wp-json\/wp\/v2\/categories?post=39"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/somewhatunlikely.com\/index.php\/wp-json\/wp\/v2\/tags?post=39"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}