Hey everyone, I’ve just released another update, mainly focused on fixing bugs (some caused by changes in the previous update)!
I won’t cover everything here, but I’ll mention the major problem areas that were addressed. If you want to see a list of all the specific bug fix changes, please check out the #git-history channel on the GearBlocks Discord.
Unity Upgrade Physics Fallout
Some problems emerged after upgrading to Unity 6.0 in the previous update.
Swap Bodies for Gear and Pulley Physics
Originally, for gear and pulley physics constraints, “swap bodies” was enabled based on the connected rigidbodies relative masses. This was to ensure that the more massive rigidbody is considered the “owner” of the constraint by the physics engine, which can improve simulation stability.
I removed the code that enabled swap bodies during the Unity upgrade because something changed in Unity 6 that broke how joint anchors and axes are set up with swap bodies enabled.
This didn’t seem to make any difference in my tests, so I figured things were OK without it. However this turns out to not be the case, some player creations very much need the improved simulation stability from swap bodies being enabled!
So swap bodies has now been reinstated for gear and pulley constraints. This required a hack to work in Unity 6, clearing the connected rigid body before updating the joint anchors and axes, and then setting it back afterwards. This ensures the anchors and axes behave correctly, although constantly setting the connected body comes with a slight performance cost.
Broadphase Type
Originally the broadphase type was set to “automatic box prune”, but with the Unity upgrade I switched it to “sweep and prune” to improve performance in the “Welcome Tutorial” scenario.
However this change caused a massive physics simulation performance penalty for some particular player creations. I think this is because these creations have a lot of overlapping parts (and therefore colliders), which seems not well suited to sweep and prune.
As a result broadphase is now set back to automatic box prune.
Grabber Tool “Shove”
This was using AddForceAtPosition with the VelocityChange force mode, and got broken by the upgrade because Unity changed how torque is calculated when using this force mode.
To get the same behaviour as before, the fix was to use the Impulse force mode instead and multiply the applied force by the rigidbody mass..
Consequences of Allowing Temporary Links
In the previous update changes were made to temporarily allow links between parts that don’t belong to the same construction (as long as the constructions remain frozen).
I believe this was a worthwhile improvement that prevented links being lost while building, but it did introduce several knock on issues which all required addressing:-
- Serialization was broken for constructions with these temporary links, preventing saves from being loaded.
- Pulley belts were broken between linked pulleys that were not (yet) part of the same construction.
- Linked engine crank and cylinder parts could be moved such that the con-rod between them was unrealistically stretchy or pistons could appear in weird places.
- Links were being left intact between parts that had broken off due to collision damage.
An engine con-rod will now “break” if the linked crank and cylinder are moved too far relative to one another, similar to the way pulley belts break.
NOTE: I’ve added an “unbreakable con-rod” option to the engine cylinder part behaviour to disable this if required.
Broken Undo / Redo
The game’s undo / redo system works by storing a command in a history buffer whenever an operation (e.g. spawn part, create attachment, etc.) is performed. Each command is incremental, it relies on the scene state (parts currently spawned, attachments created, etc.) resulting from all the commands before it.
If an operation is done (e.g. deleting a part) without storing a command, it could lead to a mismatch between the current scene state and what other commands expect (e.g. that part should still exist). This can cause weird behaviour when trying to undo or redo, or even corrupt saved creations.
When operations are invoked normally by the player’s build tools, commands are added to the history. However when invoked by Lua scripts or from collision damage (for breaking part attachments), commands were not being added because the invocation was treated as “anonymous”, i.e. not from the player.
For reliable undo / redo, invoking an operation must always either:-
- Add a command to the history.
- Or clear it completely to prevent things getting into a bad state.
I’ve now overhauled the operations code to ensure that this is the case. This means that parts breaking off due to collision damage will now clear the history, and it also has implications for Lua scripting.
Lua Scripting
Operations called from Lua scripts (via IPopulateConstructions, IAttachmentOperations, or IConstructionOperations methods) now have an “invoke as player” parameter:-
- When set to false (the default) the operation is invoked anonymously, and the player’s undo / redo command history is cleared upon invocation.
- When set to true, a command is added to the player’s undo / redo history.
- Also, when set to true for IPopulateConstructions methods, player’s part inventory is checked, and parts added / removed as necessary.
Typically scenario scripts should invoke operations anonymously, so that they can’t be undone by the player.
However script mods, particularly those that provide advanced / extended tools, should typically invoke as player so that commands are added to the player’s undo / redo history. For instance, the included WeldTool script mod now invokes as player when creating or deleting attachments.
Recovering Broken Saves
The issues mentioned above (relating to temporary links and undo / redo), caused some people’s saves to be completely unloadable, even locking up the game altogether.
Saves had parts with duplicate instance IDs, constructions with no parts in them, or pulleys that were somehow linked to themselves. All of which would fail to load.
Scenes saved with temporary links between parts in separate frozen constructions would hang when loading.
Now the serialization code is improved to better handle loading these broken saves, allowing them to be recovered without the game hanging.
Release notes:-
- Removed “Translation Step Interval” from builder tool ADVANCED OPTIONS, please use “Step Interval” in the BuilderToolExt script mod instead.
- Engine con-rod will now “break” if linked crank and cylinder move too far relative to one another. “Unbreakable con-rod” option added to engine cylinder part behaviour to disable this if required.
- Lua scripting:-
- Added “invoke as player” param to IPopulateConstructions, IAttachmentOperations, and IConstructionOperations interface methods, so that:-
- When set to false (the default) the operation is invoked anonymously, and the player’s undo / redo command history is cleared upon invocation.
- When set to true, a command is added to the player’s undo / redo history.
- Also, when set to true for the IPopulateConstructions methods, the player’s part inventory is checked, and parts added / removed as necessary.
- Added method to IPartAttachments to get an attachment (if one exists) that connects to another part.
- Added “invoke as player” param to IPopulateConstructions, IAttachmentOperations, and IConstructionOperations interface methods, so that:-
- Bug fixes.
