{"id":42749,"date":"2018-05-15T07:36:21","date_gmt":"2018-05-15T11:36:21","guid":{"rendered":"http:\/\/shamusyoung.com\/twentysidedtale\/?p=42749"},"modified":"2018-05-15T16:27:04","modified_gmt":"2018-05-15T20:27:04","slug":"pixel-city-redux-6-the-distraction","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=42749","title":{"rendered":"Pixel City Redux #6: The Distraction"},"content":{"rendered":"<p>What do you do when you want to look something up but you don&#8217;t know what it&#8217;s called? Sometimes you can just type what you know into a search engine and it will sort things out for you. I just typed &#8220;part of the car that covers the engine&#8221; and I got:<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_hood.jpg' width=100% alt='thing that you type sentence fragments into for information' title='thing that you type sentence fragments into for information'\/><\/div><div class='mouseover-alt'>thing that you type sentence fragments into for information<\/div><\/p>\n<p>It&#8217;s not a perfect result. A careless reader might look at the text and think the answer is &#8220;trunk&#8221;. But it&#8217;s still really incredible that a search engine can come up with answers like this. If you&#8217;re willing to read more than the first sentence, you can find what you&#8217;re looking for, even if you don&#8217;t know what a hood was called when you started.<\/p>\n<p>Sadly, things are not always this easy. Right now I know what I want to make but I don&#8217;t know what to search for. I know what it looks like and how it behaves, but not how  it&#8217;s created or what you call it. In fact, I can even draw a picture of it. It looks kind of like a stained glass window. Here is one I made by hand:<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_mystery.jpg' width=100% alt='Uh... Something like this.' title='Uh... Something like this.'\/><\/div><div class='mouseover-alt'>Uh... Something like this.<\/div><\/p>\n<p>You generate this by putting a bunch of points on a plane and&#8230; doing some sort of math to them. I want to use something like this to divide my city into regions. Let&#8217;s see what Google has for me:<\/p>\n<p><!--more--><code>\"dividing a 2D plane into regions\"<\/code><\/p>\n<p>Nope. That&#8217;s not it. All these results are about using line segments to divide a plane, which is what I did a few entries ago. Now I want to use dots or control points. Maybe the dots are given a position and size \/ radius? <\/p>\n<p><code>\"Divide 2D plane into regions using control points\"<\/code><\/p>\n<p>Nope. That&#8217;s not it. These results are all about intersecting 2D planes in 3D space, and I&#8217;m not looking for that kind of trouble. Hmmm.<\/p>\n<p><code>\"2d plane divide into bounded regions using control points\"<\/code><\/p>\n<p>Nope. More 3D space division using 2D planes. Now that I&#8217;m thinking about it, maybe the &#8220;control points&#8221; is throwing things off. That&#8217;s what I would call these things in code, but I get the sense that this is not what a mathematician would call them. I am definitely invading the mathematics clubhouse right now and I probably need to speak their lingo. On the other hand, what DO I call these things? Points? That sounds generic enough that it could lead to anything. <\/p>\n<p>This goes on for several minutes. I&#8217;ll run out of ideas and then go and watch <a href=\"https:\/\/www.youtube.com\/watch?v=RZFMgb7SRKI\">random<\/a> <a href=\"https:\/\/www.youtube.com\/watch?v=GXXCj5kqPcM\">YouTube<\/a> <a href=\"https:\/\/www.youtube.com\/watch?v=bWL_MVbpGT0\">videos<\/a> for a bit. Then I&#8217;ll get an idea, type more crap into Google, get unhelpful results, and then go back to wasting my time on YouTube. <\/p>\n<p>Maybe I&#8217;m overthinking this:<\/p>\n<p><code>\"diagram that looks like stained glass window\"<\/code><\/p>\n<p>Nope. Although this does lead to a nice little tangent regarding Venn diagrams. <\/p>\n<p><code>\"divide 2d grid into regions with points\"<\/code><\/p>\n<p>No.<\/p>\n<p><code>\"diagram with bounded regions\"<\/code><\/p>\n<p>Interesting, but not what I&#8217;m looking for.<\/p>\n<p><code>\"subdivide 2d plane irregular\"<\/code><\/p>\n<p>No. Although part way through typing that Google autocomplete suggests &#8220;subdivide 2d plane <b>crash<\/b>&#8220;, which is either hilarious or terrifying. <\/p>\n<p>I try throwing &#8220;euclidian&#8221; in the mix to try and trick Google into showing me where the mathematicians keep the treasure, but Google&#8217;s having none of it.<\/p>\n<p>Time passes. Eventually I try:<\/p>\n<p><code>\"diagram with irregular regions\"<\/code><\/p>\n<p>Boom! It doesn&#8217;t link me directly to my target, but it brings up an image search that contains the kind of thing I&#8217;m looking for, and when I follow the image back to the site I discover it&#8217;s an article about <a href=\"https:\/\/en.wikipedia.org\/wiki\/Voronoi_diagram\">Voronoi Diagrams<\/a>.<\/p>\n<p>Yes! That&#8217;s the one!<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_voronoi.jpg' width=100% alt='Finding this was the EASY part.' title='Finding this was the EASY part.'\/><\/div><div class='mouseover-alt'>Finding this was the EASY part.<\/div><\/p>\n<p>I read about this thing years ago and I&#8217;d forgotten almost everything about it, aside from what the result looked like. Now that I&#8217;m reading the process, it sounds a lot more involved that I&#8217;d imagined. The key here is that if you&#8217;re on one of the region boundaries, then you&#8217;re at the point equidistant to the points on either side of the line. More informally: If this was a city and the dots were all pizza places, then when you&#8217;re in the green region, the pizza place inside that region is the closest one in town. (Assuming you can get an Uber that follows as-the-crow-flies navigation.) This diagram can have you solve problems like figuring out the closest hospital \/ fire station for the given address. (Again, ignoring the thorny problem of traffic routing.) Here&#8217;s <a href=\"http:\/\/alexbeutel.com\/webgl\/voronoi.html\">a really fun diagram generator<\/a> you can play with. Once you have a few dots on the board, click and drag to see the region change shape in realtime.<\/p>\n<p>I&#8217;m not interested in pizza or hospital routing problems here. I just want this because it looks cool.  <\/p>\n<p>This thing is actually a lot more complex than I anticipated. I just need to cut my city up into regions, and there are easier ways of making that happen than to implement something like this. On the other hand&#8230; I want to anyway. <\/p>\n<h3>Let&#8217;s Do This<\/h3>\n<p><a href=\"http:\/\/datagenetics.com\/blog\/may12017\/index.html\">There are a lot of ways to make these things<\/a>. Some are focused on speed. Some are described as if you were creating the thing by hand on paper. I usually avoid the latter sorts of explanations when I&#8217;m trying to code something, because they often leave out important details. If you&#8217;re doing a worksheet and I tell you to &#8220;circle any letters with <a href=\"https:\/\/xkcd.com\/1015\/\">bad kerning<\/a>&#8220;, then that&#8217;s easy to say and easy for you to understand and trivial for you to do. But implementing that in code would be a massive undertaking. But in this case <a href=\"http:\/\/www.instructables.com\/id\/Hand-Drawn-Voronoi-Diagrams\/\">the art-n-crafts style explanation<\/a> happens to translate pretty well into code.<\/p>\n<p>I&#8217;m interested in a method that will limit code complexity. I don&#8217;t really care if this is &#8220;slow&#8221;. I don&#8217;t imagine I&#8217;ll have more than a dozen regions and I only need to do this once when generating the city, so the difference between a fast, complicated method and a slow simple one will be imperceptible. Maybe a really efficient Voronoi generator can do the job in under 1 millisecond while a shamefully slow one would dawdle and waste seven entire milliseconds. Who cares? If the second one has fewer lines of code and is easier to implement, then it&#8217;s the right choice. <\/p>\n<p>The process goes like this:<\/p>\n<p>Throw down a bunch of dots, one for every region. For best results, try to make sure they&#8217;re spaced out a bit and you don&#8217;t have too many clustered together.<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_voronoi1.jpg' width=100% alt='Meh. Close enough.' title='Meh. Close enough.'\/><\/div><div class='mouseover-alt'>Meh. Close enough.<\/div><\/p>\n<p>Great. Now this is the weird part that feels like magic. Apparently you can group these points into triangles by making groups of three that do not contain any other points within their circumcircle. Imagine drawing a circle that intersects all three corners. If that circle contains any other points, then you&#8217;ve got an invalid group of three. Try three others. <\/p>\n<p>Somehow, this always forms a tidy mesh of triangles without nasty acute triangles, without odd gaps between them, and without any triangles overlapping. Each triangle should have a circle associated with it, which just consists of a the circumcenter point and the radius of the circle. Note that the circumcenter point itself may fall outside the bounds of the triangle. That&#8217;s fine. As long as the circle doesn&#8217;t contain any other points, you&#8217;re good.<\/p>\n<p>When I read these directions I imagined it would just produce a big pile of disjointed triangles, but when I implemented it I got:<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_voronoi2.jpg' width=100% alt='Swiped from Wikipedia.' title='Swiped from Wikipedia.'\/><\/div><div class='mouseover-alt'>Swiped from Wikipedia.<\/div><\/p>\n<p>Now to finish it off. Each of those circumcircles is connected to a triangle. That triangle is obviously made up of three line segments. Each of those line segments divides this circumcircle from one of its three neighbors. Draw a line from this circumcenter to each of those three neighbors. When you&#8217;ve done this for all the triangles, you&#8217;ll have your Voronoi diagram:<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_voronoi3.jpg' width=100% alt='I guess it works.' title='I guess it works.'\/><\/div><div class='mouseover-alt'>I guess it works.<\/div><\/p>\n<p>Here is the resulting code:<\/p>\n<pre lang=\"csharp\" line=\"1\">\r\n\/*------------------------------------------------------------------------------------\r\n * Voroni \r\n * \r\n * This is an implementation an an algorithm to generate a Voronoi Diagram. This\r\n * takes a series of points on a plane and generates regions to contain those points.\r\n * \r\n * This has been optimized for simplicity and readability, not speed. If you plan \r\n * on using this to make thousands of regions, you might want to tighten it up.\r\n * \r\n * ---------------------------------------------------------------------------------*\/\r\n\r\nusing System.Collections.Generic;\r\nusing UnityEngine;\r\nusing System.Linq;\r\n\r\n\r\npublic class TriangleJoins\r\n{\r\n\tpublic bool ab;\r\n\tpublic bool bc;\r\n\tpublic bool ca;\r\n\r\n\tpublic TriangleJoins () {\r\n\t\tab = bc = ca = false;\r\n\t}\r\n}\r\n\r\npublic class VoroniRegion\r\n{\r\n\tpublic int          index;\r\n\tList<LineSegment>   perimeter;\r\n\tVector2             center;\r\n\tVector2             origin;\r\n\tfloat               radius;\r\n\r\n\tpublic float Radius () { return radius; }\r\n\r\n\tpublic VoroniRegion (Vector2 origin_in, int index_in) {\r\n\t\torigin = origin_in;\r\n\t\tindex = index_in;\r\n\t\tperimeter = new List<LineSegment> ();\r\n\t}\r\n\r\n\tprivate void CalculateCenter () {\r\n\t\tcenter = Vector2.zero;\r\n\t\tradius = 0f;\r\n\r\n\t\tfor (int i = 0; i < perimeter.Count; i++) {\r\n\t\t\tcenter += perimeter[i].start;\r\n\t\t\tcenter += perimeter[i].end;\r\n\t\t}\r\n\t\tcenter \/= (float)perimeter.Count * 2f;\r\n\t\tfor (int i = 0; i < perimeter.Count; i++) {\r\n\t\t\tradius = Mathf.Max (radius, (perimeter[i].start - center).magnitude);\r\n\t\t\tradius = Mathf.Max (radius, (perimeter[i].end - center).magnitude);\r\n\t\t}\r\n\t}\r\n\r\n\r\n\tpublic void PushLine (LineSegment s) {\r\n\t\tLineSegment l = new LineSegment (s.start, s.end);\r\n\t\tperimeter.Add (l);\r\n\t\tCalculateCenter ();\r\n\t}\r\n\r\n\tpublic List<LineSegment> Perimeter () { return perimeter; }\r\n\tpublic Vector2 Center () { return center; }\r\n\tpublic Vector2 Origin () { return origin; }\r\n}\r\n\r\npublic class Voroni\r\n{\r\n\r\n\tVector2[]               _points;\r\n\tTriangleJoins[]         _joins;\r\n\tList<LineSegment>       _lines;\r\n\tList<Triangle>          _triangles;\r\n\tpublic VoroniRegion[]   _regions;\r\n\r\n\tpublic Triangle[] Triangles () { return _triangles.ToArray (); }\r\n\r\n\tprivate int[] TwoClosestNeighbors (int self) {\r\n\t\tList<Vector2>   others = new List<Vector2>();\r\n\t\t\/\/Make a version of our list that doesn't include ourselves.\r\n\t\tfor (int i = 0; i < _points.Length; i++) {\r\n\t\t\tif (i == self)\r\n\t\t\t\tcontinue;\r\n\t\t\tVector2 other = new Vector2 ();\r\n\t\t\tother.x = (float)i;\r\n\t\t\tother.y = (_points[i] - _points[self]).magnitude;\r\n\t\t\tothers.Add (other);\r\n\t\t}\r\n\t\tothers = others.OrderBy (t => t.y).ToList ();\r\n\t\tList<int> sorted = new List<int> ();\r\n\t\tint count = 0;\r\n\t\tforeach (Vector2 v in others) {\r\n\t\t\tsorted.Add ((int)v.x);\r\n\t\t\tcount++;\r\n\t\t\tif (count == 2)\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\treturn sorted.ToArray ();\r\n\t}\r\n\r\n\t\/\/Put a division line between each point and its 3 closest neighbors.\r\n\tprivate void Triangulate () {\r\n\t\tfor (int p1 = 0; p1 < _points.Length; p1++) {\r\n\t\t\tfor (int p2 = p1 + 1; p2 < _points.Length; p2++) {\r\n\t\t\t\tfor (int p3 = p2 + 1; p3 < _points.Length; p3++) {\r\n\t\t\t\t\tTriangle tri = new Triangle (_points, p1, p2, p3);\r\n\t\t\t\t\t\/\/Make sure the triangle is constructed clockwise.\r\n\t\t\t\t\tVector2 to_center = (_points[tri.b] - _points[tri.a]).normalized.TurnedRight ();\r\n\t\t\t\t\tVector2 edge = (_points[tri.a] + _points[tri.b]) \/ 2f;\r\n\t\t\t\t\tVector2 from_center = (edge - tri.center).normalized;\r\n\t\t\t\t\tfloat dot = Vector2.Dot (to_center, from_center);\r\n\t\t\t\t\tif (dot < 0)\r\n\t\t\t\t\t\ttri.Flip ();\r\n\t\t\t\t\tif (!tri.FindCircumcenter (1000))\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\/\/Now we have the circumcirle. See if any other points land inside it.\r\n\t\t\t\t\tbool contains_other_points = false;\r\n\t\t\t\t\tfor (int i = 0; i < _points.Length; i++) {\r\n\t\t\t\t\t\t\/\/Doin't check our own points.\r\n\t\t\t\t\t\tif (i == tri.a || i == tri.b || i == tri.c)\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\tif ((_points[i] - tri.circumcenter).magnitude < tri.circumcircle_radius) {\r\n\t\t\t\t\t\t\tcontains_other_points = true;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (contains_other_points)\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t_triangles.Add (tri);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t\/\/Used during triangulation. Every line segment is a divider between two regions, and all \r\n\t\/\/triangles are wound clockwise. So to find a neighbor triangle you search for points in \r\n\t\/\/reverse order. Triangle a b c will share a border with the triangle of d b a,\r\n\t\/\/because (b a) and (a b) are the same line segment.\r\n\tprivate int FindTriangleWithSegment (int start, int end) {\r\n\t\tfor (int i = 0; i < _triangles.Count; i++) {\r\n\t\t\tif (_triangles[i].a == start &#038;&#038; _triangles[i].b == end &#038;&#038; _joins[i].ab == false) {\r\n\t\t\t\t_joins[i].ab = true;\r\n\t\t\t\treturn i;\r\n\t\t\t}\r\n\t\t\tif (_triangles[i].b == start &#038;&#038; _triangles[i].c == end &#038;&#038; _joins[i].bc == false) {\r\n\t\t\t\t_joins[i].bc = true;\r\n\t\t\t\treturn i;\r\n\t\t\t}\r\n\t\t\tif (_triangles[i].c == start &#038;&#038; _triangles[i].a == end &#038;&#038; _joins[i].ca == false) {\r\n\t\t\t\t_joins[i].ca = true;\r\n\t\t\t\treturn i;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn -1;\r\n\t}\r\n\r\n\t\/\/At this point we've performed the Delaunay triangulation. We need to turn this into the \r\n\t\/\/N-sided polygons of the Voronoi diagram. To do this, draw a line from the circumcenter\r\n\t\/\/of each triangle to the circumcenters of the Triangle's three neighbors. The resulting\r\n\t\/\/lines will form the Voronoi diagram.\r\n\tprivate void Join (int index) {\r\n\t\tint neighbor;\r\n\t\tif (!_joins[index].ab) {\r\n\t\t\tneighbor = FindTriangleWithSegment (_triangles[index].b, _triangles[index].a);\r\n\t\t\tif (neighbor != -1) {\r\n\t\t\t\t_joins[index].ab = true;\r\n\t\t\t\tJoin (neighbor);\r\n\t\t\t\tLineSegment l = new LineSegment ();\r\n\t\t\t\tl.start = _triangles[index].circumcenter;\r\n\t\t\t\tl.end = _triangles[neighbor].circumcenter;\r\n\t\t\t\t_lines.Add (l);\r\n\t\t\t\t_regions[_triangles[index].a].PushLine (l);\r\n\t\t\t\tl.Flip ();\r\n\t\t\t\t_regions[_triangles[index].b].PushLine (l);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!_joins[index].bc) {\r\n\t\t\tneighbor = FindTriangleWithSegment (_triangles[index].c, _triangles[index].b);\r\n\t\t\tif (neighbor != -1) {\r\n\t\t\t\tJoin (neighbor);\r\n\t\t\t\t_joins[index].bc = true;\r\n\t\t\t\tLineSegment l = new LineSegment ();\r\n\t\t\t\tl.start = _triangles[index].circumcenter;\r\n\t\t\t\tl.end = _triangles[neighbor].circumcenter;\r\n\t\t\t\t_lines.Add (l);\r\n\t\t\t\t_regions[_triangles[index].b].PushLine (l);\r\n\t\t\t\tl.Flip ();\r\n\t\t\t\t_regions[_triangles[index].c].PushLine (l);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!_joins[index].ca) {\r\n\t\t\tneighbor = FindTriangleWithSegment (_triangles[index].a, _triangles[index].c);\r\n\t\t\tif (neighbor != -1) {\r\n\t\t\t\tJoin (neighbor);\r\n\t\t\t\t_joins[index].ca = true;\r\n\t\t\t\tLineSegment l = new LineSegment ();\r\n\t\t\t\tl.start = _triangles[index].circumcenter;\r\n\t\t\t\tl.end = _triangles[neighbor].circumcenter;\r\n\t\t\t\t_lines.Add (l);\r\n\t\t\t\t_regions[_triangles[index].c].PushLine (l);\r\n\t\t\t\tl.Flip ();\r\n\t\t\t\t_regions[_triangles[index].a].PushLine (l);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprivate void Join () {\r\n\t\t_joins = new TriangleJoins[_triangles.Count];\r\n\t\tfor (int i = 0; i < _triangles.Count; i++)\r\n\t\t\t_joins[i] = new TriangleJoins ();\r\n\t\tJoin (0);\r\n\t}\r\n\r\n\r\n\tpublic LineSegment[] Lines () {\r\n\t\treturn _lines.ToArray ();\r\n\t}\r\n\r\n\t\/\/This is our starting point. Pass in an array of points here,\r\n\t\/\/and then extract the results from the public array of \r\n\t\/\/VoronoiRegions in _regions.\r\n\tpublic Voroni (Vector2[] points) {\r\n\t\t_lines = new List<LineSegment> ();\r\n\t\t_triangles = new List<Triangle> ();\r\n\t\t_regions = new VoroniRegion[points.Length];\r\n\t\t_points = points;\r\n\t\tfor (int i = 0; i < _regions.Length; i++) {\r\n\t\t\t_regions[i] = new VoroniRegion (points[i], i);\r\n\t\t}\r\n\t\tTriangulate ();\r\n\t\tJoin ();\r\n\t}\r\n}\r\n<\/pre>\n<p>I apologize for putting this wall of code here. I really need to find a WordPress plugin that will let me hide big stuff like this so that people who care can click to unroll it, and everyone else can just keep scrolling. Maybe you appreciate seeing the code, maybe you'd rather I put it inside a download link. Whatever.<\/p>\n<p>The point is, we got this job done in under 250 lines of code. That's pretty good. <\/p>\n<p>On the other hand, I never did learn the most important thing, which is: <em>How the heck are you supposed to pronounce \"Voronoi\"?!<\/em> I checked YouTube and I heard people use both \"voroh-noy\" and \"voor-onny\". (Sounds like \"Poor Johnny\".) In my head I've been pronouncing it \"Vore-oni\". That's certainly incorrect, but I like it because it makes this sounds like some kind of pasta: Macaroni, Ravioli, and \"Voroni\".<\/p>\n<p>So we're done. The problem is...<\/p>\n<h3>I Don't Really Need This Thing<\/h3>\n<p>My street-building code struggles when the angles get acute or when two intersections wind up too close together. Two adjacent roads will end up overlapping, which screws up their polygons, which causes a bunch of obnoxious <a href=\"https:\/\/en.wikipedia.org\/wiki\/Z-fighting\">z-fighting<\/a>. The last thing I need is a system that will make the street connections even more difficult. This code I just wrote can generate different regions so I can have different buildings in different parts of the city, but <em>I haven't even made a proper building generator yet<\/em>. <\/p>\n<p>So why am I ignoring the core task (making buildings) to work on a bit of support code that's an over-complicated solution to a problem that I don't have yet, and which makes the existing problems even worse?<\/p>\n<p>This is not the first time in the project I've gone off-mission and begun messing with things that don't matter. What's wrong with me?<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_introspection.jpg' width=100% alt='INTROSPECTION INTENSIFIES' title='INTROSPECTION INTENSIFIES'\/><\/div><div class='mouseover-alt'>INTROSPECTION INTENSIFIES<\/div><\/p>\n<p>Sigh.<\/p>\n<p>It's Unity. Or rather, it's the process of learning Unity. It's just so relentlessly frustrating. It would be one thing if I had to stop every fifteen minutes or so and read some documentation. That would actually be pretty nice. That sounds like a fun afternoon. Instead, it's this never-ending rabbit-hole of mystery and bafflement. <\/p>\n<p>I'll run into some problem. The manual doesn't have any clues. There's an archive of an instructional livestream on the topic, but this is a problem that could be sorted out in two sentences and shouldn't require watching an hour of unedited video.<\/p>\n<p>So I turn to the forums. Someone asks a question that sounds 85% like the problem I'm having. They get three contradictory answers. I try the top answer and it doesn't work in the version of Unity I'm using. I try the second answer and it sort of solves the problem, but creates a new one that sends me back to searching. So then I plunge down THAT rabbit-hole and end up in the same cycle of not finding anything in the manual, skipping a huge video, and going back to the forums. After an hour of that - assuming I don't get sucked down a third rabbit-hole - I'll give up, spend half an hour spooling through one of these videos, and discover it doesn't actually answer my question.<\/p>\n<p>Unity is really powerful. You can do amazing things with it. Stuff that might take hours on another platform can be done in seconds. But then you'll run into something that should be trivial and ends up being insurmountable.<\/p>\n<h3>Perhaps an Example Would Be Useful?<\/h3>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_editor1.jpg' width=100% alt='The custom dialog I made for generating my city. This bit was effortless. I just told Unity which variables I wanted to edit and it made the interface for me.' title='The custom dialog I made for generating my city. This bit was effortless. I just told Unity which variables I wanted to edit and it made the interface for me.'\/><\/div><div class='mouseover-alt'>The custom dialog I made for generating my city. This bit was effortless. I just told Unity which variables I wanted to edit and it made the interface for me.<\/div><\/p>\n<p>I have a script that builds my city and populates it with objects. I've got it all wired up in the editor so that I can press a button and get a city. Then I can fiddle with some sliders, press the button again, and get another city with slightly different properties. The problem is that I need to clean up the old city, which means deleting objects, and Unity does not like you using code to delete objects in edit mode. Oh, it will let you <em>create<\/em> them by the thousands of you like, but then I guess you're supposed to manually delete them by hand?!?<\/p>\n<p>Let's set aside my city, which I admit is a pretty complicated use-case. Let's say you've got a basic shooter level and you've created a script that will scatter healthpacks around. You hit the button, and the script populates the level with healthpacks. Maybe you think there are too many, so you adjust the properties and hit the button again. Ideally, the script should find all objects of type \"Healthpack\" in the scene, delete them, and then add new ones. So you write some code:<\/p>\n<pre lang=\"csharp\" line=\"1\">\r\nGameObject[] medpacks = FindObjectsOfType<Medpack>();\r\n\r\nforeach (GameObject other in medpacks) { \r\n  Destroy(other); \r\n}\r\n<\/pre>\n<p>But then you hit the button and the console is flooded with errors:<\/p>\n<p><code>Destroy may not be called from edit mode! Use DestroyImmediate instead.<\/code><\/p>\n<p>Oh, okay. This is something I'm only doing in the editor, so I guess that makes sense. I'll just change Destroy () to DestroyImmediate () and...<\/p>\n<p><code>Destroying components immediately is not permitted during physics trigger\/contact, animation event callbacks or OnValidate. You must use Destroy instead.<\/code><\/p>\n<p>This is a really simple thing we're trying to do here. Absolutely trivial. And yet if you dig deep enough in the forums you'll find people with all kinds of hacks to make this trivial action possible. The best solution I've found so far:<\/p>\n<pre lang=\"csharp\" line=\"1\">\r\nforeach (Transform child in MedpackContainer.gameObject.transform) {\r\n\tUnityEditor.EditorApplication.delayCall += () => \r\n        {\r\n\tif (child.gameObject != null)\r\n\t\tDestroyImmediate (child.gameObject);\r\n\t};\r\n}\r\n<\/pre>\n<p>So you round up all the objects you want to kill, and then you kick off a delayed coroutine (kind like a new thread) to delete each one of them.  This seems like a horribly over-complicated solution to the problem and I don't even understand the syntax happening around that delayCall thing. <\/p>\n<p>It took me a few hours to find that solution. I tried a lot of other things, which either failed utterly, weren't viable in this version of Unity, or simply moved the problem to somewhere else. (I found one that did manage to kill the desired objects, but due to the way it juggled references around it also wound up deleting some of the new objects I'd just created.)<\/p>\n<p>One of the Unity developers noticed this trap <a href=\"https:\/\/forum.unity.com\/threads\/onvalidate-and-destroying-objects.258782\/#post-1710049\">way back in 2014<\/a>. And yet here we are, four years later, trying to piece together a convoluted solution from snatches of random forum code to solve a trivial problem with no guidance from the documentation. <\/p>\n<p>I run into stuff like this constantly, and it's just demoralizing, which is why I just spent the afternoon cooking myself a big plate of voronoi. It wasn't something I needed to do, but it was a straightforward problem with known solutions and enough documentation to set me on my way. I could spend a few hours writing code instead of wading through noise in the forums. <\/p>\n<p>The longer I use Unity, the more I'm impressed by its speed and capabilities. This is an amazingly powerful tool and when things work the way they should it makes me feel like a one-man AAA development studio. But that power is so deeply hidden that I don't feel like I'm learning Unity so much as <em>reverse-engineering<\/em> it. <\/p>\n<p>Maybe this procgen stuff is just too different from the \"intended\" Unity workflow. Maybe if I was sticking closer to the script I'd have an easier time learning. I don't know.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What do you do when you want to look something up but you don&#8217;t know what it&#8217;s called? Sometimes you can just type what you know into a search engine and it will sort things out for you. I just typed &#8220;part of the car that covers the engine&#8221; and I got: It&#8217;s not a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[66],"tags":[],"class_list":["post-42749","post","type-post","status-publish","format-standard","hentry","category-programming"],"_links":{"self":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/42749","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=42749"}],"version-history":[{"count":19,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/42749\/revisions"}],"predecessor-version":[{"id":42768,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/42749\/revisions\/42768"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=42749"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=42749"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=42749"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}