Generating 2D and 3D Streamable Worlds in Unity
This all started when I was working on Bugg, a 2.5D metroidvania where you play an intelligent computer bug escaping an organic machine. I was at the phase of development where I wanted to ensure the game was built on a strong foundation to support a streamable world (seamless background loading vs. noticeable in-game loading screens). A world akin to Ori and the Blind Forest and Hollow Knight size-wise for example. Sectr by Procedural Worlds was my go-to option for the streaming tech, but the manual process of dragging
GameObjects while configuring and connecting
Portals was a pain in the ass.
GenerateSectorsWithPortals.cs was born.
After (each green line per
Sector = automated 🤘)
Appreciating the scale
Sectors streamed based on Bugg position during play 🤯
If you're unfamiliar with Sectr, here are the basics to add context to the visuals above:
GameObjectwhose 3D bounds encapsulate an amount of assets (level objects, textures, audio, etc.) that can be dynamically loaded and unloaded at runtime as a single unit
GameObjectwhose configuration defines the connection between two
Graph- The derived structure that defines the relationships between all the
MonoBehaviouror code that triggers a
Portalsuch that the
Loadercan use the
Graphto dynamically load or unload connected
Below are the generated example
MonoBehaviours of a selected
What this all amounts to is a fairly simple system for having streamable worlds in Unity. It rocks. What does not rock is manually configuring and connecting the
Portals. I love me some automation.
By now you should get a feel for what
GenerateSectorsWithPortals.cs actually does. Yup, it automates the generation and configuration of
Sectors with their
Portal connections so you get a streamable world with the click of a button.
Yes, the v1 UI is super basic
Some additional DX/UX niceties are:
Sectorvolume dimensions (width, height, depth)
- Custom grid dimensions (small world or big af world, your choice)
- Optional Sector Template prefab so each
Sectorcomes preconfigured with a particular
Sector Template hierarchy example
With this Sector Template you can delegate generation of platforms, enemies, etc. The example images in this article just demonstrate the desired volume size for chunking your world. It's naturally still your responsibility for filling the volumes with game content.
If you end up using or forking
GenerateSectorsWithPortals.cs, don't hesitate to reach out on Twitter @derekknox and share what you are working on. Retweets are free. Get the source on GitLab.
In authoring the Unity editor script, I ran into a few interesting challenges. I've noted them below in hopes they'll help a fellow Unity dev get unstuck. They may also just be interesting in and of themselves.
Dynamic mesh volume generation
- This is used to inform each
Sector's bounds. The mesh vertices are repositioned dynamically vs. scaling the
Transformso the bounding volume remains at unit scale (1,1,1).
- The bounds calculations (akin to web dev requiring a render tick before bounds values are non-zero) require its
GameObjectto exist in the scene. The bounds are used so
Portals can visually display next to the
Sectors they are linked to.
- I initially messed up Unity's built-in primitive during this process, so ensure you make a proper mesh clone if you intend to use a Unity mesh primitive as a starting point.
Portalprefabs exist temporarily vs. requiring a user to create and drag existing prefabs. This ensures the default experience is just one button click.
- Smart regeneration occurs so the script won't overwrite existing
Portals can still be reset after
Sectoradditions or removals.
- You can add a Sector Template prefab which is used to instantiate a desired child hierarchy for each otherwise empty
- A custom mesh directory setting accounts for a user's Unity project's Assets directory preferences (the mesh isn't available for the clean up step mentioned below as otherwise the
Sectorvolumes would have an invalid Mesh reference).
- A clean up step prevents polluting the Assets directory, so temporarily generated
Portalprefabs are removed upon generation completion.