09 January 2020

ShipBasher Development Log 3: Hat Simulator 2̶0̶1̶9̶ 2020

Months-long intervals between posts and then suddenly two posts in one day?!? No. Maybe. As it stands right this minute, I'm uncertain whether this post will actually be finished and I'll deem it ready to publish before another day has gone by, but I do know that I've started typing it within one day (mere minutes, in fact) of the last time I was typing one. Assuming reality is real and all, that is.
Right, the actual post content...
ShipBasher is supposed to include an editor for ships - you know, so you have something to bash. Actually the reason I'm calling it "ShipBasher" is as a portmanteau based the term "KitBash," which describes taking a bunch of existing parts (provided to you prefabricated or previously created by you) and combining them together into a new thing. This is more or less the point of Legos, though I've mostly heard the term in reference to computer-generated artwork, e.g. a 3D animator modeling a bunch of little greebles and then instantiating and intersecting them with each other to make a big awesome mech or, well, spaceship. This is, in fact, how the spaceships in the original Star Wars trilogy came to be.
In ShipBasher, ships (or stations, or drones, or whatever else) are assembled from a number of "modules" selected from a menu, instantiated, and positioned, not unlike the ship editors for Battleships Forever, Kerbal Space Program, Space Engine, and Spore. I don't intend to support resizing or reshaping of the modules as some of these do, at least not at this time, but I do intend to allow editing of the module instances, something that was not supported in "StarBlast!," the prototype version of ShipBasher (again, no affiliation with starblast.io).
Here's how this editor thingy looks so far:
Whoa! Look at that fancy transform manipulator! Maybe I'll write about that another time.
Some features are obviously still in the works, e.g. module previews and better modules that aren't just textured cubes or boring gray thrusters I made in Blender and have yet to bother texturing, but the important features I planned to include are all at least indicated here. At the top is a UI for the ship to be named and given a faction (and in the future, other properties) and buttons to save the ship to a file, load a ship file, clear the scene for building a new ship, and exit. At left is the menu to add modules, with buttons to switch between module categories (e.g. thrusters, weapons, armor plates). At right is a UI related to the selected module, with buttons to change its parent module, duplicate it, delete it, and delete it along with any siblings assigned to it, and with an extensive list of fields for editing the module's properties, from its name to its position and rotation and even how much heat it generates when it turns on. This UI and these fields within it have been my main concern for the past few days.
There are a few dozen fields already and possibly more in the future, and every single one of these has to correspond to a specific property of the module and perform a similar set of tasks when a module is selected:
- if a different module was selected before, check whether the value in the field has been changed, and if so, compare it to the current value and the default value for the corresponding property of that module
- depending on what the new, old, and default values are, update the assigned property on the module
- examine the new selection and whether the assigned property has a value set
- depending on what the existing value is, display either that value, the default value, or a blank or zero value (depending on the field type) in the field
This is a lot of repetitive functionality that I had barely begun to implement in a rudimentary and very clunky manner so far, so about four days ago I set about building a clean new system for handling them. I started an empty scene in an empty folder in my general experimentation project, and in it I put a few simple primitives and a simple UI with a few fields of a few different types. In the end what I ended up making was basically a character creator, so I stuck with the idea and this is how it looks now:
You can read a bit more about my progress on this here: one two three four five
You can click on any of the three characters to select it, edit the character's properties, determine if it has a hat, and select any hat to edit the hat's properties.
Each character and hat has an "editable" component that stores a number of properties as instances of a "datum" class (this is the singular form of the word "data" btw if you want to sound smart). Each datum contains a value and an index. The index refers to an index in an array of names for the data, e.g.:
{ "name", "HP", "armor", "hasHat", "hiddenExtraPropertyNotShownInTheUI" }
The presence of the name array effectively turns each datum into a key-value pair, which is programmer talk for the sort of information you'd find on a web form: username = "problemecium", password = "••••••••", parkingSkillLevel = 100, isBeingPedantic = true for example. I can make any number of name arrays and have them correspond to different sorts of things, e.g. characters, hats, modules, or ships. Each editable is assigned to a certain name array and to a "default" version of itself that, naturally, contains a default value for every datum named in that array. Having this default allows instantiated modules to not have to store copies of every value, but rather only those that have been modified.
Each field also has an index, which determines which datum it is meant to display and edit. Fields are able to intelligently scan for a datum with the correct index, find the default value if no such datum exists, examine themselves for what form to have that value take (string, floating-point number, etc.), and display that value in the UI. Fields can be linked to other fields, e.g. the armor field shown above, so that players have multiple ways of reading and editing the information.
Each field is also able to independently target any editable in the scene. Thus as seen above, character fields can target a character when one is selected and still correspond to that character even when the selected item is a hat, or vice versa. This actually enables me to do something awesome that I hadn't planned at first: select and edit modules on a ship inside a level that contains multiple ships. I could even pause a level that's being played and then edit values in the modules on one of my ships, for instance refilling a fuel tank or setting a damaged module's HP back to 100%! Naturally I want players to have to enable the developer cheats to do this unrestricted, but a limited version of this functionality could enable them to create, say, a level in which you have a damaged freighter you have to protect because all of its turrets have run out of bullets and the engines can only operate at half thrust.
(Battleships Forever, a major early influence on ShipBasher, includes a mission where you can interact with damaged ships from a previous off-screen battle, as seen here.)
I'm considering releasing this system on the Unity Asset Store if there is enough interest in it, as I have designed it to not be specific to ShipBasher and, in theory, work with any project that involves selecting things and editing their properties. Please do let me know if you think this would be useful in a project of yours or if you see any issues or think there is a feature it sorely needs.
As it stands now, I think this is feature-complete, and with it having passed all the robustness tests I've thought to toss at it, I intend to start incorporating it into ShipBasher. I'm not entirely sure whether to maintain the existing interface design or try something new such as a single editor that handles levels, ships, and modules. With any luck, the next devlog will reveal some exciting progress on that front.

No comments:

Post a Comment

Sorry this isn't a real post :C

I've entered graduate school and, as I expected, suddenly become far busier than I had been before, leaving no time to maintain my blog,...