Hi all, time for a long overdue progress update on the scenario mode, Lua scripting, and tutorials. This will continue on from the last blog post so check that out if you haven’t already. Okay, let’s get stuck in!
Exposing the game’s events and global variables to Lua scripting was a good start, but only allows the scripts to do pretty basic stuff. To properly open things up, scripts need access to entities in the game (such as players, tools, constructions, parts, and so on), so I’ve added interfaces for a whole bunch of classes in the game code and registered them to be accessible from Lua scripts.
I won’t go through everything in detail here, but here’s a brief overview of some of these interfaces:
- State properties (is frozen, total mass, velocity, etc.)
- List of parts making up the construction.
- Methods to get a member part from an index, for moving the construction, and so on.
- Part’s attachments (allowing access to each attachment’s position, connected part, etc.)
- Material properties (mass, strength, is paintable, etc.)
- List of part behaviours.
- State properties (camera mode, is in free flight, velocity, etc.)
- Targeter (to get currently targeted part).
- Part inventory (mode, available part catalogue, etc.)
- Toolbox (to get the active tool and the part selection).
- State properties (pivot part, is currently aligning, etc.)
- Currently selected parts.
- Methods to modify the part selection.
This is by no means a comprehensive list, but hopefully gives a flavour of what’s available. I’ve made functions accessible from Lua scripts that can get hold of the game’s construction and player instances, and then interrogate / manipulate them via these interfaces.
More UI features and proxies
Following on from the UI windowing system I covered in the previous blog post, I’ve made more UI elements available that can be added to a window from Lua scripting: toggle, slider, drop-down menu, input field, and picture (displays an image texture).
To support the interfaces, UI features, and Lua scripting in general, I had to add some more proxies for Unity types and static methods. These are: Quaternion, Time, Input (for raw input as opposed to key bound input actions), Texture (includes a function to load textures from file), and Rect.
A Lua script can serve many purposes, but I think they essentially fall into two main use cases, a scenario script or a “script mod”. A scenario script is loaded and run automatically when the player starts playing a scenario and is there to configure the game for that particular scenario. Whereas a script mod can be loaded at any point and can implement a tool, a custom UI, and so on.
Lua scripts can be loaded from any path location using the debug console, but I’ve added a UI screen for an easier way to load script mods from a “standard” location (this being a ScriptMods folder alongside the SavedConstructions and SavedGames folders). This UI screen also allows for publishing script mods to the workshop and loading those downloaded from the workshop.
I’ve written some simple tools as script mods that make use of some of the interfaces mentioned earlier.
- Player tool: displays player’s ID and current state (position, velocity, etc.)
- Construction tool: displays current number of constructions, allows debug functionality to be enabled (e.g. “show part bounds”), and for a construction to be made non-targetable or even invisible.
- Part inspector: shows targeted part’s ID and current state (position, rotation, etc.)
- Attachment inspector: shows targeted attachment’s position, connected part, etc.
Here’s an image showing all of these tool scripts running at once:
Some of these tools are useful for making scenarios, and they also serve as examples of how to write script mods, so I’ll include them with the game.
For example, the part inspector can be used to find out the IDs of parts and constructions in a scene, and then those IDs can be used in a scenario script to reference those particular part or construction instances. Another example use would be preventing certain parts from being detachable or constructions from being targeted.
For the tutorials and other scenarios I wanted to have “checkpoints”, i.e. a way for a Lua script to detect when a player or construction enters a particular area in the scene. So I’ve added a new checkpoint part that can be placed in the scene and defines a trigger volume (actually a couple of variations, a box or cylinder). These parts don’t do much on their own but they provide enter / exit events for Lua scripts to handle and implement useful behaviour.
The checkpoint parts need to be static (i.e. non movable under physics), so I had to implement a way to make a part be “pinned” (i.e. its parent rigidbody remains kinematic, even when the construction is unfrozen). This will also be needed for making a building foundation part which I want to add in the future to allow for buildings and other static constructions.
Here’s what the checkpoints look like, note they also have a customisable text label:
I’m excited about what’s now possible using checkpoints and scenario scripts, for example: timed laps with split times, obstacle courses, mini-games (e.g. vehicle based soccer, robot golf), you name it!
One of the main motivations behind scenario mode and Lua scripting are the in-game tutorials, and I’m making decent progress with these although it is slow going. It’s quite tough trying to break down the game’s complexities into simple incremental steps that gradually build upon the player’s knowledge.
Here’s what I have made so far:
- Briefly covers player movement (should be pretty familiar to anyone not living under a rock! :))
- Spawns a go-kart in front of the player.
- Introduces the construction menu and has the player use it to unfreeze the go-kart and turn it on.
- Gets the player used to controlling a construction by driving the go-kart, ending the tutorial once they reach a target speed.
- Starts with an upside down go-kart.
- Introduces the builder tool and has the player use it to freeze the go-kart and select a pivot point.
- Introduces the translation and rotation manipulators and gets the player to use them to pick up and rotate the go-kart to be right side up.
- Once the player unfreezes the go-kart, has them drive it over to a checkpoint.
- Starts with a go-kart with no wheels, and some loose wheels next to it.
- Has the player use the builder tool to position and freeze the go-kart, ready for building.
- Gets the player to pick up a wheel, use the rotation manipulator to rotate it, and align it to one of the go-kart’s axles.
- Once they attach the first wheel, has the player attach the rest.
- Introduces the concept of attachments, and has the player target the wheel attachments and cycle them to rotary bearings.
- Once the player unfreezes the go-kart, has them drive it through a sequence of checkpoints.
Tutorial 4 is still in progress but will likely introduce the idea of detaching and moving parts, and the builder tool UI for spawning new parts.
I’m trying to make each tutorial build upon the previous one, and be a little more challenging for the player each time. As you can see I still have a way to go with this, I’m hoping things will go a bit faster now that I’ve implemented most of the game code support.
I reckon I’ll probably end up with around ten basic tutorials, and that’s just covering the essentials of building. I might make a second more advanced series of tutorials to cover mechanical concepts, but we’ll see how things go.
Recently I’ve also done a major Unity upgrade to 2020 (I tried 2021 but it broke some UI stuff), and plowed through a whole load of bug fixes.
Next up will be to continue working on the tutorial scenarios, and try to get those done as soon as possible. I’ll also try adding some other simple scenarios, and I’m sure there’ll be one or two other supporting features I’ll need to implement in the game itself. That’s it for this update, thanks for reading!