Playable build – updated
Dynamic gear engagement
The engagement between gears is now activated and deactivated dynamically. This means (as the various parts of a construction move around) gears will engage if they move close enough to each other, and disengage if they move apart. The test that checks if a pair of gears are engaged is fairly expensive, and obviously I now have to do these tests every update. So to avoid doing this between every pair of gears in a construction (i.e. O(N^2), not good), I use trigger volumes around each gear to find pairs of gears that are close to each other, and then do the engagement check only on these.
New steering wheel part
I’ve added a steering wheel part to the game that attaches to axles. It has a behaviour similar to the motor, where if “switched on” it will rotate in response to user input (i.e. the usual hold shift + directional controls).

Its obvious application is as a vehicle steering wheel, but more generally it can be used as a “control wheel” anywhere you want to rotate bits of your construction in response to user input.
Playable build – updated
New rack gear added
I’ve just added a rack gear to the game, useful for rack and pinion steering among many other things. Rack gears engage with spur gears that are positioned directly above them.

The implementation is still preliminary and still needs a bit of refactoring / cleanup, but it seems to work well so far, which is a relief. It looks like my gear physics solution is holding up!
There is one significant issue remaining with gears generally however, which applies to all gear types but is particularly highlighted by rack gears. Whenever a construction is modified (by adding or removing a part), a search is performed to find pairs of gears that are next to one another and should be considered engaged, and then a physics constraint is set up between each pair. However this is done only once, after the construction is unfrozen and things start moving about, the gear engagement pairings are not updated. Obviously this becomes a problem if the gears move apart from one another, it also won’t engage gears that start off apart, but then move together.
So I think my next big task will be to overhaul the gear engagement system so that it updates dynamically. It will need to be reliable, and not incur a big performance cost doing lots of spatial searches etc. could be tricky!


New gears now in the game
This week I’ve been working on a Python script for Blender to procedurally generate the meshes for all the various gears I need. I’ve also added support in the game for crown gears, which engage with neighbouring spur gears at 90 deg.
Next I’m gonna extend the Blender script so it can generate a rack gear mesh, and then have a go at implementing support for rack gears in the game.
Playable build – new gear physics
Playable build – new gear physics
Well, after many weeks of trial and error, experimentation and frustration, I think I finally have a solution for the gear physics! To recap, the problem with my old implementation was that it was only considering relative angular motion between the gears, and not linear motion as well. This made the gears behave incorrectly if they had any relative linear velocity.
Need for a new solution
My old gear physics implementation was inspired by the one in Box2D, so I looked there again for ideas. It turns out they work around this problem by also taking into account the angular velocity of the rigidbodies that the gears are attached to. I played around with this idea for a while but I found it didn’t really extend well to my more general 3D case.
There were also other things to consider, like supporting other types of gear such as rack and pinion. Also, the fact that my gear physics was only updated once per FixedUpdate (and not as part of the main PhysX solver update) caused lag, or “wind-up” between the gears under high torque loads. A compromise I was living with, but was never really happy about.
Using configurable joints
So I decided to throw out my old approach and instead make use of the built in PhysX constraints (or “joints”), as exposed by Unity’s ConfigurableJoint. The idea was to position the joint anchors at the current contact point between the two gears (right at the edge of the gears where they touch), and then lock the motion only along the tangent at that contact point. Then every FixedUpdate, the joint anchors are re-positioned to the current contact point (as the gears will have moved slightly). By carefully positioning the anchors like this, the gear ratio (relative torque transfer), and the relative angular and linear motion are all taken into account automatically. This approach also makes it relatively easy to add support for rack and pinion gears. And…by using built-in joints, the gear constraints are solved along with everything else, so there is minimal wind-up.

Sounds good in principle, right? However the re-positioning of the joint anchors is where things get tricky. If every fixed update, they are simply re-positioned exactly to the new contact point, the gears will gradually slip when under load. This is because a joint doesn’t perfectly rigidly lock its anchors together, and there will usually be a small difference in position between them, even after the physics solve. This error gets fed back into the new joint anchor positions and the error accumulates over time.
Correcting the joint anchors
So I tried correcting for this error by figuring out what the anchor position delta was vs. what it should have been. This is not easy because there is not really an absolute angle for a rigidbody, only an absolute position. The orientation angles of a rigidbody wrap every 360 degrees of rotation, so you’ve no idea how many of these rotations have happened since the last update. You end up having to integrate velocity over time and accumulate the positional delta as found at the contact point between the two gears. There are two problems with this. First, I found that when comparing the contact point velocities between the two gears as reported by Rigidbody.GetPointVelocity, they seemed slightly off if the gears were moving linearly relative to one another. Close, but not spot on. This small error was compounded by the second problem, which is that by accumulating the contact position delta over time, any errors also accumulate – quickly. It creates a feedback loop, the error feeds into the joint anchors, which causes the joint to pull the rigidbodies around too much, causing more positional error, which feeds into the new anchor positions in the next update, and so on. This leads to unstable physics behaviour – high impulses, oscillations, and your machines exploding like crazy.
At this point I got pretty desperate, thinking I might have to abandon gears altogether, maybe even the whole game. I even tried mocking up a solution using physics colliders (one BoxCollider for each gear tooth!), and using the collisions between the teeth to provide the gear behaviour. Er yeah – that didn’t work unsurprisingly.
Predefined anchor positions
Then I came up with the idea for the solution I have now. Re-positioning the joint anchors exactly to the gear’s contact point leads to accumulated error and gear slip. So instead, each gear is given predefined positions at equal intervals around its circumference, and every update the one closest to the current contact point is found, and that’s the position used for the joint anchor. As long as the distance between these predefined positions is greater than the distance between the joint anchors after the physics solve, you get no gear slip.

However, there is a problem with this if the gears are different sizes, as shown above. The next / previous predefined anchor positions as measured along the contact tangent don’t quite line up due to the differing radii. I tried correcting for this with a fun bit of trig, the maths worked out beautifully, but in practice it led me right back to another feedback loop, the joint and its corrected anchor positions ended up fighting each other, causing oscillations, exploding machines and much cursing. In the end I just went with a simpler approach of just upping the number of predefined anchor positions, so that any differences along the contact tangent were minimised. However, this of course means the distance between each predefined position is smaller, so increasing the chance of gears slipping under load. In practice it’s actually not too bad though, it takes quite a high torque load to cause slip (to the point where axle hinge joints are also being noticeably pulled apart).
Next steps
This whole endeavour has been very frustrating, as the ideas I tried often worked fine most of the time, only to fail in particular use cases (certain combinations of bevel gears seemed to be particularly sensitive). I spent a lot of time switching back and forth between my various approaches, trying different modifications, until homing in on what I have now. It was so time consuming as I had to do lots of testing every time I made a change to check that I hadn’t broken one of my many test cases.
Well, hopefully the implementation I ended up with will see me through. I’ve tested a lot of situations (complex gear trains, high torque loads, high rpm, etc.) but the open ended nature of this game means I might have missed a case where things go bad, let’s hope not. Next up I’m going to work on implementing rack and pinion gears, and probably worm gears too, I wanna really be sure these will actually work with no problems, before going ahead with any other part of the game.
Gear physics – a bit of a setback
I just realised it’s been ages since my last post! This is because there hasn’t been anything new in the game to speak of over the last few weeks. Unfortunately, progress on the project was completely halted when I discovered a serious flaw in my gear constraint implementation.
The problem is, it is only transferring rotational motion between gears, not linear motion. This works for static constructions with rotating gears, but as soon as the gears themselves move about, it is totally (noticeably) incorrect. If I can’t fix this, then it pretty much screws up the rest of the game as I have it planned. So I need to try and get it sorted before proceeding with anything else.
Over the last few weeks I have been digging through Box2D and Bullet code for inspiration, and have tried a few different solutions with varying degrees of success. I have one idea I’m pursuing at the moment that seems promising, but we’ll see, it may come to nothing.
The good news is, if I can fix this gear physics issue, it’ll fairly easily allow me to add rack and pinion gears (where linear motion is obviously crucial).
Honestly, I’ve been very demotivated by this setback. The game wasn’t progressing as quickly as I’d like anyway, and this really hasn’t helped. It’s been a real struggle to keep going. Hopefully I’ll figure out a solution soon, wish me luck!
Playable build – updated
Centre-of-mass indicator and bug fixes
This week not much outwardly apparent has changed with the game but I’ve fixed a load of bugs, including a fairly major error in the gear constraint code that sometimes caused gear trains to gain too much angular velocity.
I’ve added an indicator that shows a construction’s centre-of-mass when you freeze it. This will be useful when you want to balance a construction around a pivot point or centre-of-lift (e.g. flying vehicle, see-saw, etc.).
Construction controls update
Over the last couple of weeks, I’ve made a couple of changes to the controls:-
- After parts have been attached together, you can now cycle their attachments between available types (e.g. rigid or hinge), by hovering over attachments and pressing E.
- Cloning and deleting entire constructions is now done via a separate menu (accessed by holding Shift + Q).
More rendering improvements and other fixes
Also now in the build:-
- A load more rendering improvements following on from the previous overhaul. The main difference being that the sky and distant water are now rendered before everything else, using another separate camera with a much larger far clip distance. This prevents the horizon line from being clipped out.
- Time-of-Day upgrade.
- Reference grid in inventory part preview images.
- Force zones now slow down objects at world boundaries.
- A bunch of bug fixes.
Playable build – updated
Rendering overhaul
In Unity, full-screen image effects, such as screen-space ambient occlusion (SSAO), bloom and tone-mapping, can only be applied after everything else has rendered. You can optionally flag image effects to render between opaque and transparent stuff, but that doesn’t help me because image effects wipe the stencil buffer, which I need for object highlighting.
Previously there were many things about the rendering order in the game that were just plain wrong. For example, SSAO was being applied after water and atmosphere / fog, and 3D UI elements were being bloomed and tone-mapped. Ideally you want to be able to interleave image effects and other rendering at will. The only way to do this in Unity is to use multiple cameras (with only the first one clearing the screen, the rest rendering on top). Here is how I have things set up now to achieve the correct rendering order:-
Camera 1
- Clear screen.
- Render opaque objects (e.g. terrain and other solid objects).
- Render object highlighter mask texture using stencil values written by object shaders. This has to be done before any image effects, as they wipe the stencil values.
- Render SSAO full-screen image effect.
- Render atmosphere / fog as a full-screen image effect.
Camera 2
- Render transparent objects (e.g. water), these apply atmosphere / fog in their shaders.
- Render object highlighter full-screen image effect, using mask rendered earlier.
- Render sun shafts, bloom and tone-mapping image effects.
Camera 3
- Clear depth only.
- Render 3D UI elements.
- Render 2D UI / menus etc.
- Render anti-aliasing full-screen image effect.
Unfortunately, using multiple cameras like this exposes some long standing bugs in Unity which really screwed me up for a while. Luckily there are known workarounds for these, for more info you can check out these threads:-
- http://forum.unity3d.com/threads/deferred-renderer-multiple-cameras-posts-ssao-bugged-ufps-onrenderimage.198632/
- http://forum.unity3d.com/threads/grabpass-problems-when-using-multiple-cameras.167676/
Ambient occlusion
I’ve also fixed some issues with SSAO that were causing black speckly artifacts to show on the distant terrain. Now that SSAO looks much nicer, I’ve enabled it by default. I’ve also fixed a bunch of other bugs and issues!


