BLOG


Tumblr

GearBlocks on Steam

GearBlocks Demo 0.6.7560

Hey everyone, I've just released a minor update to the demo.  Here are the release notes:-

Saved game / construction format changed to support part attachment improvements, old saves are converted when loaded.Parts can now slide along multiple slider rails that are placed end-to-end.Constructions are now spawned frozen and positioned in front of the player, rather than being immediately selected.Player free flight movement now has a different acceleration and a higher top speed when holding shift.Bug fixes.Upgraded to Unity 2019.4.10.

Part alignments and slider rails

Greetings all, I think it’s time for an update on what’s been happening for the past few weeks!  I got back up and running on a newly built PC after the old one gave up the ghost, and I’ve been working on task management stuff, making various improvements to the game, and fixing bugs.

Trello

During the down time while waiting for parts to arrive for my new PC, I couldn’t make much development progress, so I took the opportunity to get set up on Trello for task tracking.  All of my tasks are on there now, as well as feature requests and suggestions from the GearBlocks community.  Many of the tasks still need fleshing out more and perhaps breaking up into sub-tasks, but it’s a decent start.

image

The great thing about Trello is that it gives people the opportunity to comment and vote on tasks.  Currently it’s set up as invite only, so if you’d like access, email me at: sam@gearblocksgame.com

Part alignments

I’ve been making improvements to how part alignment works, specifically how alignment positions & orientations are defined and processed.

Previously, a part’s alignment grids could be specified from a local origin + width & depth values, saving the need to specify each alignment point individually.  Now, these grids have been extended to optionally have a height value, allowing for alignment “columns” to be more compactly represented (useful for axles for example).

Also, the alignment grid setup and search code has now been refactored to be simpler, easier to debug, and easier to extend.

All this was a prelude to the main change, which was to make part attachments (fixed, rotary bearing, etc.) refer to the alignment grids that they were created from.  An attachment now gets its orientation and allowed attachment types directly from the alignment grid, saving the need to store them separately.  The main reason for doing all this though was to address a problem with linear bearings which I’ll come to in a moment, but having access to the alignment grids this way has other advantages too, for example it allows for retrieving the alignment type when displaying attachment indicators (e.g. surface vs. interior could be shown differently).  This is something I’ll hopefully get to make use of in the future.

As attachments now index into their source alignment grids, I had to change the save format to store these indices.  I’ve implemented code to convert old saved games / constructions upon load so that their attachments reference valid alignment grids.

Sliding distances

When setting up the physics constraint for a linear bearing attachment, a sliding distance and anchor offset need to be calculated.  Previously this was done by simply using the bounds of the part, i.e. its outer dimension along the sliding direction.  However this only works for simple “convex” parts (e.g. blocks and axles), for anything more complex, the sliding distance may need to be less than the size of its bounds.

So to solve this, the sliding distance and offset for a linear bearing attachment is now calculated based on the dimensions of its source alignment grids, which it has access to due to the changes I mentioned earlier.

The slider rail parts are limited to 25 units in length, I don’t want to make them any bigger than this as I think it would be rather unmanageable to build with.  However, it seems reasonable to be able to create effectively longer slider rails by placing them end-to-end, so I made some modifications to allow parts to appear to slide from one rail to another.  To do this, I implemented code in the slider rail part behaviour to find its adjacent neighbours, and then calculate a new total sliding distance and offset for any linear bearing attachments associated with it.

Here’s an example of this in action:-

image

Other stuff

I’ve also been working on some other improvements.  For example, constructions are now spawned frozen and positioned on the ground in front of the player.  Previously one of the parts in the construction would have been selected by the player after spawning, resulting in the construction potentially being oriented weirdly, poking through the ground, player, etc.  This made spawning constructions awkward and confusing, and I think the new way is a lot better.

Player character free flight movement has been modified to have different acceleration and a higher top speed when holding shift.  This helps to quickly navigate larger distances around the map.

All of this, plus various bug fixes will be in the next demo update, which I’m hoping to release very soon!

GearBlocks on Steam

GearBlocks Demo 0.6.7518

Hey everyone, I’ve just released a demo update with all the UI and workshop improvements that I discussed in the previous blog post, along with several bug fixes, enjoy!

Release notes:-

Improved UI textures, colours, and elements to make the UI more legible and easier to use. Improved the general appearance and layout of all the UI menus and screens. Selection lists of saved games / constructions are no longer refreshed every time UI screens are opened, only when something has changed. Improved Workshop browser screen, including search functionality, various sorting & filtering options, and voting. In saved game / construction UI screens, shown saves can now be filtered by their tags. Added UI support for publishing saved games to the Workshop, and for loading downloaded games. Saved game / construction tags are now forced to be all lowercase, in order to match Steam Workshop. Double clicking on a saved game / construction will now load / spawn it. User now asked to confirm before overwriting an existing saved game / construction. Esc. key now backs out of in-game GUIs. Added a “Steam Workshop agreement” popup UI that is shown after publishing an item when the player needs to agree to it. Increased LOD transition / draw distances for parts. Bug fixes. Upgraded to Unity 2019.4.5.

UI and Workshop improvements

Hey everyone, it’s been a while, so here’s a brief update on what I’ve been working on over the past month or so!

Save / load UI improvements

I’ve made quite a few improvements to the UI screens used for saving / loading games or constructions.

image

Now, rather than repopulating the list of saves whenever the screen is opened, they are only updated if something has actually changed (e.g. file saved or deleted).  This makes it more responsive and means the scroll position doesn't keep getting reset.

I’ve also implemented some features to help manage and organise a larger number of saves more easily.  Each save screen now has a list of tags (populated from those currently in all the saves), which can be selected from to filter out which saves are shown.  In addition, locally saved, Workshop downloaded, and built-in example saves are now separated into their own panels that can be switched between.

The player now has to confirm before saving over an already existing saved game or construction (just like when deleting a save).

Double clicking on a saved game or construction now loads / spawns it, without having to click on a button.  Similarly, double clicking on a map in the “creative mode” screen will start a new game with that map.

UI appearance

I also spent a lot of time tweaking the layout of the UI screens and improving the various UI elements.  My aim was to improve the overall UI appearance, make better use of space, and (most importantly) improve legibility.

The UI could still be way better of course, and there are many more things I would like to do, but I think it has been a good step in the right direction.

Workshop integration

Finally, the other area I’ve been working on is extending and improving the Steam Workshop support in the game.

image

In the Workshop browser screen, there are now a whole host of searching, sorting, and filtering options.  The player can search with a text string (matches against the text in item names and descriptions), or they can search using tags (matching against any or all specified).  Results can be sorted by popularity, recently added, etc. and filtered by items subscribed to, published, etc.  Speaking of popularity, I also added buttons for voting items up and down.

This was all implemented using Steamworks functionality, so it was pretty easy to do really, the main challenge was more on the UI side of things.

Lastly, I’ve also added support to the load game screen for publishing saved games, and for loading games downloaded from the Workshop!

Hardware fail

On Monday my PC completely died (reboots every few seconds), narrowed it down to either the CPU or motherboard.  It’s a fairly old machine, so at this point it probably makes most sense to build a new PC.

Anyway, I’m currently resorting to using my old laptop, which is a major setback to progress as it makes development painfully slow.  I was hoping to release a demo update soon with all the UI and Workshop improvements, but this will probably be delayed for a while now unfortunately.

Discord build contest for the Steam Game Festival week

Discord build contest for the Steam Game Festival week: June 16th - 22nd

Theme: Build a walking vehicle.

The creations for this one were amazing, well done to everyone who entered!

GearBlocks on Steam

The Steam store page is now live, with the latest demo available to download with Workshop integration and more.  Check it out, and don't forget to add the game to your wishlist!

NOTE: To load your old saved games / constructions in the new Steam demo, first make sure you load them in the previous demo version (0.5.7362) and save them back out to convert them to the new save format.

Steam Game Festival

Phew, it’s been a busy time lately!  I decided it would be a good opportunity to take part in the upcoming Steam Game Festival from June 9th to 14th, so for the past few weeks I’ve been working towards getting ready for that, and there’s still a lot more to do.

I’m excited that soon the GearBlocks store page will be live on Steam, and a new updated demo build will be playable there during the festival!

Saved game changes

The first thing to mention is that I’ve removed support for the legacy save format, which means that saved games / constructions from demo builds prior to the most recent version (0.5.7362) will no longer load.  You can still convert older saves into the new format by loading them into demo version 0.5.7362 and saving them back out.

I have also changed the saved game / construction folder structure slightly, so that all files for each save are now held in their own sub-folder (existing saves are converted over to this new folder structure).  Also, each save now has an additional meta data file (for name, description, and tags).

I’ve modified all the save / load UI screens to allow the name, description, etc. to be entered / viewed when saving or loading, for example:-

image

All this was necessary for the next step…

Steamworks integration

Given that the GearBlocks demo will soon be up on Steam, I really wanted to take advantage of the platform from the get go, and utilise Steam Workshop in some way.

The first step was to get Steamworks integrated and initialised.  I’m using the excellent Facepunch Steamworks .NET implementation (https://github.com/Facepunch/Facepunch.Steamworks), which seems to support everything I need, and I found it to be really easy to use!

Next I implemented code for publishing saved constructions to the Workshop, and spawning subscribed (and downloaded) constructions, also modifying the construction spawner UI to support these operations:-

image

Finally, I built a basic browser screen to query and view all items currently uploaded to Steam Workshop, and to allow you to subscribe / unsubscribe to them:-

image

There’s a lot more work left to do for this screen, e.g. query sorting and filtering options, up / down voting of items, etc. but this has the bare bones functionality for now.

Also I plan on adding Workshop support for saved games, which should be relatively quick to do now, saved games already have meta data so they’re basically good to go.

Steam store page

Before the festival starts, I also need to get my store page ready for prime time, as this will link to the demo and give people an opportunity to wish-list the game.  I still have plenty more work to do on this, but I’ve done most of the graphical assets now.  I’m not going to reveal any of these just yet, but you may have already noticed the new and improved logo!

image

More gear improvements

Over the past few weeks I’ve been working on the gears and a few other random bits and pieces.

Gear masses

I’ve now finished tuning the gear masses to have more reasonable values.  They’re no longer crazily heavy but still work well in the situations I tested.  Due to the lower mass values the gear’s “teeth” physics constraints can no longer handle as much torque loading as before.  However I found this not to be such a problem because for example, vehicles are generally now much lighter (requiring less motor torque to accelerate them) so things tend to balance out OK.

Gear model improvements

I’ve also made some improvements to the gear models themselves and added additional axle attachment points to them, something I’ve been meaning to do for ages.  These modifications serve two purposes, firstly it makes it easier to actually see the gears rotating, and secondly it allows for greater flexibility with what you can do with the gears.

image

Here’s an example, the red hand of this stopwatch (indicating seconds) is rigidly attached to an axle “passing through” the central gear via a rotary bearing, while the white hand (showing minutes) is attached to another short axle rigidly attached to one of the gear’s new attachment points.

image

Other possibilities with these extra attachments include using the gear as a crank, attaching a structure such as a rotating platform to the gear, or even attaching other gears to the gear!

Other random non-gear related stuff

In order to try and improve performance for constructions with a large number of lights, I’ve made a first stab at a simple distance based culling for lights.  I also plan on adding a settings option to disable shadows cast from them (separate from sun shadows), as this helps performance dramatically when you have a lot of lights.

Another quick change was to make the seat fabrics be paintable to add a bit more variety to the seats!

image

Discord Build Contest

Discord Build Contest: March 21st - April 5th

Theme: Build an amusement park ride.

Thank you to all those that took part, and congrats to the winners.  I had a lot of fun messing around with these builds.  Been meaning to make this video for a while, but better late than never I guess!

Revisiting gear physics

Hey everyone, I hope you and your families are hanging in there during this crazy situation we’re all in at the moment.  It seems like the whole world has been turned upside down over the past month or so.  It’s hard to predict what the future will bring, or what the long term impacts will be, but I’ve been trying to stay focused as best I can by working on the game!

At some point soon I need to starting putting together trailer videos and other materials for GearBlocks, and for this I want to build some example creations to show off all the parts in the game.  So a while back I started building a 4WD off-road buggy with differentials, CV joints, suspension and so on, but that’s when I ran into a problem.

Heavy gears and weird physics

It’s an issue that someone pointed out to me quite a long time ago actually.  It’s this: when you have a 4WD vehicle with a long axle connecting the front and rear differentials via gears, at high speed the vehicle wants to rotate in one direction (i.e. steer left or right) much more easily than the other.  Its preferred direction depends on the direction of rotation of the long axle.  This is a very odd and unnatural behaviour, almost like a kind of gyroscopic effect, and is even more noticeable in the air (during a jump for example).  The problem can be reduced slightly by increasing the simulation update rate (and therefore physics accuracy) but this isn’t really practical as it slows performance too much.

It turns out that this weird behaviour is so noticeable because the gears all have really big masses (20kg each).  When you have a gear on each end of a long axle (e.g. running front to rear of a 4WD vehicle), it has a large polar moment of inertia.  I’m not entirely sure why, but this fact, combined with the high RPM of the axle is what seems to be making the problem so bad.  I found that if I give the gears smaller, more appropriate mass values, the unwanted behaviour is significantly reduced.

Why do the gears have such high masses in the first place?  Well, it’s a workaround to prevent the gear teeth from slipping from one physics constraint to the next.  In the physics simulation, if you have two rigidbodies constrained together, generally speaking the more equal their masses, the better that constraint will solve (with less “stretchiness”).  Giving the gears a large mass was a hack to try and balance them with the combined mass of all the parts in the rest of a typical construction.

I’ve always hated this hack, apart from anything else it makes constructions with a lot of gears weigh a huge amount!  So I’ve been working on a way to make the gear constraints more resilient, allowing the gears to have more reasonable masses, while still preventing gears slipping.

Searching for an anchor

Previously, when two gears were engaged, for each gear the closest constraint anchor position to the other gear would be found.  The problem is, on any particular gear each possible anchor position is quite close to its neighbours, making it easy to slip from one to the next if the constraint doesn’t solve very well (i.e. if it “stretches”).  However, I realised there’s a better approach, here’s how it works.

Starting with the simplest case - two gears with an equal number of teeth.  As before, for the first gear in an engaged pair, the closest anchor position to the second gear is found.  Then, taking the index of the first anchor and negating it will give the anchor index for the second gear, as it can be assumed to match only one possible anchor on that second gear, as shown below.

image

By directly mapping the first gear’s anchor index onto the second gear makes it almost impossible for the gears to slip.  The physics constraint would have to stretch so much that the gears rotate one whole revolution opposite to one another, very unlikely to happen!

To make this work with a pair of gears with an unequal number of teeth is a little trickier.  The largest common factor of the two gear’s numbers of teeth has to be considered when mapping the first gear’s anchor index onto the second.  This means that there is no longer only one possible anchor on the second gear, for example here’s a situation with three possibilities (a, b, or c).

image

It means that, of these three possible anchor positions, the closest to the first gear must be found.  However, they’re still far enough apart that slipping from one to the next is highly unlikely.

Finally, I had to account for the relative orientation of two gears when they first become engaged.  So an anchor index offset is calculated at the point of engagement, that is subsequently applied when mapping an anchor index from one gear to another.

Other gears, and pulleys

Once I had this all working for gear wheels, I then applied the same principle to rack and worm gears.  Previously, if for example you crashed a vehicle with rack and pinion steering, it was very common for the rack gear to slip, causing the steering to be offset.  You’d have to freeze and unfreeze the construction to fix it.  Now this annoyance is much less likely to happen!

I also re-implemented the constraint anchor search code for pulleys to work in a similar way to the gears, bringing the same benefits to the pulleys.

Tuning the masses

I’m now in the process of tuning the gear masses.  For stability under high torque loads, I’m finding I still need to give them masses higher than they would naturally have (albeit not as high as before), particularly for the smaller gears.  It takes a lot of testing, but hopefully soon I’ll be able to settle on some reasonable masses for the gears that work well in most situations.

All told, this has been a lot of work (that I wasn’t planning to have to do), but I think the results are well worth it!

An update all about the latest demo, showing the physics performance improvements, a tutorial on the new debug console, and more

An update all about the latest demo, showing the physics performance improvements, a tutorial on the new debug console, and more.

GearBlocks Demo 0.5.7362

Sorry everyone, the latest build (0.5.7361) had a bug where slider rails would not attach to anything, so I'm releasing another build with a fix for this.

The problem was due to an issue in the Unity editor with multi-select editing (i.e. selecting multiple gameobjects and editing common serialized properties).  This can mess up serialized enum properties, I've been bitten by this before, and that's what happened here.  The slider rail part was inadvertently set to have the same alignment and attachment flags as the axle part.  An easy fix to set it back to the correct enum flags, but such a stupid and annoying problem.

I also found another bug that was a silly error on my part that messed up switching between first / third person mode, so I've fixed that too.

GearBlocks Demo 0.5.7361

Here's the latest demo update with the new saved game format, all the physics and rendering performance optimisations, player physics improvements, debug console, etc.

Player physics improvements, rendering optimisations

In this update I’ll briefly go over what I worked on last week.  This week so far has been focused on bug fixes and preparing for another demo release which should be coming very soon!

Take a seat

Previously, when a player activated a seat, they would be “locked” into the seat by their transform being re-parented to the seat part’s transform, and their Collider / Rigidbody disabled.

This meant that the player would suddenly seem to have no mass, having no weight exerted on the seat.

So instead, I now keep the player’s physics active, and lock them into the seat using a ConfigurableJoint between the player’s Rigidbody and the seat part’s parent Rigidbody.

This means that the player’s mass now dynamically affects the construction they’re seated in.  Also, by setting up the ConfigurableJoint appropriately it allows for some sprung-damped “give” between the seat and player, as you can see below.

image

It does of course mean however that constructions now have a little more overall mass and a slightly different CoG when players are riding in them, much as in real life.

Highlighting render optimisation

When a part (or a whole construction) is frozen, selected, etc. it is highlighted with a glowing outline.  To achieve this the part’s meshes are drawn in a “mask” render pass that accumulates the outlines of all the highlighted objects.  However, up ‘til now, even parts / constructions that weren’t currently being highlighted would still be drawn in this pass (having no visual effect and not necessary).

So now I’ve modified things so that it no longer draws parts in the highlighting mask render pass unless they are actually currently being highlighted.

I also tweaked the mask render shader to fade the highlighting out over distance, and set the camera far clip plane to cull objects beyond the “fully faded out” distance.

These changes save on draw calls, and give a slight rendering performance improvement when viewing constructions with a large number of parts.

Debug console

Over the weekend I implemented a debug console in the game, something I’ve been wanting to do for ages.  It shows logging output, and it can be used to inspect / modify variables, and trigger events in the game.

This was pretty simple to do, because the “global” variables and events were already implemented as ScriptableObject assets (see ScriptableObjects For Fun and Profit for details).  It was just a matter of making them automatically add themselves to a list to then be accessible in the console.  Almost as if I’d planned it that way from the beginning!

These existing variables and events are used by the various systems in the game, and don’t all necessarily make sense to mess with in the console, but many can be useful for testing purposes, or simply for playing around under the hood.  I did add a couple of extra variables just for fun though, one to modify gravity, and another to change the time scale (slow-mo / fast forward).

The console itself has a simple UI, just scrolling text with a box to input commands at the bottom.

image

There are a few different available commands, for example to do things like listing the available variables or events, or to get help on using the console.Typing a variable’s name will shows its current value, or typing its name followed by a value will modify it.  Typing an event’s name (followed by arguments if required) will raise that event, which can cause things to happen in the game (depending on the game’s current state).

Unity upgrade brings performance gains

Now that I’ve removed the old RakNet networking stuff, I’ve been unblocked from upgrading to later versions of Unity, and so that’s what I’ve been working on over the past couple of weeks.

Unity 2018.4

First I upgraded from 2017.4 to Unity 2018.4, this brought some significant improvements:-

PhysX upgraded to 3.4, I found this to be a big performance improvement, especially for constructions with a large number of rigidbodies / constraints.Non allocating collision contacts.  By enabling “Reuse Collision Callbacks”, and using the new Collision.GetContacts() API in OnCollisionEnter / OnCollisionStay, this eliminates GC allocs and improves physics performance too.Graphics jobs no longer marked as "experimental", so I enabled this, it should take some load off the main render thread.Terrain instanced rendering, fewer draw calls for rendering the terrain mesh..NET 4.x no longer experimental, so I switched over to this from version 3.5.IL2CPP scripting back-end for standalone builds, compiles to native binary, should improve performance and is more secure than shipping IL assemblies.

Unity 2019.3

Then moving on to 2019.3, which included a PhysX upgrade to version 4.1, this didn’t seem to provide any additional performance gains out of the box, but it does introduce some intriguing possibilities:-

New temporal Gauss Seidel solver (see below).Automatic box broad-phase pruning, I tried this and didn’t notice any performance improvement, but I need to do some more tests to be sure.

Temporal solver

This new solver is supposed to improve stability for jointed rigidbodies with large mass ratios.  I was hoping that it would eliminate or at least reduce the need for “fake” masses.  For example, the gears right now all have the same (quite large) mass regardless of their size, to prevent them slipping, and it would be nice to give them real masses instead.

Unfortunately in my experiments this didn’t work out, in fact even leaving the gears with their fake masses, they wouldn’t run smoothly at all.  It was almost as if the constraints between them were now too stiff, so instead of locking them together I tried using a limit with a small distance, to introduce some “backlash” to relax things slightly.  This definitely helped but was still not completely smooth.

Sadly though, there were many other problems too, such as CV joints glitching out like crazy under even small torque loads, and wheels sinking through the ground.  Not to mention spring dampers being way too strong (I guess everything would need re-tuning).

So I decided to leave this for now and stick with the old projected solver.  There is a potential massive performance gain to be had with the temporal solver however, due to its faster convergence.  I found that to achieve the same approximate constraint “stiffness”, it seems to only need the number of solver steps to be scaled linearly with the sim fixed time step, rather than with the square of the time step like the old projected solver.

I think this new solver will be worth revisiting again if I have time at some point in the future.

Performance results

One of you talented folks sent me this awesome snow groomer creation!  It’s quite physics heavy due to the tank tracks (a large number of rigidbodies, constraints, and collision contacts), so I’ve been using it as a test case to do some before and after performance comparisons.

image

I also compared with “Continuous Contact Detection” under the gameplay settings both on and off.  Turning this off disables OnCollisionStay, which makes a big performance difference when there are a large number of collision contacts (the only downside being you get no sliding sound effects).

Here are some results (running on my dev machine at 1920x1080 full-screen) with the snow groomer:-

2017.4 / PhysX 3.3, OnCollisionStay enabled: <10 fps.2017.4 / PhysX 3.3, OnCollisionStay disabled: <10 to 23 fps.2019.3 / PhysX 4.1, OnCollisionStay enabled: 14 to 21 fps.2019.3 / PhysX 4.1, OnCollisionStay disabled: 30 to 40 fps.

Note that there’s a range on these numbers because performance varies depending on how things are moving, how many collisions are happening, etc.

Saved game success with Json

A few months ago I re-implemented the saved game serialization using Json.NET, the idea being to replace the existing BinaryReader / BinaryWriter based approach.  I’ve already discussed the motivations for this before, so I won’t go into it again, if you’re interested you can read about it here.

Unfortunately, during testing I found serious performance problems and excessive GC allocations during (de)serialization.  Using JsonSerializer (along with the JsonObject and JsonProperty attributes, JsonConverters, and so on) keeps the code nice and simple, but the performance and memory overhead with large data sets is exorbitant, at least that’s what I found.  I was worried the work I’d done would go to waste and I’d have to find some other alternative to the current save / load system.

Well, I have now reworked things again to (de)serialize everything manually with JsonReader / JsonWriter, avoiding JsonSerializer altogether.  Happily this seems to have eliminated the performance and memory issues, it comes at a cost of having more code to maintain and it’s not as “clean”, but I think this is a small price to pay.

So baring any unforeseen issues, I think using JsonReader and JsonWriter this way will do the job.  The version tolerance Json gives should allow me to move forward with new features without worrying so much about breaking old saves!

Photon PUN and building UI feedback

Happy new year everyone!  Time for a quick dev update for last week (meant to post this earlier, but ah well).

Networking abstraction and Photon PUN

About a year ago I implemented a networking abstraction layer to separate use of the deprecated Unity RakNet based API from the rest of the code.

Last week I made some improvements to its interface to finish it off, and then I added a new implementation under the hood using Photon PUN 2.  I went with PUN because it’s easy to get up and running, it’s well supported, and its API is very similar to the old Unity API.  Thankfully the PUN implementation was relatively easy to do, partly due to the API similarity, and partly because of the abstraction layer which meant I didn’t have to touch the rest of the code.

I’ve no idea yet if I’ll stick with PUN in the long run, but for now it at least means I can get rid of all references to the deprecated Unity networking API, while not breaking my prototype multiplayer implementation.  So now I’m finally free to move on past Unity 2017.4 and upgrade to a newer version, which I’ll hopefully be doing soon!

Builder tool UI feedback

After the recent video I put out about the builder tool UI changes I was considering, I’ve had loads of amazing and really useful feedback, so thank you for that!  I think the consensus is to leave things as they are and focus on the rest of the game, so that’s what I’ll be doing, at least for now.  I’ll keep the prototype code around somewhere in case I need to come back to it in the future.

Saved game serialization

As for this week, I’m back to looking at Json.NET saved game serialization, a topic I covered a few months ago.  I’m trying to improve on the performance and GC alloc issues I had discussed in that blog post.  If this doesn’t work out then Json isn’t going to be viable for this purpose, and I’ll have to think of another way to solve the inflexibility of the current binary stream based system.

GearBlocks building UI - need your feedback

GearBlocks building UI - need your feedback!

One of the main core elements of GearBlocks is the building game mechanic, and it’s an area I’m still not really happy with.  I think the builder tool user interface is too clunky and awkward to use, and it presents too steep a learning curve to new players.  However I’ve struggled to think of how to simplify the UI without losing the flexibility of the current system.

So I decided to go back to basics and just look at the way that parts are positioned and orientated to be aligned together.  For now I’m ignoring part resizing, which I think it might be best to separate out into another tool anyway.

In this video I show what I think are some of the problems with the current system, and demo a quick and dirty prototype of a possible alternative.

I’d love to know what you guys think.

How hard was it for you to learn how to build stuff in the game when you first started?Do think the current builder tool is basically OK as it is, should I just leave things as they are and get on with finishing the rest of the game?Or do you find the current building user interface difficult to use?Do you think the approach that I’ve shown here in this prototype is worth pursuing?

Let me know in the video comments, or on the GearBlocks discord.  Thank you, and happy holidays!

A quick run through what’s new in the latest demo, a better player character model, improved animations, and player physics interaction

A quick run through what’s new in the latest demo, a better player character model, improved animations, and player physics interaction.

Join the GearBlocks Discord Server!

Hey everyone, I've finally gotten around to creating a Discord server for GearBlocks!

You can upload your save files there, so I think it will be a great place to share your creations, at least until I implement a proper way to do this from within the game itself.

It's also a good place to discuss the game, share tips & tricks, give feedback, report bugs, and so on.

I'm still learning my way around the whole Discord thing, so let me know if you have any suggestions for the GearBlocks Discord.  Welcome aboard!

GearBlocks Demo 0.5.7273

A bit later than I was hoping, but here’s a new demo build!  This one includes a whole bunch of player character improvements and several bug fixes too.

Player physics

Over the past few weeks I fixed a bunch of bugs, and then turned my attention to player physics and movement control.

Problems with using CharacterController

Since the very earliest days of the game’s development I’ve been using a CharacterController for the player along with a “character motor” script (adapted from a Unity sample) to control it using the CharacterController’s Move() function.  The character motor would apply forward / back, strafing, and jumping movement, acceleration due to gravity, and if the player was standing on a moving object it would make them move with it.

This setup worked reasonably well, but the CharacterController doesn’t provide proper interactions with Rigidbodies in the world.  The player is treated as a static immovable object when things collide with them.  The player can’t push objects around, and they can’t be pushed by objects either.  It just looks wrong when for example a vehicle hits the player at high speed and they don’t move at all.

Also, the character motor implementation had a bug where, if the player collided with a Rigidbody, they would occasionally get thrown across to the other side of the map.  Most often this happened when exiting a seat, very annoying!  I suspect this issue was related to the code that moved the player when standing on something, but I’m not 100% sure.

Despite all these problems, I didn’t particularly want to add more work to my plate by throwing out this character motor code and starting again from scratch.  So I tried playing around in the OnControllerColliderHit() message to try and get the player to push stuff around, and in OnCollisionStay() I tried to make the player be pushed by objects that collide with them.  I couldn’t get this to work nicely though, I think it really is necessary for the player to have a Rigidbody to give proper physical interactions, anything else is always going to be a bit of a hack at best.

At this point I realised I needed to ditch the CharacterController and start from scratch after all, using a Rigidbody instead.

A physics based player

So now instead of a CharacterController, the player has a CapsuleCollider and a Rigidbody.  I implemented new code that replicates the original forward / back, strafing, and jumping behaviour, by applying a force to the player’s Rigidbody.  It uses a Physics.SphereCast() to detect contact with the ground and to find the Rigidbody that the player is standing on, if any.  If they are standing on a Rigidbody, its velocity is transferred to the player.  Also, the force used to move the player is applied in the opposite direction to the Rigidbody that they’re standing on, thus obeying Newton’s third law.

To sum up the features and benefits of this new approach:-

Correct player collisions with other Rigidbodies.Player can push other Rigidbodies around.Player can be pushed by other Rigidbodies.Player can stand on a moving Rigidbody.Obeys Newton’s third law when player accelerates while standing on a Rigidbody, this results in really cool “conservation of momentum” behaviour.Player falls due to gravity automatically from having a Rigidbody, but even better, the player’s weight now pushes down on the Rigidbody that they’re standing on.Eliminates the old “player thrown across to the other side of the map” bug.Code is simpler and cleaner than the old character motor implementation.

Here are some examples of all this in action:-

imageimageimageimageimageimageimageimage

As you can see this provides a level of interaction between the player and the constructions they build that simply wasn’t possible before, so I’m happy I bit the bullet and re-implemented things this way!

However it’s by no means perfect, and there are a few issues / missing features that will need addressing at some point, for example:-

I’d like to implement code to handle climbing steps, I think the player needs an extra force to push them up steps, as they tend to get stuck at the moment.I also want to add something to make the player slide off ledges, as right now the player can stand more than half way off a ledge with their feet in the air, which looks weird.The old character motor had code to make the player slide down steep slopes, not especially crucial but it would be good to get this working in the new implementation.

Character customisation

Over the past few weeks I’ve been finishing up the player character work I started a while back, along with some code refactoring and other things.

Building a player character

I’ve now implemented functionality so that a construction built out of body parts can be treated as a player character model.  Such a “character construction” differs from a normal construction as follows:-

It doesn’t get serialized out to saved games, because the player’s character construction gets spawned separately (based on what was selected in the character screen, see below).It doesn’t collide with other non-character constructions or objects in the world (the player’s CharacterController takes care of collisions).It can’t be selected, frozen, or destroyed.Body parts in it don’t move via physics, instead they are locked to the appropriate animated bone (e.g. head, upper arm, lower leg, etc.)

I added a new character screen accessible from the main menu.  This allows the user to select a character construction, which will then be spawned as the player character when entering a game.

image

To create a custom character, first the user assembles a construction as normal out of body parts, and then they save it via the save construction screen.  As shown below, I added a tab to this screen to allow a construction to be saved as a character so that it’ll then appear in the character screen and be available for selection.

image

To switch to the new character, the user then has to exit back to the main menu, go into the character screen and select the one they just saved, before re-entering a game.

In game, the character construction can be seen in the world tool UI just like any other construction.  However there are some operations that can’t be performed on it as mentioned before: select, freeze, or destroy.  This can be seen below, note that the character construction has an icon to identify it as such.

image

This pretty much completes the player character system although, as always, there are a few loose ends to tie up:-

I need to add checks to ensure that the construction is valid to be a character (e.g. has the correct body parts, and they are connected together appropriately).Currently, to change the player character construction the user has to exit back to the main menu, I’d like to implement a way to swap it during game play.The body part meshes need a bit more modelling work.I’d like to add more attachment points to the body parts to allow for more customisation options.I also want to add more body part variants and accessories.

Free flight mode

I’ve also finished working on a “free flight” mode for the player.  This turns off gravity for the player and changes the controls slightly so that the user can fly up and hover in the air, handy for when building large constructions!

Singleton squashing

Finally, I also did another code refactoring pass to eliminate the remaining singleton MonoBehaviours in the game (well nearly).  This primarily involved converting them to ScriptableObject assets, and replacing any public method calls with events and handlers.  I covered this topic in the ScriptableObjects For Fun and Profit blog post a while back, so I won’t go into detail here.  Suffice to say I’m done with this refactoring process now, there are only a couple of singleton MonoBehaviours left, which are for my networking abstraction layer (something I also blogged about a while ago), and I think I’m just gonna leave these as they are.

Saved game serialization

Well, seems like another two months has gone by in a flash!  I was away visiting family for some of this time, and the work I’ve been doing on the game has resulted in a frustrating lack of progress to show for it, but here’s an update on what I’ve been up to anyway.

Saved game serialization

Up until now, saved games and constructions have been serialized via a binary stream, with no formatting, just using BinaryReader and BinaryWriter directly.  This is fast and results in a compact file size, but has one huge disadvantage, a lack of version tolerance.  In other words, if I add or remove any variables to be saved, or reorder them, then old saved game files will no longer load correctly.  To work around this I wrote code to check a version number in the saved file, and then convert things over for each added or removed variable.  This is a hack really, and has resulted in rather messy and hard to maintain code.

This situation is bad enough with just the demo version of the game out there, with a cut down feature set.  Maintaining saved game backwards compatibility will only get harder once the full version is released.

Ideally, I need a properly structured save file format, with some kind of key value pairing that would allow for version tolerance, but wouldn’t bloat the file size too much.

BinaryFormatter

First I investigated using BinaryFormatter, because it allows for version tolerance via optional fields, but I couldn’t get it to work when deserializing MonoBehaviour classes.  I need to be able to instantiate the MonoBehaviour and then populate serialized values into it, not have the deserialization process itself try and allocate a new MonoBehaviour (which is not allowed by Unity).  I thought maybe using a serialization surrogate might allow for this, but couldn’t figure out a way to make it work.  The other downside of BinaryFormatter is all the assembly and type data it saves out adds quite a bit to the file size.

Json serialization

So after looking around for other possible solutions, I decided to try Json.  This provides the key value pairs I need in a fairly compact structured format.  I used Json.NET from Newtonsoft (provided via a Unity asset store package for ease of integration) which seemed really promising, it’s very easy to use and highly configurable.  In most cases there’s very little additional code to write, you can just use the JsonProperty attribute to specify which class properties to serialize, and configure how they’re serialized.  Also, it allows for populating properties of a MonoBehaviour that has already been allocated, by using JsonSerializer.Populate() inside a JsonConverter.

Still, it took me several weeks to get Json serialization working for both saved constructions and full saved games, there were a few stumbling blocks along the way which took time to work around, as did just learning how to best use the Json.NET API.  The end result seemed great though, it solved the version tolerance problem, and the code was so much simpler and cleaner.

One issue was that the resulting file sizes of the text based Json format were huge.  Given that the game uses the same serialization code path to send construction data between networked players, this was a problem.  So, I switched over to using Bson (the binary equivalent to Json), and also compressed the data via a DeflateStream.  This worked well, the resulting file sizes actually ending up smaller than my original binary stream format.

Performance and memory problems

At this point I thought I was good to go, but then I started profiling the Json serialization with large saved game files (more than a thousand parts), and realized I was in trouble.  Firstly, deserializing the saved game was more than twice as slow using Json vs. the old binary stream method.  This wasn’t a complete disaster as the load times weren’t terribly long in the first place.  The other more serious issue was that the Json deserialization did an enormous number of tiny GC allocations (as in millions of allocs, totalling hundreds of MB!).

I found that reducing the JsonProperty name lengths helped slightly with this but not to any significant degree.  I spent quite a lot of time restructuring the code that loads the various modules in the game (player, constructions, time of day, etc.) to try and deserialize from the file stream more efficiently, but this made very little difference to performance or memory usage unfortunately (the resulting code was cleaner than before though so I guess the refactoring was worth doing anyway).

I’m annoyed with myself that I didn’t do enough tests to pick up on these problems before putting all the effort in to convert the game over to use Json.  If I’d known ahead of time, I probably wouldn’t have bothered.

So now I’m not sure what to do.  If I stick with the old binary stream solution, then all the Json serialization effort will have been wasted and I’m still stuck with difficult to maintain code for backwards compatibility.  But the Json serialization option as it stands isn’t acceptable, I’d need to do something to resolve the memory and performance issues.  One possibility would be to manually serialize everything (i.e. use JsonReader / JsonWriter directly rather than JsonSerializer), supposedly this is the fastest way as it avoids overhead from reflection and so on.

I’ve decided for now to put all this to one side, think about it some more, and come back to it later.  In the meantime I really need to get back to trying to make some positive progress with the rest of the game!

Player animations

The janky placeholder player animations that have been in the game for ages were long overdue for replacement with something better.  Over the past couple of months I've been working on sourcing better animations, setting up the animation blending and transitions, and then driving that based on game state.

I worked out that I needed animations for:-

Standing idle.Standing jump.Turn left / right in place.Locomotion (forward, backward, strafe left, strafe right) at various speeds from walking to sprinting.Walking and running forward jumps (for jumping while moving backwards or strafing I just use the standing jump animation, as I couldn’t find anything more suitable).Seated.Tool holding (right arm held out) in up, forward, and down directions, blended based on the camera view direction.

I don’t have the budget to pay for an animator, so it was quite challenging to find suitable animation content to meet these requirements.  In the end I was able to get by with a combination of a paid animation pack from the Unity asset store, some free animations from https://www.mixamo.com/, and creating some animations from scratch.

It was a fiddly process to set up the animation state machine in Unity to get all these motions blending and transitioning nicely, but I’m happy with the final outcome:-

imageimageimage

First person mode

I've now enabled the animated player character in first person mode, the downside being that this can cause problems with bits of the body poking through the camera near clip plane, not the easiest thing to avoid especially if the camera is set to have a wide field of view.

To solve this I had to do a few tricks to offset the character and camera based on the view direction.  It also imposed restrictions on the range of motion of the upper torso and arms and therefore what animations I could use.  The end result is well worth it though:-

imageimage

In first person mode the camera is now attached to the character’s animated head position, this adds a lot of life to the camera movement (e.g. “dipping” after landing from a jump), and makes a big difference to the feel of the game:-

image

Tools

Once I had the player character animations working well in both first and third person modes, I moved on to the task of adding some tool models and attaching them to the player’s hand.  Now, as the player selects between the different tools (e.g. builder, painter, etc.), the transition between them is animated, and the models are swapped.  Right now I just have simple placeholder models for the tools, and I plan on adding some transition sound effects, but here’s what it looks like so far:-

imageimage

Body parts

Time for a long overdue update!  I’ve done a lot over the past two months so I’ll have to split this into a couple of blog posts.  In this first one we’ll look at the character models I’ve been working on.

Crash test dummy

A while ago I added knuckle joint connectors which, along with the ball and socket connectors, can be used to construct simple rag-doll characters.  This got me thinking, it would be cool to have some proper body parts with the connectors built in to them, which could be assembled in the game to make more convincing humanoid rag-dolls.  I figured a crash test dummy would best fit with the idea of being made up of rigid body parts with exposed joints.

The first thing I had to decide was what body parts would be needed.  I wanted to allow for flexibility of movement, but not have so many parts that building a character in the game would be unmanageable.  I settled on the following 11 parts:-

Upper and lower torso (initially I had a single torso part, but in the end I had to split it to allow for animation - see “Player character” below).Head.Upper and lower left arm.Upper and lower right arm.Upper and lower left leg.Upper and lower right leg.

The second problem to solve was the joint connector locations and body proportions, this was tricky as I wanted to keep all the connectors on unit boundaries (or failing that, half unit) relative to one another, while keeping the dimensions of all the body parts in proportion.

After these decisions were resolved it was time to fire up Blender and make some parts, here’s what I ended up with:-

image

…and once assembled together:-

image

I added attachment points on the hands so that other parts such as axles can be connected to them:-

image

…and because the body parts are compatible with everything else in the game, you can create all sorts of nightmarish stuff!

image

Player character

One of the longest unresolved design problems in GearBlocks has been the player character model, the skinned models in the game at the moment are just placeholders and were well overdue to be replaced.  The trouble is, I couldn’t decide what the player model should look like, or how to have it fit in aesthetically with the rest of the “GearBlocks world”.

Then I thought, now that a humanoid character can be built in the game from body parts, why not utilise this for the player too?  This will require implementing a way for a character built in game to be selected and used as the player model.

To explore this idea, I decided a crash test dummy wasn’t good enough, I wanted to have a proper human.  Inspired by action figurines, I tried to make the body parts so that their joints, although exposed, are not overly obvious.  I went with a stylised appearance for the face and hair, this was partly due to the limitations of my modelling skills, but I also think this look fits the visual style of the game quite well.  Here’s what I have so far:-

image

Note that this is all still a work in progress, in particular the clothing and feet need some more refinement, as do the skin and hair shading.  At some point I’d also like to add a female variant, and other skin tones.  Plus it would be cool to have accessories (such as crash helmets).  I did make the clothing paintable however, which allows for creating somewhat unique looking characters:-

image

…and of course you can mix and match with the crash test dummy parts!

image

I haven’t yet implemented the system to make a built character “become the player”, this will need to hook up the body parts to the appropriate animated bones (replacing the old skinned mesh altogether).  For now I’ve hacked something together so I can test these character models out with the player animation system to make sure they work properly:-

imageimage

The animations you see here are all new, in fact most of my time over last two months has actually been spent on the player animations, and this will be the topic of the next post…

Text decals, data links, and electronics

I’ve been wiped out with a nasty bug over the last couple of weeks which slowed productivity somewhat, still got quite a few things done though!

Text decals

I implemented a decal shader that can modify material properties in the g-buffer independently of normals.  This allows for rendering over the top of objects already rendered in the scene, modifying albedo, smoothness, etc. while leaving the underlying normals as they are, which gives a “painted over” look.  I wrote this shader specifically to work with rendering font text from the Unity UI.

Then, I added a Canvas in World Space mode and a UI Text component to the resizable plate part, and implemented a new text label part behaviour to configure the text string to be shown.

With a "painterly" font, it’s quite a nice effect, here’s an example of what it looks like:-

image

And here’s the part behaviour UI the player can use to configure the text string:-

image

This will be handy for labelling things on constructions, and I'm thinking I might make use of it in future challenge game mode scenarios / tutorials.

Data links

I refactored the part behaviour linking code using various interfaces to better decouple the code and make it easier to add new link types.  I also made some minor fixes and improvements to the linker tool.

I then implemented a new data link type, which allows part behaviours to expose “data channels” that can be accessed by other linked part behaviours.  Where appropriate, I added data channels to all the part behaviours already in the game, for example the electric motor now exposes its current RPM, torque, and power values.

Electronics

Now the dawn of a whole new category of parts, electronics!  I hope to expand on this a lot more in the future but here's what I've done so far.

image

Putting the text decal shader and the data links together, along with a LCD display font, I implemented some text display screen parts that show the data channels of the part they're linked to.

Here you can see the new data link type being used as we link a display to a motor:-

image

The display screen showing the motor's data channel values while it runs:-

image

These displays have a part behaviour that lets the player assign a data channel to each text line on the display.  Here’s the UI for this, it needs some improvement but is functional for now at least:-

image

I also added some “sensor” parts which are little modules that calculate their own speed, acceleration, or attitude (i.e. orientation in the world) and report these values via data channels.  These can then be linked to from the LCD displays to show their current values.

image

The speed sensor in action, as well as speed it also reports its altitude and rate of climb (RoC):-

image

The accelerometer sensor, reporting longitudinal, lateral, and vertical acceleration separately, as well as overall acceleration:-

image

Finally, the attitude sensor, which reports heading, pitch, and roll in degrees:-

image

I have loads of ideas for more sensor modules I could add in the future, e.g. for reporting angle, angular velocity, proximity (think radar / lidar) and so on.  Let me know if you have any ideas too!  Combining these with the control links I have planned will really open things up to some very cool possibilities I think.

Anyway, for now I've just been enjoying messing playing around with these parts, like adding some sensors and LCD screens to the Mosquito flyer for flight instruments!

imageimage

Linker tool, power, and more

Here’s a quick update on what I’ve been working on over the last month or so!

Linker tool

After a long hiatus from working on it, I finally went back and completed the linker tool.  The first attempt at this tool that I did a while back was hard-coded to work with the pulleys, so I had to generalise the implementation to support different link types.  A part can now have one or more link nodes that are associated with its part behaviour(s).  When the linker tool is active these link nodes can be highlighted by the player, which they can then click on and drag to another link node to create a link between them.

These are the different link types that I’ve done, or am planning to do:-

Pulley - used to route belt between pulleys, implementation now complete.Power - used to link motors, batteries, solar panels, this is also now done (see “Electric Power” below).Data - allows one part behaviour to query data from another linked part behaviour, an example could be a screen that can be linked to a motor to display its current RPM.Control - allows one part behaviour to control another part behaviour, an simple example being a switch that can be linked to several motors, lights, etc. to turn them on / off together.

In this example you can see some pulley links and a power link being added between a motor and battery:-

As there are now different link types, I’ve made a few tweaks to make it easier to manipulate them.  The indicators for each link type are colour coded so that they can easily be distinguished from one another, and there is now a linker tool UI that allows links of different types to be shown or hidden.

Electric power

As I mentioned, I’ve now implemented “power” links so that motors, lights, and so on can be linked to batteries.  I implemented code in the motor and light part behaviours to calculate a power value that is then used to discharge energy from the linked battery / batteries.  Also, when braking, a motor will now regenerate energy back into its linked battery / batteries.

The battery part behaviour itself does very little other than tracking the battery’s current state of charge.

I’ve also added solar panels, these have a simple part behaviour that calculates a power value based on the panel’s surface area and its current angle relative to the sun.  This is then used to charge energy into its linked battery / batteries.

It’s fun to play around with this stuff in conjunction with the day / night cycle in the game, using solar panels to charge a battery during the day which then powers your lights at night:-

Knuckle joints

I’ve also just added a new type of hinge connector, what I’m calling a “knuckle joint”, where the parts connect in line with one another like this:-

I made two versions of the knuckle joint connector, one that can rotate through 180 degrees and another that is limited to 90 degrees.  Here’s an example of using the 90 degree version, as well as the ball and socket connectors I added ages ago, to make a ragdoll in the game:-

GearBlocks Demo 0.5.7019

New demo build is up.  A lot of code "under the hood" has changed since the last one, so I'm really hoping I haven’t broken anything!

Better building for multi-player

Most of my time over the past few weeks has been spent on a major reworking of the code for all of the tools in the game (builder, material, painter, etc.) in order to improve the building experience for networked client players in multi-player games.

Previously the tool code that responded to player inputs in order to perform various actions (such as attaching a part, breaking an attachment, applying paint, and so on) would always run on the server for all players, with each client simply sending their inputs to the server for it to deal with.  This setup made it relatively easy for the server to handle things like arbitration between players, seeing as they were effectively all running locally as far it was concerned.

However this approach was flawed, the most significant problem being the latency between client player input and an action happening, which made building really awkward to say the least.

So I’ve now re-implemented every tool so that player input is processed locally on each client.  In some cases the client must still request the server to complete certain actions, so that the server can validate and arbitrate where needed (for example, while one player is attaching one part to a second one, at the same time another player could be deleting that second part; the server needs to have the final say on the outcome in this scenario).  In many situations however, it is not necessary for the client to check with the server first (e.g. moving or resizing a selected part, painting a part, etc.), instead the client just informs the server of the change made so that it can be broadcast out to the rest of the clients.

The result is that the building experience for networked clients is now basically the same as it is in single player games.  The other benefit of these changes is that because input is processed locally for each player, it simplifies the code and makes it a bit easier to modify and improve the tools.

Builder tool tweaks

On which subject, I’ve made a couple of minor improvements to the builder tool thanks to some suggestions I’ve received.

Remove actions (delete part, destroy construction, etc.) are now delayed, during which time the action key has to be held down.  This should hopefully prevent annoying accidental deletions from mis-clicks!I changed the default key binding for duplication from “Q” to “Left Alt + LMB”, by default “Q” is now dedicated just to opening the tool menu.

The usability of the builder tool controls is still an ongoing concern, and something I’ll have to keep plugging away at over time, but at least now it’ll be easier to implement any further improvements I need to make.

New demo coming soon

Finally, I’m getting close to releasing another demo build, and I’ve been fixing a bunch of bugs in preparation for this.  There have been a ton of changes to the code since the last demo, so I’m slightly paranoid that some as yet undiscovered bugs might have been introduced.  Time to do some more testing I think, hopefully I don’t encounter any last minute issues!

Here’s a quick demo of the new material tool, showing how the tool is used, and how the different materials affect both visuals and physics

Here’s a quick demo of the new material tool, showing how the tool is used, and how the different materials affect both visuals and physics.

ScriptableObjects For Fun and Profit

Well, it’s been a while, so time for a progress update I think!  The material tool is now done, and I’ll show it in action very soon, so watch out for that.  Most of my time however has been occupied with a massive code re-architecture effort, and that’s what I’m going to go over in this update.

From a high level perspective the GearBlocks game code is quite well laid out in terms of separating various subsystems (e.g audio, graphics, player, UI, etc.) via namespaces and so on.  However, there was still a lot of code coupling (i.e. direct dependencies) between areas of the game code that should really be completely independent.  This made it impossible to reuse or test parts of the code independently, and it was only going to get worse as development progressed.

ScriptableObjects to the Rescue

I’d been using ScriptableObjects in Unity for a long time, but only in a select few cases as data containers, I certainly hadn’t been using them to their full potential.

I watched these two excellent presentations a while back:-

Overthrowing the MonoBehaviour Tyranny in a Glorious Scriptable Object Revolution - Richard Fine (Unity) Game Architecture with Scriptable Objects - Ryan Hipple (Schell Games)

Ever since, I’d been wanting to adapt the ideas presented in these talks to the game to improve the code architecture, and so I finally decided to take the plunge.  This was a huge endeavour, but well worth it I think.

ScriptableObject Events

Previously I was using Unity’s ExecuteEvents system as the basis for events in the game.  This was helpful for code decoupling, however it still had some disadvantages:-

In order to add a new event, a new interface has to be written (derived from IEventSystemHandler), and then implemented in all the MonoBehaviours that need to receive the event. It’s necessary to explicitly call ExecuteEvents.Execute() on every GameObject with MonoBehaviours that need to receive the event.  To me, this makes ExecuteEvents more like messages than true events, but perhaps that’s just semantics. Only MonoBehaviours on GameObjects can receive these events, ScriptableObjects can not.

So I replaced these with a new system, where each event is now a ScriptableObject asset.  Here’s a simplified version of the code:-

public class EventAsset : ScriptableObject{    public delegate void EventHandler();    public event EventHandler Handler = null;    public void Raise()    {        if( Handler != null )        {            Handler();        }    }}

The real implementation is slightly more complex, but follows the same principle.  It’s implemented using C# generics to allow for different event argument types, and has support for logging and listing the current event subscribers.  This is used by a custom editor I wrote to display this info while the game is running in the Unity editor, here’s an example of it in action:-

To use an event it can simply be assigned to a variable in the Unity inspector, then to receive it, just subscribe to Handler:-

public class Receiver : MonoBehaviour{ [SerializeField] EventAsset somethingHappened; EventAsset.EventHandler onSomethingHappened; void OnEnable() { onSomethingHappened = () => { Debug.Log( "I hear that something happened!" ); }; somethingHappened.Handler += onSomethingHappened; } void OnDisable() { somethingHappened.Handler -= onSomethingHappened; }}

Or to raise the event, just call Raise() on the event:-

public class Sender : MonoBehaviour{    [SerializeField] EventAsset somethingHappened;    void SomethingHappened()    {        Debug.Log( "Something happened, telling everyone!" );        somethingHappened.Raise();    }}

This setup has some useful advantages over the old ExecuteEvents system:-

No need to write any code to add a new event, just create a new event asset and assigned it in the inspector where needed.No need to explicitly refer to specific GameObjects to send the event.Don’t even need to be using GameObjects, these events can be used by ScriptableObjects as well as MonoBehaviours.The events are more easily debuggable via the custom editor.

ScriptableObject Variables

Events aren’t always the most appropriate pattern for sharing data between subsystems, for example sometimes it’s necessary to store a value somewhere and allow it to be read a later point, perhaps continuously polling it to watch as it changes.

Previously I was doing this by having my subsystems be singletons, and then directly reading / writing properties in them where needed, thereby tightly coupling different areas of the code together, not good!  To solve this I made a new “variable” system, where each variable is a ScriptableObject asset.  Whereas events can be thought of as radio broadcasts, the variable system is conceptually more like a noticeboard (with each variable being a notice pinned to the board).

Here’s a simplified version of the code, it’s implemented as a generic class to allow for different variable types:-

public abstract class VariableAssetBase<T> : ScriptableObject{    [SerializeField] T value;    public T Value { set { this.value = value; } }    public static implicit operator T( VariableAssetBase<T> variableAsset )    {        return variableAsset.value;    }}

For example, a bool variable type:-

public class BoolVariableAsset : VariableAssetBase<bool>{}

Again, the real code has a bit more going on.  It has an event delegate that code can subscribe to, in order to be notified when the variable value is assigned to (this saves having to use a separate event for this).  It also has support for serialisation so that I can use these variables for things like game settings (e.g. controls, gameplay, video) and allow the player to save / load them.  Plus I made a custom editor that allows variable values to be viewed or even modified while the game is running in the Unity editor.  At some point I might implement a debug console that would allow this to be done even in standalone builds, which would be super cool!

To use a variable it can be assigned in the inspector, then written to / read from.  Notice that Assigner and Watcher in this example are completely independent of one another:-

public class Assigner : MonoBehaviour{    [SerializeField] BoolVariableAsset isThingTrueVar;    void ThingBecomesTrue()    {        isThingTrueVar.Value = true;    }}public class Watcher : MonoBehaviour{    [SerializeField] BoolVariableAsset isThingTrueVar;    void Update()    {        PollThingTruthiness();    }    void PollThingTruthiness()    {        Debug.Log( "Thing is currently " + isThingTrueVar );    }}

I replaced data in my subsystems that needed to be shared with these new ScriptableObject variables.  This allowed me to remove a lot of code dependencies, and eliminate the need for singleton references in most cases.

One example being the UI overlay that displays the player’s speed, acceleration, and altitude.  It now just reads variables for these values and displays them, completely independently of the player code that updates them.

ScriptableObject Dictionaries

There’s one slight wrinkle with the ScriptableObject variable system, in that there is only one global instance of each variable.  For example, sometimes I need one instance of a variable per player (in multi-player games).  To solve this I implemented a simple ScriptableObject dictionary, here’s the implementation pretty much in full:-

public abstract class DictionaryAssetBase<TKey, TValue> : ScriptableObject{    Dictionary<TKey, TValue> dictionary = null;    void OnDisable()    {        if( dictionary != null )        {            dictionary.Clear();        }    }    public TValue this[TKey key]    {        get        {            if( dictionary != null )            {                TValue value;                if( dictionary.TryGetValue( key, out value ) )                {                    return value;                }            }            return default(TValue);        }        set        {            if( dictionary == null )            {                dictionary = new Dictionary<TKey, TValue>();            }            dictionary[key] = value;        }    }}

Then for example, a dictionary with byte keys and bool values:-

public class ByteBoolDictionaryAsset : DictionaryAssetBase<byte, bool>{}

The only part I left out here is some code for listing the entries currently in the dictionary, used by another custom editor I added for debugging while the game is running in the Unity editor.

A dictionary is used in much the same way as a ScriptableObject variable:-

public class Assigner : MonoBehaviour{    [SerializeField] byte thisPlayersID;    [SerializeField] ByteBoolDictionaryAsset isThingAboutPlayerTrueVar;    void PlayerThingBecomesTrue()    {        isThingAboutPlayerTrueVar[thisPlayersID] = true;    }}public class Watcher : MonoBehaviour{    [SerializeField] byte thisPlayersID;    [SerializeField] ByteBoolDictionaryAsset isThingAboutPlayerTrueVar;    void Update()    {        PollPlayerThingTruthiness();    }    void PollPlayerThingTruthiness()    {        Debug.Log( "Thing is currently " + isThingAboutPlayerTrueVar[thisPlayersID] + ", about player with ID: " + thisPlayersID );    }}

Replacing Singletons

The game has many self contained code modules providing utilities and functionality used by other parts of the code.  Previously these were either static classes or singleton MonoBehaviours, both having their disadvantages:-

Static classes can’t have variables serialized by Unity or edited in the inspector.Singleton MonoBehaviours need to live on a GameObject somewhere in the scene (or at least in a prefab).

So now I’ve re-implemented most of these as ScriptableObjects which have neither of these downsides.  They work well with the new ScriptableObject events too, these modules being able subscribe to or raise events, which helps with code decoupling.

Other Uses of ScriptableObjects

I found many more places to use ScriptableObjects, far too many to go over in detail now, but here’s a brief summary of a few of them:-

Added ScriptableObject “delegate objects”, making use of the strategy pattern where different variations on a theme implement a common interface.  For example I use this for the procedural generation code for the various different re-sizable parts in the game.Replaced some enums with ScriptableObject assets.Implemented ScriptableObject data assets with built in functionality for better separation of concerns.  For example, I implemented a “sound asset” ScriptableObject that handles random AudioClip selection and playback, and then created a whole bunch of these assets for all the sounds in the game.

New material tool, and a new year!

Hey all, hope everyone has had a good holiday break.  I thought I’d give a quick update on what I’ve been working on over the past few weeks.

Toolbox code refactoring

Up until now, the code for the various tools (builder, linker, painter, etc.) was pretty much all in one (very large) source file.  This was driving me crazy as made it a real pain to to fix bugs, or add new features.  So I finally took some time to do something I’d been wanting to do for ages, which was to refactor this monolithic beast into separate source files for each tool.

There are still things I’d like to improve and clean up (further code decoupling, mainly), but it’s much better than it was, and makes it easier to add new tools, on which subject…

Material swapper tool

After the refactoring, I started work on a new tool that allows you to swap the material on certain parts (such as beams and plates) after they’ve been spawned, and even after they’re already part of a construction.

The first step was to add a material definition that encapsulates all the various part material properties (i.e. the rendering & physics materials, density, strength, and “is it paintable”).  Next I had to refactor the part descriptor code to allow parts to use this new material definition (seems like I’ve been doing a lot of code refactoring lately!)

image

Then on to the material tool itself, which I’m still in the middle of building.  Right now I have a first pass implementation working, with the basic UI done, and the ability to change material on the highlighted part.  There’s still more to do however; for example, save / load (including converting old save files to the new material swappable parts), and probably more refactoring as I’m not quite happy with how the part descriptor code is structured just yet.

Anyway, it shouldn’t take too much longer to finish up, once it’s done I’ll reveal more about how it works.  After that I’ll probably get back to finishing up the linker tool, as that’s been on the back burner for way too long now.

In the meantime, I’d like to say a big thank you for following my progress, particularly to those of you that have been following for a long time, and who continue to play the demo and give me feedback.  I know development of the game is frustratingly slow, but I will get it done eventually, I hope!

Happy New Year, and all the best for 2019.

Damage is doneWell, it took me long enough, but finally the damage system is complete

Damage is done

Well, it took me long enough, but finally the damage system is complete!  Most of the time was actually spent doing optimisation work, which I’ve discussed before in previous posts, the damage system itself didn’t take that long to do.

On the idea scrapheap

My original idea for damage was that each attachment between parts (fixed, rotary, linear, etc.) would have a “health” value.  Then upon a collision contact with a part, some damage amount would be propagated out to all of that part’s attachments.  For each attachment, damage would effectively accumulate over time as its health value gradually reduced, until it reached zero at which point the attachment would be deleted.

However, there were problems with this method:-

Deleting individual attachments due to damage would lead to inter-penetration issues, just like when you manually delete attachments with the builder tool.Each attachment having a health value would need to be conveyed somehow to the player via a UI, and I couldn’t think of a way which wouldn’t be messy and confusing.Because damage is applied for every collision contact (of which there can be many), the code is quite performance sensitive, and so needs to be as lightweight and simple as possible, which this method wasn’t.

Binary break

So in the end I went with a simpler solution that just uses a “strength” threshold.  When a part receives a collision contact, I simply compare the impact force with the part’s strength value, and if the force is greater than this value, I break the part off (i.e. delete all of its attachments), otherwise I leave it attached.  In other words, a part is either entirely broken off or it isn’t, there’s no intermediate damage state or health values to deal with.

Happily, I found was that there was not really any need to explicitly propagate the damage force to neighbouring parts to achieve a convincing effect.  Direct impacts seem to be enough, I think because as parts break off they hit other parts and the damage sort of propagates organically.

I’ve also finished the implementation of explosives that integrates with the same damage system, in this case the damage force is simply derived from a linear fall off from the explosion centre.  The resultant bits that are broken off then have an explosion force applied to them to push them around, seems to work pretty well.

Lastly, I’ve also added a per-construction setting to enable / disable invulnerability (i.e. immunity from part breakage), as sometimes it could be useful to disable damage for those particularly “experimental” constructions that might try and smash themselves to bits.

Still to do

As I mentioned, each part has a strength value which basically determines how hard it is to break off.  A part’s strength value is intended to reflect the material it’s made from (e.g. steel is stronger than wood or plastic), and I still need to fine tune these strength values to get the balance correct and hopefully give a nice trade off between the various materials.

Also, I’m thinking I might bias each part’s strength value slightly based on the number of attachments it has, so that the more other parts it’s attached to, the harder it is to break off.  Again, hopefully giving the player further interesting trade offs to choose between when building their constructions.

Yet more optimisations

OK, it seems I spoke too soon when I said in the last blog post that I was done with optimisations to the construction modification code!  When working on the damage system, I found that detaching parts off large constructions with lots of parts could still be really slow, so over the last few weeks I’ve been working to resolve this.

Setting transform parents

When modifying a construction (i.e. attaching or detaching parts), I need to change transform parents in order to manipulate the construction’s transform hierarchy, and by far the biggest performance cost I found was with this re-parenting.  Even when setting worldPositionStays to false when calling SetParent() so that Unity doesn’t have to recalculate world transforms, it’s still really slow when you call SetParent() a lot, due to Unity internally updating the physics colliders.  When modifying a large construction, in the profiler I was seeing Physics.HandleColliderHierarchyChanges and Physics.SyncColliderTransform costing many tens, sometimes hundreds of ms!

So now I’ve done everything I can to get rid of unnecessary re-parenting, thereby minimising the number of SetParent() calls, specifically:-

When fixedly attaching parts together, all the parts have to be re-parented from their current rigidbodies to a single rigidbody.  Now, parts from the rigidbody with the smaller number of parts always get re-parented to the rigidbody with the larger number (without re-parenting the larger number of parts).Similarly, when deleting fixed attachments, parts need to be re-parented to separate rigidbodies.  Now, after determining the groupings of parts left after attachment deletion, the largest group always stays under their original rigidbody, and the rest get re-parented to other new rigidbodies.Lastly; I was parenting rigidbodies that were part of the same construction to a container gameobject, this was handy for clarity and debugging purposes, but not strictly necessary.  I changed the code to maintain the rigidbody-to-parent-construction relationship a different way, rather than relying on the transform hierarchy for this.  After that I was able to eliminate setting of the rigidbodies transform parents entirely.

Other optimisations

I was using List<T> to hold temporary lists of parts and rigidbodies when determining how to reorganise a construction hierarchy after deleting attachments.  If there were a large number of things in these lists (e.g. parts), then calling Contains() or Remove() on them would be noticeably slow because these are O(n) operations (a linear search).  So I switched over to using a HashSet<T> instead, for which these operations are O(1).

After a construction is modified, its rigidbodies bounds and mass properties (e.g. centre of mass, inertia tensor, etc.) need to be recalculated.  I’ve now optimised the code that does this, mostly by caching data that doesn’t change (e.g. for parts that haven’t been re-parented to a new rigidbody).

Also after a construction is modified, a few GetComponentsInChildren() calls were being used to cache references to rigidbodies and parts.  These calls were quite slow (and also caused some pretty sizable GC allocs), but after restructuring the code a bit, I was able to eliminate the need for them.

Results

All of these optimisations added together have made huge gains, at least in the test case I was using (a construction with over 2000 parts).  It used to be that detaching a single part in this test could take well over 300ms(!) which caused a noticeable frame rate hitch, now it takes less than 37ms.

Around 22ms of this remaining time is taken by updating rigidbody mass properties (assigning to mass, centerOfMass, inertiaTensor, and intertiaTensorRotation), which there’s not much I can do about.  I can’t understand why this would be so slow, something odd seems to be happening under the hood in Unity.  Maybe this issue is fixed in Unity 2018, but for now I’m stuck on 2017.4, due to the Networking API issues I’ve discussed in previous posts.  Another 12ms out of the ~37ms total is taken by Unity in Physics.UpdateBodies, which I don't think I can do anything about either unfortunately.

Networking and optimisations

Sorry for the lack of updates for the past couple of months, I was away visiting family and things for some of that time, but I have also made a lot of progress on the game.  So let’s dive in!

Networking layer

Most of my time lately has been spent on networking code.  As I discussed in the previous post, the Unity networking API situation at the moment is unfortunate to put it mildly.  To mitigate against this, I’ve now built a new networking abstraction layer.  This wraps and hides away all direct access to the deprecated Unity RakNet based API that I’m currently using, and should facilitate easier migration to a different networking API in the future.

This was a big task as it touched code throughout the game.  There are four major aspects to the networking API that needed to be eliminated from the game code: Network static API, network messages, NetworkView, and NetworkPlayer.  In more detail:-

Network static API, e.g. Network.isServer, Network.SetSendingEnabled(), etc.  These are now only used inside the networking layer (or where absolutely necessary, wrapped behind a new API for use in game code). Network messages, e.g. OnServerInitialized(), OnPlayerConnected(), etc.  These are now only used inside the networking layer, and where necessary propagated out to the game code via events. NetworkView, used for remote procedure calls (RPCs) and state serialization:- RPCs.  The new layer now allows game code to register methods, then remotely call, and receive them.  Internally this currently is still implemented using a NetworkView and RPCs. State serialization via OnSerializeNetworkView() and BitStream.  I’ve now implemented a system within the networking layer to synchronize state across the network.  Internally this is still implemented using a NetworkView, OnSerializeNetworkView(), and BitStream, but none of this is exposed to the game code. NetworkPlayer, used to uniquely identify a connected player.  Now the new networking layer assigns its own ID for each player, and keeps a reference to each player’s NetworkPlayer for use internally only

After of all of these changes, the Unity networking API is no longer directly referenced anywhere in game code.  The next step will be to actually change the networking layer’s internal implementation from using the Unity API to something else.  This will likely still be a painful task, but should be far more manageable now than it would have been before.

Construction modification optimisations

In the previous blog post I talked about the optimisations I’d done to the construction modification code (this code deals with attaching and detaching parts).  The performance of this code is particularly important in the context of the damage system which can require a large number of parts to be detached at once.

I have now implemented a GameObject pooling system, which eliminates the last major remaining performance cost, that being the instantiation and destruction of construction and Rigidbody GameObjects.  In the example I showed in the last post (shown again below), the cost of breaking the attachments is now down to less than 10ms (prior to doing any optimisations, it was around 60ms!)

image

There are still more optimisations I can do.  For example, the instantiation and destruction of the attachments between parts are contributing some performance cost (and GC allocs).  Plus, associated with the attachments are the physics ConfigurableJoints between Rigidbodies, which also have to be created and destroyed.  Maybe I could pool these too, something to look at in the future for sure.

But for right now I’m happy enough with the performance that I can get back to working on the damage system.

Damage system

On which subject, I’ll be returning my focus to this next.  I still need to decide how to propagate collision forces to cause plausible breakage of parts.  Also, I’m leaning away from the idea of damage accumulation and attachment “health”, towards more of a probabilistic method, but I’m not entirely sure yet.

Optimisations and explosions

As I’ve alluded to in previous updates, the damage system is still a way off from completion, so that’s what I’ve been working towards over the last month or so.  One challenge is to design a system to propagate and accumulate damage in a way that is, if not realistic, at least plausible, as well as making sense to the player (without being frustrating or annoying).

Before I can get to this though, there is a more fundamental problem.  Breaking parts off a construction due to damage requires efficient construction modification code, and the existing system just isn’t fast enough.

UI Optimisations

The first problem I looked at was with the construction list in the world tool UI.  Whenever a construction is created or destroyed, this list in the world tool UI gets updated accordingly.  When a part gets broken off a construction, it’s re-parented under its own new construction GameObject, and this process was getting slowed down by the world tool UI being updated.

So now the UI elements in this construction list are held in a pre-allocated pool and used / reused as needed, which avoids the performance cost and GC alloc of instantiation when a new entry is added.  Also, the UI update code now queues up any new constructions and only adds one element to the UI per frame, this results in a slight visible delay as the player sees the UI updating itself, but avoids a single frame performance spike.  In fact I made these changes to all other UI screens too that have a large list of entries (for example, the saved game screens).

Construction modification code optimisations

I’ve now also optimised the construction modification code (actually I had to completely restructure it) to be simpler and more efficient.  It now uses fewer server-to-client RPC calls, only one per player operation (operations being things like attaching a part, deleting an attachment, etc.)  There are less GC allocs too, as it now reuses many of the temporary data buffers these operations require.

These changes so far have made a big difference.  I hacked in a key so I can trigger the deletion of all attachments in a construction for testing purposes, as you can see in the example below.  In this example the cost of breaking the attachments went from around 60ms to less than 25ms on my machine, still a significant performance spike, but definitely moving in the right direction.

image

The major remaining performance cost is with instantiating new construction GameObjects, and also the Rigidbody GameObjects that live under them (as I mentioned before, parts get re-parented to these when they’re broken off an existing construction).  So, just like with the UI elements, to solve this I’m going to need pre-allocated pools of these GameObjects.  However before I do this, to make life simpler, I need to remove all references to Unity networking stuff from the constructions.  Which brings me to another issue…

Unity networking API woes

GearBlocks is still using the old RakNet based Unity networking API, which has been deprecated for a while (and now completely removed from Unity 2018.2).  I was waiting for Unity’s replacement for it - UNET, to be a bit more mature before I switched to it, but sadly UNET has now also been deprecated.  Apparently there’s another replacement solution coming at some point in the future.  Anyway, I guess it’s a good thing I never switched to UNET, it will be supported for another couple of years I believe, but there doesn’t seem much point using it now.  So the upshot is, I’m probably going to have to look for a third party solution.

Whatever networking solution I end up using, one thing is for sure, I really need to abstract the networking API away from the rest of the GearBlocks code as much possible.  This is something I should have done in the first place really, it’ll make changing networking APIs much easier in the future.

So to allow for pooled construction GameObjects, and as a first step towards this abstraction, I’ve now implemented my own world object ID system.  This allows GameObjects to have a unique ID consistent across the server and all the clients, and is now used by construction and part GameObjects.  This allowed me to remove the Unity NetworkView from the construction GameObject (which will make pooling them easier), and move all code for state synchronisation out of the construction and into a central manager that synchronises the state of all constructions together.

The next step in this abstraction effort will be to wrap all the RPC calls (currently scattered throughout the code) behind another interface.  As well as meaning there will then only be one place in the code to modify when I change networking APIs, it will also allow me to remove the NetworkView from part GameObjects too.

Explosives go boom

My future plans for GearBlocks mean that the damage system needs to apply damage not only from collision impacts, but also from explosives.  So I had some fun adding a simple placeholder explosive that’ll serve as a good test for now.  Right now it only applies a force to nearby objects, it doesn’t do any damage yet, that’s something I’ll have to work on soon!

image

Here’s a quick update on some of the changes in the new demo build

Here’s a quick update on some of the changes in the new demo build: world tool UI improvements, preventing part inter-penetrations, better collision sounds, and more.

GearBlocks Demo 0.5.6773

I had to fix a few last minute issues as is usually the way, but finally here's the new demo release as promised.  Enjoy!

Glitch fixes, demo update soon

Last week I fixed a problem that someone found while playing the demo, player feedback is so valuable and always much appreciated by the way!  Here’s the scenario; the player deletes a jointed attachment (e.g. rotary, slider, etc.) between two intersecting parts, but the parts still belong to the same construction after the deletion.  Physics will consider these parts to be inter-penetrating, and if the construction is unfrozen, it’ll try to force them apart.  This can sometimes cause your constructions to jump all over the place like they’re possessed.  Here’s an example of the problem.

image

The solution I came up with was to keep track of the intersections left after attachment deletion, and prevent the construction from being unfrozen until they are resolved.  The player can do this by deleting other attachments until the intersecting parts are no longer part of the same construction.  Any unresolved intersections are now shown by a red cross as can be seen below.

image

I’ve also been working on a bunch of bug fixes, mostly regressing issues introduced by recent changes.  Another more serious problem was a crash that sometimes happened when quitting the game, the Unity error log didn’t point to anything obvious in my script code, and I couldn’t find any other devs on the forums having a similar issue.  After a lot of trial and error I found which version of Unity introduced the problem.  So I rolled back to 2017.4.2 for now, any 2017 version after this seems to have the crash (I haven’t tried any 2018 releases yet).  I don't know what was changed that caused this crash, I didn’t find any clues in the Unity change logs.  After the next demo release, I’ll just upgrade to the latest 2018 build and with any luck the issue won’t reappear.

Speaking of the demo, I should be ready to put the next update out in a day or two.  I finally got my new video card today to replace the one the died, so I’m now able to do some final testing before the release.

Collision exposition

As I mentioned in the last dev update, I’ve been working on re-implementing the collision contact system, which is used for triggering impact sounds and applying damage to constructions.  I’ve now finally completed this work, not without some challenges along the way though, and it ended up taking far longer than I was hoping.  Not to mention my video card died and my Internet connection went down last week, fun times!

Apologies for the wall of text, but here’s my attempt to explain what I’ve been up to.

Impact overload

The old collision code dated from the early prototype days, and simply played an impact sound (and applied damage to the construction) directly in the OnCollisionEnter() event handler.  This event gets triggered once for every collider pair that makes contact, which can end up being a lot particularly if there are many moving parts in a construction, and meant that way too many impact sounds were being triggered concurrently.

Also, I’ve been working on adding sliding sounds for when parts slide past one another.  This requires continuously tracking collision contacts, for which I use the OnCollisionStay() event.  Again, this event gets triggered once for every contacting collider pair, except that unlike OnCollisionEnter(), it gets called every fixed update for the duration that the colliders are contacting one another, so the performance cost of any code in the event handler becomes a real concern.

Unity performance woes

On the subject of performance, the overhead for Unity to collect the collision contact data is one thing, but what I find even more frustrating is the way it must be accessed.  For every single collision contact, a call from the Unity engine (unmanaged C++ code) into the C# script is made via an OnCollision…() event, with an attendant GC alloc for the collision data being passed into the event handler.  This means in my “worst case” tests where I had thousands of collision contacts per update, I was seeing a performance cost in the tens of milliseconds, and thousands of GC allocs totaling a few MB.  This cost is just for reporting the collision contacts, and does not include the physics sim update or anything else.

I wish it were possible to access all of the per update collision contact data in one call, preferably into a pre-allocated buffer, but for now we’re stuck with the OnCollision…() events.  Hopefully at some point Unity will improve this situation!

I tried to find a way of eliminating OnCollisionStay() while still keeping the sliding sounds working.  It seemed like it should have been possible because you can still keep track of what colliders are currently contacting by using OnCollisionEnter() / OnCollisionExit(), and then get the velocities from their rigidbodies.  Unfortunately what you don’t have is the new contact position and normal each update, which are required to calculate the relative velocity at the point of contact, necessary for the sliding sounds to work properly.  I tried fudging my way around this by estimating these values, but couldn’t come up with a solution that worked reliably.

In the end I resigned myself to keep using OnCollisionStay(), and turned my attention to optimising the code inside the OnCollision…() event handlers as much as possible, and consolidating the collision event data into something more manageable.

Discard and merge

The first step was to discard any collision contacts whose separation is larger than a small threshold value, happily this eliminated most of the spurious impact sounds that were being triggered when parts were merely sliding past one another.

The second part was to merge collision contacts such that for each update, only one contact is considered per Rigidbody pair / PhysicMaterial combination.  This means that, for example, a construction with a large number of parts all made of the same material and all rigidly attached together will only generate one impact or sliding sound.  The most important thing was to perform this merging as efficiently as possible because the OnCollision…() events can be called so frequently; it was crucial to avoid any computation, conversion, GetComponent…() calls, etc. inside the event handlers.

To keep track of the currently active contacts, the system now uses a dictionary whose keys are a struct containing the two Rigidbodies and the PhysicMaterial (these are all available directly from the data passed into the event handlers).  The dictionary’s values are a struct containing the contact position and normal, the merging happens by only keeping this data for the contact with the smallest separation, the rest are discarded.  Then every update this dictionary of active contacts (of which there aren’t that many due to the merging) is looped over, calculating the required relative velocities, and updating the sliding sounds accordingly.

To mitigate the OnCollisionStay() performance overhead further, I also added an option in the game-play settings to disable it, for players with low end machines and / or particularly complex constructions.  This effectively disables the sliding sounds, but the impact sounds still work, so it’s not the end of the world.

Audio materials

Once ready to trigger an impact or sliding sound, I wanted to add some variety and sophistication to the sounds, while also making configuration easier.  So now, rather than each part explicitly referencing which AudioClips to use, the system automatically maps from the PhysicMaterial to an “audio material”.  Each audio material specifies the AudioClips to be played on impact and during a slide.  The pitch of these sounds are scaled based on the mass of the part that is colliding, and there can be different AudioClips chosen based on the pitch scaling factor.

I also added support in the audio materials for a “rolling sound” (played based on the angular velocity of a part when it’s contacting something).  This allowed me to make the wheels (which have had sliding and rolling sounds for some time now) use the same unified system.  I do love me some unification!

AudioSource pools

Despite the aforementioned reduction in number of collision sounds being triggered, there’s still no real limit on how many could be triggered concurrently.  Also, each part behaviour might have a sound playing (e.g. motor whine, gear whirr, propeller wash, etc.) which is only limited by the number of active part behaviours.

To bring this situation under control and place a hard cap on the number of AudioSources, I implemented a pooling system.  This pre-creates a fixed number of AudioSources and keeps track of which ones are currently in use.  The collision contact system and the part behaviours can request to play an AudioClip via the pool, and if a free AudioSource isn’t available the request is ignored.  Once an AudioClip has stopped playing, the corresponding AudioSource in the pool is automatically freed up to be available for a future request.

Damage propagation

In the game, damage (based on the collision impulse) is only dealt with in the OnCollisionEnter() event handler, not OnCollisionStay().  However I still wanted to optimise this as much as possible, so rather than applying damage directly in the handler, it is now accumulated over an update.  The total damage is then applied once per update (this is where the damage is divided up and propagated out to part attachments).

I still have some work to do on the damage system but this at least moves the code out of the event handler, and means that if I need to increase the complexity of the damage propagation code, it shouldn’t affect performance too much.  This is a topic I’ll be revisiting in a future update.

Dev update Apr / May - part 2Linker toolI’ve continued work on the linker tool, creating the first pass implementation of an indicator for it, this can be seen above with some pulleys (notice also the automatic belt routing, sweetness

Dev update Apr / May - part 2

Linker tool

I’ve continued work on the linker tool, creating the first pass implementation of an indicator for it, this can be seen above with some pulleys (notice also the automatic belt routing, sweetness!)

I think I now have a solution for how to handle parts that have multiple linkable behaviours, but I need to start implementing it to really see if it’ll work out.

Resize indicator

I’ve added a new indicator to show the selected part’s bounds during resizing, this was particularly needed for parts that can resize along all three axes (e.g. sloped plates) to make things clearer for the user.

UI stuff

Up until now each part behaviour has had a specific pre-created UI with all of its elements (key bindings, sliders, checkboxes, etc.) laid out ahead of time.  This was very inflexible and made it awkward to add or change which user adjustable parameters a part behaviour exposed.  So I’ve now removed these hard-coded UIs and replaced them with a generic part behaviour UI implementation that automatically populates itself based on what parameters a particular part behaviour exposes.  This will make adding new part behaviours (and modding support!) much easier in the future.

I’ve also modified the world tool construction UI to allow for multi-selection, this allows you to select multiple constructions at once and perform an operation (such as delete, freeze, etc.) on them all in one go.

Dev update Apr / May - part 1Sorry for the radio silence over the last couple of months

Dev update Apr / May - part 1

Sorry for the radio silence over the last couple of months.  Here’s an update on what’s been happening, there’s a lot to talk about, so I’m gonna break it into two parts!

Collision impacts, and damage

I’ve simplified and optimised the construction modification code and the way attachments are handled.  This means that adding or removing parts from large constructions is now noticeably faster, but there’s still more optimisation work to be done in this area.

Being able to quickly break attachments without causing frame rate drops is a requirement for the damage system, and I’ve been revisiting this too, fixing a few bugs that had crept in.  It still needs more work, but above you can see an example of the damage system in action as it is right now.

On a related note, the collision impact sounds have been a source of complaint for some, and I agree!  There are too many collision sounds when parts are merely sliding past one another.  I’m currently working on overhauling the collision impact system to make the sounds behave better, and the plan is that this will improve the damage system at the same time.

Servo and stepper motors

It’s been suggested that you should be able to set the servo motor target to angles greater than +/- 90 degrees, this was a perfectly reasonable request and sounds like it should have been an easy thing to do!  However, due to the way I was interpolating between the servo’s current and target angle, it would always rotate through the smallest possible angle.  Which meant that for a range of greater than 180 degrees it could easily end up rotating in the wrong direction towards the target angle.

I’ve now completely re-implemented the angle interpolation code to work a different way, so that it maintains the correct rotational direction.  Now a servo motor’s max angle can be set to +/- 180 degrees.

Likewise, the stepper motor’s step angle can also now be set up to 180 degrees.  Here are a couple of examples, one with a step angle of 45 degrees, one with a step of 180 degrees.

I’ve also fixed a bug that would sometimes cause a servo motor’s centre “resting” angle offset to be incorrect after loading a saved game.  And finally, I’ve lowered the minimum speed for servos and steppers to 1 RPM, as I think it’s sometimes useful to be able to go that low.

Belt up!

Belt up!

Wow, the past few weeks have been rough as far as productivity goes!  First my PC blew its power supply, so I couldn’t work for a couple of days while I was waiting for a new one and then installing it.  Then this week I was totally wiped out by a nasty cold and got pretty much no work done all week.  I guess that’s the way it goes sometimes, really frustrating though.

Anyway…I have now finished the pulleys and belts, barring a few minor bugs here and there.  The belt rendering is now done and working nicely, the belt automatically routes its way around pulleys based on how they are linked together, and seeing the belt really makes the behaviour of the pulleys appear more convincing.  Have to say I’m pretty pleased with how it all turned out!

I’ve also added a “pulley whirr” sound that changes based on the pulley’s RPM, and a “belt snap” sound for when the belt breaks (this happens when pulleys move too far from their original position).  These details all add to making the pulleys and belts seem “real”!

The last video in this series showcasing GearBlocks player builds from last year, this one themed mostly around cars and trucks

The last video in this series showcasing GearBlocks player builds from last year, this one themed mostly around cars and trucks.  Thanks again to everyone who has played the demo, given me feedback about the game, and shared their fantastic creations!

Here’s part 2 of this player creation’s series, some very cool stuff in this one

Here’s part 2 of this player creation’s series, some very cool stuff in this one.  The final part will uploaded very soon.  Enjoy, and thanks everyone!

GearBlocks Demo 0.5.6628

Time for another long overdue demo release, and an update on what I’ve been working on recently!

Linker tool

After the last update where I talked about the pulleys and linker tool that I was working on, I have since completed the first pass implementation of the linker tool, and links between pulleys can now be set up by the player (rather than being hard coded).

However, the linker tool goes far beyond just pulleys and belts, my intention is that it’ll be a general way to associate various part behaviours together (e.g. batteries, switches, motors, and eventually, more advanced control systems), and this introduces the one major wrinkle I still have to figure out.

The thing is, parts can potentially have multiple behaviours associated with them, which means in theory there could be multiple links between two parts.  I need to decide whether to either prevent multiple links (and in which case, how to do this in a way that makes most sense), or allow for them (in which case, how to represent them to the player via the UI, and if the player should have the ability to create links between individual part behaviours).

I also still need to add UI indicators, both to show those links already existing, and a link as it’s being added or removed (right now I’m still using debug lines).

At this point I decided to have a break and work on some other stuff instead, but I will be getting back to the linker tool very soon.

Third person camera

I’ve now added third person cameras to the game, both for when the player is walking around, and for when they’re seated.  I debated doing this for a while actually, because I don’t currently have a proper player model, but I finally relented mainly because it’s so much fun to be able to see vehicles from the outside as you’re driving around!

The player models and animations I’m using are just placeholders that I put in ages ago for the prototype multi-player mode.  Of course this now forces the issue - I now have to decide what the player character(s) should look like, as well as source the models for them, and put in better animations.  Looks like I’ve just created a load of more work for myself!

Wheel physics revisited

OK, this is the big one.  It wasn’t supposed to be a big deal, but ended up taking several weeks to sort out!  I wanted to build on the “proving ground” aspect of the desert map in the game, so I added some bumps and ramps (for testing vehicle suspension and so on).  However this highlighted a significant problem with the wheel physics.

Let’s briefly recap how the wheels worked up until this point.  First the wheel finds where it contacts the ground, by firing a Raycast towards it (perpendicular to its rotational axis) to find a contact position and normal.  Then, it uses a ConfigurableJoint connected to the wheel’s rigidbody, that every update gets repositioned using the contact data, and has a linear limit set up to provide the collision response.  If you’re interested, I did a detailed write up on this a while back: http://tmblr.co/ZzNKAt1D-zxlq

Using a Raycast to find the ground contact point was acceptable on terrain with a smoothly changing gradient, but fails once other collision shapes besides the base terrain are introduced (such as boxes, spheres, etc.) for the wheels to roll over.

You can see here in this example that the Raycast can’t “see” the box, so the wheel inter-penetrates it.  But worse, if the wheel continues to move in the direction shown, the Raycast will eventually hit the box, causing the contact point’s height to change instantaneously, pushing the wheel up with a large impulse.

So I wanted to come up with a new technique to find the contact point that would meet some important criteria:-

It should ensure that the contact point’s position changes smoothly with no discontinuities.It should allow the wheel to accurately roll over box, capsule, and sphere colliders.It should not change the wheel’s behaviour on the base terrain (this can be very sensitive, particularly for vehicles traveling at high velocities).It should not incur any additional performance cost over the existing solution.

I experimented with many alternative ideas, including using a bunch of BoxCasts to approximate a cylindrical shape, but everything I tried failed one or more of these criteria.  That is, until I eventually settled on using a single CapsuleCast in the downward direction, whose radius is the same as the wheel’s.

However this clearly has similar problems to just simply using a CapsuleCollider for the wheel.  For example, if the wheel is tilted to one side relative to the ground, we get a contact point outside of the wheel, coming from one of the capsule’s “end caps”.  To get around this, I effectively clamp the contact point to be within the wheel’s outer rim, as shown in the diagram below (this time viewing the wheel end on):-

This assumes that the terrain’s gradient doesn’t change too much between the found contact point and the final clamped point!

Another problem is shown here, where the CapsuleCast would find a contact point on the box in this example, not the point on the ground that we actually want:-

To get around this, I simply discard any contacts coming from colliders outside the planes indicated by the dashed lines in the diagram above.  So in this example the box's contact point would be discarded, and the ground contact point is used instead.

So all in all, this technique is a bit of a kludgy approximation of a true cylindrical collider, but it actually seems to work quite well.  I’m pretty happy with the results!

Other stuff

I’ve also done load of code refactoring, bug fixes, UI improvements, rendering improvements (post processing effects, lighting), and other miscellaneous stuff over the past few months.  Check it all out in the new demo build, have fun!

Part 1 of a series of videos demoing some of the fantastic GearBlocks community builds from last year

Part 1 of a series of videos demoing some of the fantastic GearBlocks community builds from last year.  I meant to do this at the end of the year, but I was working on adding a third person camera to the game and I wanted to wait until that was in, as it better shows off these creations!

Parts 2 and 3 will be coming soon…

Pulleys and belts

Apologies for the lack of updates lately!  I’ve been working on implementing pulleys and belts in the game, and I was hoping to get them finished before posting an update.  However, as always seems to be the way, they’re taking longer than I expected.  They’re not quite done yet, but I have made enough progress now that it’s worth talking about where things are at.

Pulley physics

The first thing I had to figure out was how to physically constrain a pair of pulleys together such that they would transfer motion and torque correctly.  My plan was to use PhysX constraints (as exposed by Unity’s ConfigurableJoint) to accomplish this, in the exact same way I do for gears.

However, pulleys differ from gears in two important respects:-

Pulleys transfer motion and torque over a distance, through the belt that connects them (unlike engaged gears, which must always be adjacent to one another).A pair of pulleys linked by a belt rotate in either the same direction or opposite directions, depending on whether the belt is in an open or cross configuration respectively (unlike a pair of engaged gears, which always rotate in opposite directions).

The first idea I tried was to set up a constraint whose anchor points were positioned on the edge of each of the pulleys, with motion locked along the tangent vector as shown below for two pulleys A and B:-

image

However, this didn’t work well at all because the constraint anchor points were separated by such a long distance.  The pulley motion was unstable at anything other than very low RPMs.

So the next approach I tried was to instead calculate the two circles centered on each of the pulleys, whose radii are in the same proportion as the pulley’s, and whose edges touch each other.  Then I placed the constraint anchors on the edge of these circles, represented by the dotted lines in the diagram below for the two pulleys A and B (again, motion is locked along the tangent vector):-

image

Note that these dotted circles are only used to position the constraint anchors, they aren’t visible and don’t interact with the world in any other way!

This method seems to work pretty well, it also easily allows for a cross configuration belt in a similar manner (by calculating proportioned circles whose edges instead touch in between the two pulleys, and positioning the anchor points where they touch).

Implementing pulleys in game

Actually getting the pulleys functional in the game required a lot more work beyond just the physics constraints.  I wanted to allow the player to link an arbitrary number of pulleys together in whatever order they like, to form a chain that determines the route the belt takes through the pulleys.

For this I created infrastructure to associate or “link” parts together (or more specifically: link their part behaviours together).  This needed to generalise beyond just pulleys, because I plan on also using it to link other parts together in the future (e.g. batteries, switches, motors, and eventually, more advanced control systems).  It also needed to facilitate restrictions being applied (for example, in the case of pulleys, only allow linking if the pulleys are coplanar, and only allow each pulley to be linked to a maximum of two others).

Based on the order the pulleys are linked together, I also implemented a system to automatically calculate the belt routing (i.e. which side of each pulley the belt should go), which is then used to determine whether to use an open or cross configuration for the constraint between each pair of pulleys, as well as for positioning the visual representation of the belt.

I wanted pulleys to be able to move around slightly when the construction is unfrozen, but obviously there’s only so far a belt can plausibly stretch!  So I wrote some code to deactivate the belt (both constraints and rendering) when any of the pulleys move too far from their original position, giving the appearance that the belt “broke”.

This work is complete now, and the pulleys are working in game.  There are still a couple of major pieces left to do however:-

Right now the links between the pulleys are hard coded just so I have something to test with.  I still need to make a linker tool to allow the player to create and destroy the links themselves, as well as a UI to show these links.Currently I’m just using debug draw lines to visual represent the belt, so I need to implement some code to generate a proper render mesh for the belt.

But for now, here’s an example of some pulleys linked together, the yellow debug lines showing the links, and the black ones representing the belt:-

image

So lots left to do, but this should be really cool once it’s done, and I’m excited about the possibilities that the linker tool will allow for with other parts in the future!