Category
Software Engineering

Published
Aug 25, 2020

Updated
Aug 26, 2020

Read
3 min

Tweet
Share
Comment

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 GameObjects while configuring and connecting Sectors with Portals was a pain in the ass.

GenerateSectorsWithPortals.cs was born.

Scene before

Before

Scene after

After (each green line per Sector = automated 🤘)

Appreciate the scale

Appreciating the scale

Example in action

Sectors 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 a GameObject 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 unit
  • Portal - MonoBehaviour on a GameObject whose configuration defines the connection between two Sectors
  • Graph - The derived structure that defines the relationships between all the Sectors and Portals
  • Loader - MonoBehaviour or code that triggers a Portal such that the Loader can use the Graph to dynamically load or unload connected Sectors

Below are the generated example MonoBehaviours of a selected Sector and Portal respectively.

Sector MonoBehaviour

Resulting example: Sector MonoBehaviour

Portal 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 Sectors and Portals. 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 Sectors with their Portal connections so you get a streamable world with the click of a button.

Generate sectors and portals basic menu

Yes, the v1 UI is super basic

Scene before reminder

Before (reminder)

Scene after 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 particular GameObject hierarchy
Sector template

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.

GitLab - Sectr Generation

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 the Transform 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 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.
DX/UX
  • Generated Sector and Portal 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 Sectors, where Portals can still be reset after Sector 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 and Portal prefabs are removed upon generation completion.

Enjoy.