- Fixed creating volumes issue outside of external volume mode
- Fixed generation speed for the CityGen example
- Fixed issue when deleting volumes from a building
- Fixed issue with initial long pause on multi building generation scene
- Fixed interior UV generation
- Fixed issue with room style not applying to some building rooms
- Fixed issue with editor locking selection onto building
I’ve been working on an extension that will implement a version of Interior Mapping for BuildR. For those that are unaware what that is, it’s a shader technique where you can fake interior rooms for buildings. It’s been used extensively in games and even in film.
The BuildR version will include code that will match up the shader data to the building data so that ceiling and floors are rendered in the correct position.
I’m also looking to support a basic environment lighting model inside the rooms along with direct and internal lighting to achieve a higher level of realism and to support nighttime environments along with daytime.
For simplicity the shader would use a single texture atlas and will randomise walls, floor and ceiling textures along with supporting curtains and blinds.
So towards the end of this release, I wanted to add some headers to my code files. A little warranty blurb, copyright, link to the support channel, version release. I’ve been using Rider over the last 18 months and was surprised that there was no way to generate these headers inside it. I had a look around and there really wasn’t anything obvious that I could use and would fit the specific use case I wanted to employ.
So like any good developer, I wrote my own script. Now, I’m no Python programmer! For a couple of years (and before this pandemic) I’ve been teaching computing at my local primary school to kids aged 8-12. We’ve either been on Scratch or Python. Of course, I didn’t know any Python when I started but that doesn’t stop an enthusiastic programmer! 😀
So, when I saw this problem, I saw a chance to exercise my Python skills and create something that would solve my specific needs! And it’s been ace, Python is a lot of fun.
I’ve popped the scripts onto Github so grab them and have a go if you need headers in your Unity project. Do make sure you’ve committed your scripts to a repo before you let this tear over your code! There is some basic documentation in the read me. Hope it’s useful to someone other than me!
- Added BuildR Asset Picker
- Added Atlased Dynamic Texture
- A lot of code cleanup, refactoring and commenting
- Added architecture to support BuildR Extensions
- Fixed issue with AABBox calculation in constructor
- Fixed issue with importing BuildR into a fresh project
- Fixed issue with default material not setting correctly in new project
- Fixed issue with room styles not being applied to some buildings
- Fixed issue with facade uv calculations across the horizontal grids
- Fixed issue with culling wallsections not rendering correctly on buildings.
- Fixed icon preview generation
- Fixed volume above not accounting for roof base value
- Added element duplication
- Fixed interior door placement UI size
- Added editor for volume stacking
- Added dynamic models to interior floorplans
- Fixed issue with Unity selecting objects behind BuildR when editing
- Fixed issue with facade design ground floor
- Added collider generation
- Improved building core UI
- Fixed UI blue dots rendering on wrong side of camera
- Assets renamed and standardised
- Preview icons now generate with shader colours
- Added Wallsection elements for shutters including open/close lerp
- Fixed issue with asset duplication in the BuildR asset system
- Added prefab model support to buildings
- Refactored asset data base classes – might cause issues that can be solved by refresh
- Fixed model preview drag on rotated view
- Fixed issue with new models created causing error
- Fixed error with new wallsection
- Fixed facade pattern editor UI
- Added new model placement system for geometry (prefabs to be added in following release)
- Added custom model wallsections
- Fixed issue with mouse behaving erratically again
- Fixed issue with mouse behaving erratically
- Started reworking how models are applied to buildings
- Fixed issue with Unity Editor frustum error
As work on version three progressed it became apparent that generating buildings would always be too expensive to do at runtime if you wanted to maintain a fast frame rate.
BuildR was very capable of generating simple buildings within milliseconds but version three had me targeting full city generation at runtime.
I had progressed well with the problem, developing a level of detail system and a simple manager to queue building generation so that we didn’t overwhelm the main thread. However, generating complex buildings would not be possible within the processing budget wanted.
The Job System
The last couple of years saw Unity unveil their job system as part of their move to data based programming. This was a very exciting development which I followed over Unite presentations and blog posts.
It would make sense to investigate what this new system could do for BuildR in solving it’s processing issue. This appeared at first to tie well into what version three was trying to achieve by extracting the data of BuildR from the Unity components and I headed into learning what the Job system has to offer…
Sadly, but thankfully very quickly, it was apparent that the Job System was not suited to what BuildR needed. The first problem was how the Job System would approach data. To ensure speed, it would want data bundled into similar chunks or in small simple packages. Trying to fathom how BuildR building data would fit into these constraints was overwhelming. It would require a complete rethink of how building data is stored and accessed.
The second issue was time. The Job System data had a very finite maximum lifetime and exceeding this would cause issues. I was aware that with very complex buildings, it could take a very long time to generate the geometry.
So, I decided that the Job System was not the magic bullet to solve BuildR’s runtime generation issue.
After my taste of the Job System though, I started to look into standard multithreading in Unity and C#. Games have not traditionally been multithreaded, so it was an area I was not highly clued up on. Unity and C# would work well together with a few caveats. C# itself is well provisioned to write this code. There are ample examples and explanations on what can be achieved and what should be avoided when writing multithreaded code. Unity isn’t written for this though. It lives on the main thread, as does it’s family of objects (gameobjects, materials, textures). Trying to do anything with these directly in threads would be a problem.
It did promise to fix the generation of even the most complex buildings. I was even thoughtful of it completely freeing the main thread of BuildR, allowing the game to run at whatever framerate it would sustain without generating buildings.
Using multithreading would also allow BuildR to generate multiple buildings in parallel too, making it even faster. I could use as many threads as I the system would give access to!
Adventures in Parallel Processing
Version three of BuildR had already been a process of splitting out the data from Unity, and this was going to pay off when I started to write multithreaded code. The buildings in BuildR were ideal candidates for multithreading to begin with. They were individual blocks of data what didn’t really touch other data points. There was also a lot of preprocessed data from Unity objects too (things like mesh data, bounds size) which would be inaccessible directly when off the main thread.
Writing the threading code involved changing the manager to deal with sending buildings off into their own threads and waiting for the procedurally generated building data to return.
On of the fun things about threads was the ease with which you could produce a race condition. The bugs created by this are hellish to reproduce as it’s entirely dependant on multiple processor cores working together (or should I say against each other).
I came across one simple case when multithreading BuildR. The most central class BuildR depends on is the Dynamic Mesh class. It handles collecting the generated mesh data into a format that can then be transferred over to a Unity mesh and they were used throughout BuildR to generate every part of it. In version three, two big things has changed about how I dealt with these objects so that I could reduce garbage allocation. First, I had the internal lists for vertices and normals set to a high capacity so that they would unlikely exceed this during generation. And second, I created a static pool of them so that we would only allocate what we needed and reuse what we had.
The static pool was accessed by the threads to get a Dynamic Mesh to generate BuildR wallsections and here was where the fun began. C# allows you to lock methods that are being accessed by multiple threads. It will elegantly block other threads when one is executing it and would form a queue while this is running. I had thought this method was well covered in my initial attempt but maybe after a hundred or so buildings were procedurally generated, there would be errors popping up that suggested I had not fully locked this class down and a race condition was happening. Instances of the Dynamic Mesh class were being reset by one thread finishing while another thread had got hold of it and started generating with it. So I was seeing errors halfway through the generation process that would normally be impossible to get that far.
The solution was to completely lock down the static pool so that only a single thread could access it at once. I wanted to be a little more smart about this class, as I worried it would be a bottleneck for the generation processes, however it seems it’s simpler and safer just to keep this class in lockdown.
Lifecycle and Synchronisation
Finally, I found that I would need to solidify my threaded code to deal with a simple lifecycle. I had created a generic class for dealing with threading that would transfer to other projects (and I aim to share that very soon!).
I created an interface that defines the lifecycle of the task sent to the threading manager and a simple identification and event system to allow external classes to intercept complete executions so that the data could be synchronised with the main thread.
So far this process has removed all building generation off the game thread and into the other unused cores of the processor. The framerate at runtime is now almost unaffected by complex building generation and we have the ability to generate multiple buildings at the same time giving us further speed at generating a city.