Unity Array assistance

I'm currently working on a Unity project that uses perlin noise to build modern urban terrain. At each noise value I instantiate a prefab building (first floor) from an array. The next step is to instantiate prefab floors based on which ever building was chosen from the array. (e.g. At a point building_0 is chosen and the ground floor set, the code then loops through the floors associated with building_0 placing them until it reaches the roof level. At another point building_4 is chosen and the ground floor set, the code then loops through the floors associated with building_4 placing them until it reaches the roof level. This would continue until all buildings have been generated.)

Where I'm running in to a problem is designing the 2d array to facilitate multiple prefab building types with their associated prefab floors.

If my newness to this is making this difficult to understand, please let me know and I will try to elaborate. Below is the link to my single building test code on GitHub.

Can anyone point me in the right direction?

Thank you in advance for any assistance you can offer.



I'm one of the least expert programmers in Tech and Help, but I suspect using an array is probably not what you want to do here. Arrays are for identical types arranged in identical amounts, and the variability of buildings doesn't suit them at all. You'd end up with enormous amounts of wasted space, because each dimension would have to be defined large enough to contain the biggest thing of that type. If the tallest building is 50 stories, then a building of 5 stories, stuffed into an array, would still allocate room for 50. If the largest building is 20x20, then a 5x5 building will waste 3/4s of its allocated RAM. Like that.

Without any experience in doing software of this type, my first spitball model is the observation that you're collating a master list of all the possible buildings. Then each building has a list of floors, and then each floor has a list of objects. You're doing a list of lists of lists (of lists?), and many languages have list types that would suit this quite well. I assume you're working in C#, and I'm nearly certain it has lists.

In an object hierarchy, you'd probably start out with basic 3D things, like ceilings and walls and windows and doors. Each object would be a list of geometric elements, perhaps lines and maybe fills, possibly all in 2D. Then you'd do floor objects, which would have (at least) a height and a list of objects. Then you'd do building objects, which would have (at least) an X, Y, and Z location, probably a height (maybe computed by adding up all the floors), and a list of floor objects.

Finally, you'd build a master list containing all the possible building types, if you want them all to be pregenerated. The list itself would be pretty small, basically just containing pointers to building objects, but having a lot of predefined building objects could take prodigious amounts of memory. There's also some overhead in actually putting instances of your buildings into a scene, because each one needs X, Y, Z, and the building type.

I don't know if C# has generators, but Python has this concept, and I think it might be useful. A generator looks just like any other sequence object, and it works roughly like one. But, instead of storing a predefined list, it generates return values as it's queried. It's like a list that doesn't exist except in the exact spot you're presently looking. ("What's item 3?" and you get back item 3, but no other items presently exist. "What's the next item", and you get back item 4, but nothing else exists. It just remembered that item 3 was the last thing it gave you, so it handed you 4. Ask it again, and you'll get item 5. Items 1 through 4 aren't stored, and if you want them again, the code has to re-generate them.)

As an example of a generator, consider the Python range() function, which returns a numeric sequence of values based on its inputs. A naive implementation would create every number it was asked for, and return them all at once. If you asked for a range of a million numbers, you'd get many megabytes' worth of data, which would be stupidly wasteful just for counting. Only one value matters at any one time, so range() can best be implemented as a generator. It remembers its start, end, and step values, and the last value it returned, so it knows what to do next. It only needs to remember about four things, and it can generate as many numbers as you want.

Likewise, if you could do a building generator, where you gave it a seed value, then you wouldn't need to predefine your buildings. You'd have a list of possible floors, probably divided by sizes, and each building would remember X, Y, Z, and the last floor it returned, so it would know how to answer when queried for 'the next floor'. And if it was asked for, say, the third floor, then it could run whatever algorithm it has, select a floor 3, and return that.

In other words, as long as it was perfectly consistent about always returning the same floor 3, it would look like a static list of floors, and you could treat it that way, while actually being code with a seed value. This would let you make a whole lot of buildings in a very small amount of RAM.

If you'd rather stick with the pregenerated idea for now, then you interface with lists in pretty much the same way; the only real difference is that you have to create them before using them. Modern machines have oodles of memory, so burning 50 megs storing your buildings may not matter in the least, and you could get your landscapes up and running much sooner. You could always go back and plug generators in later on; because they're so similar (at least in Python, dunno about C#), they're pretty much drop-in replacements for one another.

Again, I'm not the best person to be giving you advice on this, but in my limited experience, algorithms are usually a lot easier if you get the data model right. This 'lists!' idea is obvious, and obvious ideas are not always the best ones. This is just a fumble from an amateur, and someone who's actually good might have a much better idea. I will say, however, that if you can figure out the right way to represent and store the data, the actual code to glue it together may fall out of your fingers without much effort.