For the last few months I’ve been tinkering on several “throwaway” Unity projects. Some of the projects were based on data we mess with at work (“hey, I wonder if I can import this into Unity 3D and blow it up!”), and some of was to test out ideas hatched in my brainz. I consider these projects throwaway because I never intend to finish them, but I definitely value my time spent on them as a form of learning. I also use these projects as benchmarks to develop my Unity-based code library against.
Each of them has brought with it some lessons, which I will try to reflect upon here, in the blog. This should give me some ongoing, short and hopefully helpful content! I tend to flick between the projects as often as the wind changes, which should give me a nice range of topics to cover.
The spark of my most recent project was an idea for a universe generation algorithm I’ve been mulling on for a few years.
The key goals for this mini-project were as follows:
- Procedural Generation of a seeded universe containing an endless set of systems, each containing a semi-believable assortment of stars, planets and moons.
- In-universe Agent Simulation. Pirates, traders, military, etc, all going about their business.
- Faction Power Struggle Simulation.
- Economic Simulation.
- Lastly, from a technical standpoint, and as an ongoing task across all projects, I wanted to try out a method of applying MVC design principles to a Unity project. Only interesting to programmers, but it should allow for rapid development. With the groundwork for this in place, create an interactive Visualiser to see the simulations at work.
So far I have tackled the Procedural Generation and Visualiser bits.
My goal here was not to invent some Elite: Dangerous-style Stellar Forge behemoth that knows the universe better than the universe itself, but instead to define a limited set of procedurally generated properties that can be used to present a reasonable approximation.
For example, my simulation is not concerned with Star temperature or Planet compositions; rather, I just want them to look different to each other. Therefore, the “look” of a star, moon or planet is simply a randomly-generated and unlimited integer, which then gets used (with a modulo) as an index into an array of predefined Unity GameObjects. Done!
Nor am I interested in proper orbits and solar masses and gravity wells, so rather than laying out astronomical objects thoughtfully, I just scatter them throughout the system. I am going for semi-believable, though, so I do have some smarts that mean stars tend to appear near the centre of the system, with planets and moons more likely as we move outwards. With a bit of fuzzyness in the logic, I get a nice mix of usually-has-star-in-the-middle and a nice occasional binary system, and even the occasional dark system!
The takeaway here is that procedural generation is what you make of it: start with raw random numbers, combine them with your human-refined content, then present the result to the player and hope they don’t see the 1s and 0s behind it all.
A core principle of good software architecture is the Single Responsibility Principle – a unit of code should try to focus on doing one thing only. This encourages code reuse and reduces the potential for unforeseen “knock-on” collateral damage when working on a seemingly unrelated part of your project.
The Model-View-Controller Pattern presents a method of separating your data (the model) from your display logic (in this case, messing with Unity objects). The controller acts as the facilitator of these two parts.
The actual implementation of the pattern will always vary across platforms and projects; in my implementation, I rely heavily on a “view-model binding” pattern to associate a Unity Component with a specific type of Model object; the Unity Component observes the state of the model and applies visual effects as necessary.
This allows me to write game logic without having to intersperse UI logic amongst it, keeping both the game logic and UI logic clearer and shorter (and therefore less prone to error).
The implementation can be found in the JoelMalone.Unity.View namespace of the JoelMalone.Unity project. While quite small (4 files), it is reasonably powerful, if as-yet unproven for anything beyond these “throwaway” projects. There is definitely room for optimisation, to be tackled when needed.
I plan to document and blog about the namespace (and JoelMalone.Unity in general) “one day.”
Right now, I have a Unity project that will generate and render a handful of systems and their astronomical contents. The simulation aspects will be next.
Interestingly, I have run into problems dealing with realistic-sized systems and astronomical objects, due to Unity’s use of single-precision floats to store transform data and the scales involved – for example, consider the radius of the Moon (~1737 Km) vs. Pluto at aphelion (~7 million Km from the Sun). I simply can’t represent a relatively tiny object like the moon and a ridiculously distant position using single-precision (it’s a Computer Science problem). This is completely reasonable and the common case, so it is up to me to solve it with smarts – a task that should be made easier by the clear separation of logic and UI that the MVC pattern presents. Essentially, I should only need to render relevant things at any given time, ignoring entities so far away they are effectively invisible.
Unfortunately I am unable to make the source code publicly available due to use of some third-party libraries. However, if there is any interest, I am happy to look into a project reshuffle to make it available.
Footnote: WordPress doesn’t allow me to host Unity projects. Clearly I made a great choice when choosing a host for such a Unity-focused blog! Once I sort this out, I’ll provide demos to go with these articles.
Attribution: the star, planet and moon meshes come from the Space for Unity package available on the Unity Asset Store.