Original post on my personal projects blog, Six-Six-Punch.
“Ultimate” is not a word I use lightly.
Or maybe I should say, if there was any word I didn’t use lightly, “ultimate” might be that word.
Full disclosure: the following project as described is probably not “ultimate” in any actual sense.
In fact, I was thinking of calling this project o’ mine the “Extensible PC Controller” – getting strait to the heart of it: a character controller script that would be easy to update, to be used in all of my future 2D side-scrolling game projects. But “Extensible” doesn’t play well on a T-Shirt, so that’s out.
What is a character controller? In my mind it is a script that translates the button presses of the player into the actions of the character on the screen. This includes managing movement, character’s special abilities, and the animation the character displays at any given time. What’s with the PC? It’s not a “computer” controller, it’s P for player, C for character, anyway moving on.
Here’s the scope of the project in a little more detail. I’ve worked on a few 2D platforming projects in Unity, and have run into a couple issues each time. Unity comes with a robust set of features for character control and animating, all of which can be completely ignored or misappropriated at the designer’s whim. That means there’s no one right way to achieve the effect you’re going for, and that can be daunting.
I also have a perennial problem with single-script character controllers, in that they tend to get out of hand real quick. All of the tutorial scripts I’ve come across are made-to-order, eschewing object oriented design for straightforward line-by-line code. The end result is typically a mess of boolean states and timers, spread across multiple update methods. That means that adding new maneuvers to the character, like perhaps a double-jump, inevitably leads to a tangled nest of if/else statements. Yuck.
What I look for in a 2D platformer
She needs equal parts class and sass. I like my ladies with a little weight and momentum, if you know what I mean. None of this prudish “real-world jump physics” stuff, I need some old-fashioned air control. And get out of here with your timid “tilt-to-walk” analogue stick nonsense, this ain’t 3D stealth. This is 2D ACTION, my friend. I want that double-tap, air-dash, hold-to-charge, wall-kick, super-move-screen-clearing, slide-tackle-goodness.
And she can’t be shy about adding new moves to the repertoire now and then; I get bored easy, so without some variety in the move list I might just wander off. Don’t hate the player, girl.
What I want in my Character Controller
With that in mind, here’s what I want out of my Ultimate PC Controller:
1. A standardized system for applying accurate movement to the character
2. A standardized system for handling character animations
3. A system that can be easily modified, where character moves can be added, removed, or changed between games or within the course of one game.
4. A system where the numeric details of each move can be modified from within the Unity editor.
And now, gentlemen, my genius plan:
1. Applying Movement – For applying movement I have decided use Unity’s built-in physics engine rather than point-based math for each character move. There are many advantages here, not least of which is time saved on code writing. It will also be easier to leverage Unity’s built-in colliders and materials, and with the way I plan to manage multiple simultaneous actions, it should make things simpler when combining movement. Plus, after playing around with the out-of-the-box Unity physics, I found that a lot of the momentum-based character movement was close to what I wanted – I need that little skid at the end of a long dash to feel alive.
2. Character Animations – I was inspired by an article on 2D Animation Methods in Unity, recently posted on Gamasutra. The article experiments with three separate ways of handling character animations, one done entirely in code, one that uses code to trigger Unity animations, and one built in Unity’s mechanim animator with as little code as possible. The article raises some good points about working with 2D animation in Unity regardless of the method you choose, I highly recommend giving it a read.
In the past I have relied on the mechanim animator for most of my projects, and I can say first-hand that it can be unwieldy for 2D. This makes sense, since it was primarily designed for use with 3D bone-based animation, and that can be troublesome when working with old-school 2D animations. I think the best solution is to choose the middle path by using Unity’s animation framework to handle each animation, and triggering these animations from within your own code structure. This lets you put Unity’s animation engine to it’s full use, doing things like changing colliders based on animations and timing sound effects to key frames, but without needing to mess with mechanim’s state-machine transitions.
3. Object Oriented Moves – Here’s the big one, but I won’t spend too much time on it here and now. The current scheme is to build a multi-class rig where each character move is represented by its own script sporting the same “MoveBehavior” interface. Each of these classes will contain a method to check the conditions for triggering, and a method with the physics operations to apply for that movement. The PCController class will contain a list of these objects, along with it’s own logic for determining the character’s positional states (airborne, grounded, hit). Every update, the PCController will iterate through its list of currently-attached moves and resolve each one separately.
I get the feeling this system will provide some challenges when it comes to handling move priority, but on the other hand it will let me confine the guts of each move to its own script (which can be edited or swapped out on a per-game basis). This will also force me to build each move in a way that plays nice with others, and should facilitate combining forces from multiple simultaneous moves. Hopefully that will avoid some of the stiffness of 2D character controllers built in single scripts or with state machines.
4. In-Editor Tweaking – This is an added bonus of the OO approach, surfacing key values in the editor becomes a cleaner process. Because the physics logic for every one of my character’s moves will be encapsulated, each script will decide which values to make public to the editor. When working in the editor, each of these scripts can be collapsed or expanded for easy compartmentalization, and because all of the physics logic is kept separate, you can change the character’s run acceleration with worrying about how it might affect their dash attack.
I plan to do a few updates while assembling this beast, and write up some documentation on its use once I’ve tested it some. If you have ideas, questions or feedback, find me on twitter @ NinjaBoots88