I’ve made a lot of progress with the character screen over the last week or so, ever since getting the spiral stat/skill thing worked out:
Of course, except for the spiral (which you totally can’t tell above, but I finally figured out how to get anti-aliasing on the LineRenderer, so it looks much smoother), everything here is just a placeholder. I’ll come up with some actual images and textures to use later on (yes, I know that the icon for “punch” is a kick, and I don’t care), but these let me see how the layout will look, and test out various features.
I’m especially proud of the “select a weapon” popup- it took me a while to come up with a good way to do that, but I’m starting to embrace how flexible Unity’s prefab system is. I spent a long time trying to embed dynamically-generated text and images inside of a Vertical Layout Group, housed inside the Content block of a ScrollView, and it was an absolute disaster. Something about dynamically generating the stuff inside the Content block completely threw off all the size fitters, and the end result was very Picasso-esque. I probably could have spent a few more days getting it all worked out, but I realized it would be way easier and faster to just create a prefab for the icon-name-description weapon block on the inside, and jam them inside the Content of a ScrollView without any need for a Vertical Layout Group. After all, they’re all the same size, so I know exactly where they need to be positioned.
After that, it was basically just getting all the mouse-over behavior working right as far as highlighting and clicking things, and then replacing them on the character’s “equipped weapon” blocks.
You can’t see it in the screencap above, but right underneath where the “select a weapon” popup appears is the Equipped Armor block- that’s what actually contributes to your Soak value aside from your Might stat points and your Endurance skill points. As soon as I started working on that, I realized that I had sort of painted myself into a corner with my inventory system. My plan is to have one inventory “pouch” that holds all your items, whether they’re weapons, armor, key plot items, or combat consumables. However, so far I had only implemented combat consumables, and my combat code expects the list of inventory items to only include consumables.
I really don’t like the idea of having a “Weapons Inventory,” “Armor Inventory,” “Combat Inventory,” and “Miscellaneous Inventory.” But I also *really* don’t like the idea of rewriting everything in the combat code to support such an all-encompassing inventory list. I realized, then, that this is pretty much a textbook scenario for implementation of inheritance in classes. Most guides and books use animals for the examples- “Pet is a class of animals with four legs, Cat is a class of animals that eat mice, Cat inherits everything from the class Pet” kind of stuff. So, what I need is an InventoryItemClass that implements some basic stuff, like “name,” “description,” “purchase cost,” “icon sprite,” and an ability to return a list of items filtered by type (for example, only combat consumables). Then, WeaponClass will inherit from InventoryItemClass, but also include “damage dealt,” “skill used when attacking,” “melee or ranged,” and stuff like that. ArmorClass will also inherit from InventoryItemClass, and include “soak value.” Perfect.
After spending the last week tearing my hair out trying to make a spiral that matched the image I had in my mind, I feel like I’m starting to identify with some of the characters from that old Junji Ito body-horror comic.
I started working on the layout for the character screen, and realized that I really didn’t have a plan for portraying skill points and stats. In the game, they’re represented by dice just like in Mini Six, the tabletop system I created the (current iteration of the) story in. However, I don’t want it to feel like the digital version of a tabletop game- I want it to just be a story-driven game. Nothing against Baldur’s Gate, or anything else that integrates mechanics from roleplaying games into their stats, but I think that sort of thing narrows the audience down a little bit.
So I needed a way of representing the values of skills and stats. In this system, each skill is associated with a stat, and the points you put into that skill are additive with the base state when it comes time to “roll a check.” For example, the character might have 3D+1 (three six-sided dice plus one pip) in Might, and then they’ve added an additional 1D+1 into their Brawling skill. The next time they try to punch someone, they get to roll four dice and then add 2 to the result (since Brawling relies on Might). Initially, I thought about just showing some large symbol as a dice, and then fractions of that symbol to represent pips (three pips equal one dice, since the average roll on a six-sided dice is going to be about 3), but that just didn’t feel unique enough- it reminded me of health and pieces-of-heart from the Zelda games.
Next I considered just a single bar, with all the dice converted into pips for a single number. The “stat” pips could be shown in one color, and then the skill pips would get added to the end of the bar in a different color. I felt like this was a closer representation of the actual value, but even less unique as far as roleplaying and stat-based characters go.
Eventually I settled on cross between the two- each pip could be represented by a symbol that linked to itself, and they’d spiral around an icon that represented that particular stat. When the character earned pips, (for “leveling up”) I could just show it as whatever symbol I ended up using to represent the pip in the dialogue box. Now I just had to find some symbol that would tesselate into a spiral like that. I was picturing something like a hexagon, but smushed so that its “inner” sides were smaller than its “outer” sides. I spent hours looking for something that would work, with the constraint that I didn’t want the symbols on the outer radii to be significantly larger than the inner ones- that would imply that the skill points you earn at higher levels might be “worth more” than skill points at lower levels, and that’s not what I wanted to convey.
There just doesn’t seem to be any such shape- I’m sure it’s some sort of mathematical constraint, but it felt weird to be able to sort-of picture it in my mind but not be able to get it down on a piece of paper or find anything similar in Google Images. I finally settled on using just a regular spiral, but with segments of equal arc-lengths and thickness. I could still color them differently to indicate stat vs. skill, though I’d lose out on showing that symbol when the characters earn skill points (probably not that big of a deal in the long run). Something like this is what I was picturing now, and it felt much more reasonable:
Apparently, though, I completely underestimated how difficult it would be to reproduce this in Unity. First, I ended up having to use the LineRenderer object to get anything like this at all (unless I wanted to have a million different sprites to piece together every time I wanted to create a spiral). Unfortunately, it looks like the LineRenderer isn’t really intended for UI objects, and doesn’t work on canvases that are shown as an overlay (which took a while to realize), so I ended up having to create a new Canvas in camera space instead to draw everything on.
Drawing the actual spiral is actually very simple- I wanted an Archimedes spiral, where the distance between the coils doesn’t change as the spiral gets larger and larger. That’s a simple formula in polar coordinates, and converting polar to cartesian is no big deal. The tricky part, it turned out, was getting segments of equal arc-lengths. The formula for calculating the arc length of a portion of an archimedes spiral is… daunting:
It’s complicated because it involves integrals of trigonometric functions and exponents- this isn’t something I wanted to attempt in Unity. I found someone who came up with an estimate based on radius by assuming a circle instead of a spiral, but it didn’t work out very well for me. In the end, I finally just cobbled my own equation together based on trial and error- it’s definitely not a mathematically-accurate formula for calculating anything useful, but on the scale I was working in, it gave me a visual approximation of equal-ish arc-lengths:
Now it was just a matter of prettying it up. It was no trouble at all telling it to draw the different segments in different colors/materials based on whether that segment was part of the base stat or part of the skill points. I generated another spiral behind the whole assembly that was just black in color, and sized so that it would look like an outline for the segments. Then, in front, I placed a round image with an icon representing the base stat. Easy-peasy, right?
Except I started getting caught up in how Unity draws LineRenderer objects again. That second Canvas object I made to hold the spiral worked great up until I added the stat icon- for whatever reason, that icon seemed to completely ignore the “sorting order” I created for the UI components, and rendered behind the spiral instead of in front of it. I spent days modifying layers, render priorities in materials, sorting orders, adding/removing/modifying canvases and camera settings- something about the LineRenderer object just threw everything off, and nothing was acting quite the way I expected it to (after checking out Unity forums, it looks like I wasn’t the only one disappointed in how hard it was to work with LineRenderers).
I did eventually get everything working, though I had to go back and redo all my calculations for “is the mouse cursor hovering over this object or piece of text” because I had to drag all my UI objects out of the “overlay” mode and into “camera space” instead. And so I finally have a spiral that renders the way I wanted it to, after an entire week of messing around with it. Time well-budgeted? Probably not. But it’s a good-looking result:
This spiral would represent an Agility-based skill. 9 total pips in the Agility stat (which is 3D of dice) and an additional 4 pips in the skill itself, for a total roll of 4D+1 whenever the skill is used.
I guess it’s a good thing I’m not under any sort of deadlines.