Synergizing, orienting and aligning prefabs in C#

NOTE: For the TL;DR types, just read the question in bold at the bottom.

I have a set of dungeon prefabs which, when placed together, create a dungeon environment.
Now, I’d like to utilize my background in software development to script a random level generator. So naturally, I would need a way to know if any given prefab would work tiled together with any other given prefab(s). However, the trick here is that not all prefabs hold the same world-space dimensions, and (geometrically speaking) some prefabs would look strange linked to other certain ones, leaving gaps that the player could see through.

At first, I figured I could just use a 2D array or Dictionary to specify which prefabs play well with whatever other prefabs, and at which orientations. But rather than hardcoding this, I wonder if there would be a more dynamic approach?

One idea I had (which could also potentially work for any future prefabs I place into my project), was to create empty game objects tagged as “Magnets”, and attach them to the end of each individual prefab at specific vertices, essentially creating a flat primitive shape that could be compared to other “magnet” shapes attached to other prefabs. Then during level generation, after all the magnets on any given prefab successfully became linked to other magnets, it would be safe to delete them in the script, in order to free up run-time performance. This would work very nicely, but would probably require some sort of scalable 3D shape recognition algorithm in order to accurately compare 2 separate shapes… Which threw me off just enough to come back to square one.

So… Does anyone know an efficient, dynamic way to align two arbitrary geometrical pieces together via scripting?

The most easy to have some kind of markers (as you call magnets) and then simply have some config which type of magnet can be attached to which. And then make your modeller follow the rules. It will be much easier than trying to stick semi-arbitrary pieces together.

Edit:

When I say I would put markers/magnets, I mean I would put them in the modelling software. If you’re making your level objects in 3DsMax, then I would put special nodes and call them Magnets, you can orient them any way and position anywhere (and you don’t have to enter offsets and rotations by hand). Let your artist do the work in the environment that they are comfortable with. If you are doing it in Unity, then you can do the same - attach special GameObjects all call them Magnets.

Information about which magnet can be attached to which can be imported in multiple ways. You can have different types of magnets and then just define which type can be attache to which. Or you can store that information directly on each magnet. For example in 3dsMax there is such thing as UserProperties on each object. You can store magnet information there and import it into Unity. If you’re doing this in Unity, then you can simply attach a config script to each Magnet GameObject and store info there.

You can import and process more information from model files by implementing your own AssetPostprocessor. I would advise to familiarise yourself with it.

So I’ve managed to whip this little script up, which does the job… Magnet.cs - Pastebin.com

Just drop the script on any prefab, set the attributes in the editor window, and launch.

Attributes are as follows…

Polarity: The direction from the center of this object to become “magnetized”. This value becomes normalized upon startup.

Allowed: The list of qualified prefabs which can connect to this object. Will be attached to the side (or corner) specified by the polarity attribute.

Offset: This is for fine adjustments, and is applied to the final transformation of all “allowed” objects.

Some things that could improve this script:

  • Rotation, or the ability to set the “magnetized side” of the allowed objects
  • Automatic removal of all magnets after full initialization (to free up performance)
  • Your idea here?

Feel free to contribute to this!

Post your version in the comments below.

//////* Update (v2.0) *//////

  • Completely restructured, more user friendly!
  • Offsets now include rotation, and are separated from direction
  • To test this script, have at least 1 prefab in your project assets, and 1 parent object (like a simple 3D cube, or even an empty GameObject) in your scene/hierarchy… Then drag the Magnet script onto this parent object, and from the inspector be sure to drag your prefab asset from your project folder to the “Prefab” attribute in the script. Next, set the number of orientations that this prefab can connect to it’s parent, then manually enter each orientation (direction values should only range from -1.0 to +1.0 in each axis). If desired, you can also set offsets and/or rotations for those orientations… repeat for each prefab you wish to allow to connect to this parent object. Then, simply press play to see all specified prefabs created, attached and translated to it’s parent object!