Man, writing Unity Editor scripts is addictive.
One of the things I’ve come to really like about Unity is the ability to write Editor Scripts, i.e. scripts that modify the behaviour of the editor itself to allow some pretty neat optimization and… may or may not take more time to write than the optimization they provide. But… but… writing them feels so good… and… and then once you have one…
To be fair, I’m getting faster at it, so, like something something opportunity cost isn’t approaching zero?
This week, I decided to convert the Stages system over to something a little more structured than what it was before. Previously, I’d just hard-coded levels into the game in a switch statement, and this worked, but… it had this annoying problem where creating a level involved more than one step 😦
To get a bit more specific, I implemented each level as a scene in Unity. Unity lets you load new scenes to basically refresh the set of Game Objects that are active, do clean-up, etc etc. Unity ALSO lets you load scenes additively, which is where you have some scene, and then load another into it. That’s how I do my levels. I have one Play scene with shared functionality that makes gameplay do its thing, and then individual level scenes that contain the arrangement of objects that make up the environment.
In order a load scene, Unity requires you to add that scene to the build settings (this only has to happen once, it’s, like, associated with the project, not associated with an instance of your running game), and if you forget to do this, you get a bunch of angry messages in the console telling you that you’re a worthless individual and forgot to add the scene to the build settings, probably because you’re just human garbage.
I decided to scriptify this! Now Unity automatically adds scenes in certain folders to my build settings in a process I don’t want to go into right now that involves writing them to an XML file.
This worked pretty seamlessly (I’d done this previously, so I wasn’t just inventing it for this), but things got complicated when I wanted to add new fields to the XML file without ever having to do anything that might result in a typo (I’m really good at maikng tpyos).
I tried to find a way to read in metadata from files, like the tags files can have in certain versions of OS X. I spent probably far too long on this and resolved, nope, not able to do that (at least not in an obvious way), so I decided to tell the script to write in fields I could fill in later. The tricky part involved making sure not to overwrite existing fields, but to add them if they didn’t exist.
The good news is, my code looks beautiful! Actually no. It doesn’t. It never does. But it MAKES pretty things!
Okay, so maybe YOU don’t think so. But like…
WHATEVER, IT’S PRETTY, GET OVER IT
Anyway, it feels reeeeeeally good to add scenes and not have to worry about that build settings error any more, and also to be able to have all my stage data in one spot.†
†it was pretty much in just two spot before: one section of code + the file system. Now it’s just in the file system, and this XML gets generated based off that. I will have to go into the XML occasionally, to enter specific data into fields other than the stage name, like the display name etc etc. If I could figure out how to encode that data in the files, in theory, I wouldn’t ever have to open the XML file, but… some other time I’ll work on that… maybe…
Okay okay, I haven’t had any pretty pictures yet.
So… you know what time it is!
Sprite Cover in 2D
An issue that’s been bothering me for a while is that, because of the way I’ve implemented flower sprites (i.e. each flower is made of multiple sprite stacked at various zorders), sprites from different flowers would cover each other up in what would appear to a player weird or broken ways. Since the face was on the top layer, for example, it would ALWAYS appear on top of a face sprite, even if that face sprite was an opponent’s… so if you stood behind an opponent, your face would appear on top of your opponent’s petals…
This week, I finally fixed that issue! How did I do this?
Although I’m building a 2D game, Unity’s still a 3D engine, and I can still use a lot of the 3D stuff to my advantage. In this case, I was able to set the z coordinate of any objects I so desire in the scene based off their y coordinates. I had to be sure to account for camera distance too, otherwise objects would seem to disappear if they ever passed behind the camera.
The sort of wonky (and cool) thing about this is that there are two other ways I’m determining which object gets drawn on top: zorder and layer order. Layer order takes precedent over zorder which takes precedent over z coordinate. As long as I keep that all in mind though, all should be good.
Also, this is much better than what I was thinking of doing; I was considering writing a shader to do draw all the textures in the proper order, then apply zorder to those shaded sprites. Not only is setting the z coordinate easier (for me) to think about, because it’s more visually confirmable, but also it may be more efficient than doing this via a shader. Not sure though. Anyway, I’m not getting huge performance hits I don’t think.
With my newfound solution to layering sprites, I was able to pretty easily add a new tile type: grass you can walk through.
If I like it enough, I may make it taller and make it rustle as you move through it, so you can only see where you are based on the rustling. Maybe bees can also hide in it.
I’ve also started making the stage selection screen look a little better. Ideally, it’ll have a larger image and name too.
I quite like the look of this guy, and may take some inspiration from it. It’s pretty clean and not too flashy.
Also, and this may have been apparent from the XML, stages can now be unlocked by playing matches! The UI I’ve added to show the player this is meant to show up after a match, but I also save the “do show” and “did show” data, so that the UI can appear to players who haven’t yet seen the message but have earned the unlock, in case of power outage or whatever.
That’s all for this week
Until next time,