Generating 2D and 3D Streamable Worlds in Unity
Introduction
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 GameObject
s while configuring and connecting Sector
s with Portal
s was a pain in the ass.
GenerateSectorsWithPortals.cs
was born.
Before
After (each green line per Sector
= automated 🤘)
Appreciating the scale
Sector
s streamed based on Bugg position during play 🤯
Sectr
If you're unfamiliar with Sectr, here are the basics to add context to the visuals above:
Sector
-MonoBehaviour
on aGameObject
whose 3D bounds encapsulate an amount of assets (level objects, textures, audio, etc.) that can be dynamically loaded and unloaded at runtime as a single unitPortal
-MonoBehaviour
on aGameObject
whose configuration defines the connection between twoSector
sGraph
- The derived structure that defines the relationships between all theSector
s andPortal
sLoader
-MonoBehaviour
or code that triggers aPortal
such that theLoader
can use theGraph
to dynamically load or unload connectedSector
s
Below are the generated example MonoBehaviour
s of a selected Sector
and Portal
respectively.
Resulting example: Sector
MonoBehaviour
Resulting example: Portal
MonoBehaviour
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 Sector
s and Portal
s. I love me some automation.
Code
By now you should get a feel for what GenerateSectorsWithPortals.cs
actually does. Yup, it automates the generation and configuration of Sector
s with their Portal
connections so you get a streamable world with the click of a button.
Yes, the v1 UI is super basic
Before (reminder)
After (reminder)
Some additional DX/UX niceties are:
- Custom
Sector
volume dimensions (width, height, depth) - Custom grid dimensions (small world or big af world, your choice)
- Optional Sector Template prefab so each
Sector
comes preconfigured with a particularGameObject
hierarchy
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.
Challenges
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 theTransform
so 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
GameObject
to exist in the scene. The bounds are used soPortal
s can visually display next to theSector
s 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.
DX/UX
- Generated
Sector
andPortal
prefabs 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
Sector
s, wherePortal
s can still be reset afterSector
additions or removals. - You can add a Sector Template prefab which is used to instantiate a desired child hierarchy for each otherwise empty
Sector
. - 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
Sector
volumes would have an invalid Mesh reference). - A clean up step prevents polluting the Assets directory, so temporarily generated
Sector
andPortal
prefabs are removed upon generation completion.
Enjoy.