Movement and Game Feel
Instead of talking about what I said I would talk about in the last post, I’m going to talk about what has been consuming my nights and days recently – Game Feel. Especially game feel with regards to input and controls.
Controls. Like few other things in game creation, bad controls can render your game nigh unplayable if not at least unpleasant to play. It’s because of this that I’ve spent a fair amount of time recently investing into the controls of Reborn. Whether that’s paid off remains to be seen, but intent has to count for something… right?
I’m currently reading a book called Game Feel which tries to more clearly articulate how a game feels to play and assign metrics and explanations to why different games feel the way they do. It’s been a really interesting read so far and gave me an idea on how to analyse my game and improve the feel of the controls. Using an idea mentioned in the book, I created a system which enables me to graph various values in my game and see how input changes those values.
I created it partly in the hope that a hard metric like this would actually help me at all and partly out of curiosity about what kind of graphs my game would create. I am happy to say that not only has it helped me tune my game much closer to how I wanted it to feel but I got to see some SUPER interesting graphs too!
In this “Game Feel” book, they use the concept of ADSR envelopes to analyse input and movement in games. If you want a more in depth explanation on the concept of ADSR, I really suggest reading the book. It’ll do a way better job than me. I’m more familiar with the concept from playing guitar and tinkering with amps and effects pedals where it’s used to analyse to sonic character of an instrument. ADSR stands for Attack-Decay-Sustain-Release and is a way of dividing up an sound’s volume over time.
For something like a piano, the “attack” is the period from when the key is first pressed to when the maximum volume is reached; the “decay” is when the volume dips from this maximum down to a stable volume level; the “sustain” is how long this stable volume level is held for and the “release” is the period from when the key is released to when the volume hits zero again. Applied to a game character, the run key is pressed and the character hits his maximum run speed (attack), the character continues to run for a bit (sustain), the run key is released and the character stops (release). Most games seem not to use a decay in the movement speed. Armed with this new knowledge I dug into my game to try to figure out what was what.
I started by analysing my character’s movement speed over time. In the graphs below, you can see the increase in the value (attack), the continued run (sustain), and the deceleration after run is released (release).
Firstly, my movement was feeling too twitchy which is fine and was feeling good, but wasn’t weighty like I wanted the character to feel. From the graph I could see that the acceleration was too fast and linear and for some reason there was an exponential component in the deceleration (which was a bug I probably wouldn’t have found otherwise).
So after a bunch of tweaking and bug fixing, I arrived at this. An exponential acceleration, so that as soon as the run key is pressed there is a big and obvious change in the character’s motion, but not completely linear so it feels more organic and heavy, and a longer linear deceleration. So far so good.
Next I checked that the jump was behaving as I expected and thankfully it was. This graph shows the vertical speed of the character. When the line’s in the center of the graph the character isn’t moving vertically, above he’s moving upwards and below he’s moving downward. With the high jump (the first jump in the graph) we can see the character very quickly accelerate upwards, slowly decelerate and reach the apex of the jump, hang there for a bit and then accelerate downwards until he hits the ground. In the short jump where the player releases the jump button before the jump apex to alter the eventual jump height (second jump in the graph), we can see the character accelerate upwards, the acceleration gets cuts short by the release of the jump button, the character hangs for a bit and then slams back to ground. Woot!
I sent my prototype out to get play tested by some friends and most seemed to like the way the controls were feeling, but I got two reports of the the dodging mechanic feeling “weird”/”abrupt”. So back into the graph to see what the problem could be. The movement speed during a dodge looked like this. I wanted the explosive acceleration but maybe the deceleration was too fast? So I reduced that, sent it back but no love. Still feeling weird. I was a bit lost and was ready to write it off as “different strokes for different folks” but after some more play testing I noticed what the graph looked like if you dodged while running.
Ahhh… So if u dodged during a run, the character was decelerating to a standstill and having to build up his speed again giving a feel of momentum loss. Possibly what the testers were experiencing, so after some tweaks later:
A nice smooth transition between running and dodging sans momentum loss. Hooray. I may have fixed that issue, but I suspect this will introduce another issue of making dodging the optimal method of locomotion around the level resulting in players just dodging everywhere which isn’t really ideal. I think I’ll have to do something about that like put a cooldown on the dodge, or go back to the original behaviour but push it even further so that the player is rooted to the spot for a short time before they can move again. After all, the dodge is supposed to be used to escape danger and evade attacks not to just run faster, but that’s a problem for another day
That’s it. I hope this has given you some ideas on how to analyse the input and control in your own game and make things feel better, or at least some insight into how I’m muddling through it. If you have some other ideas let me know. I’m always keen to learn new ways to improve my games.
Character Movement
I have been super busy with freelancing work and working on Reborn (that’s the working title of the platformer game I’m making with Filip Orekhov), but I thought I’d take some time to write a blog about the progress so far.
I’ve been mainly working on the character movement and the weapons systems and combat. I’ve been trying to get a good base together that I can start adding other features on top of.
I’m just going to talk about the character movement for now. I’m writing a platformer framework code base that can be reused under a large number of circumstances and game types (within reason, obviously) and is highly tweakable to be able to easily create very different feeling characters and motion. I’ve also been trying to wrap Unity’s 2D and 3D physics systems up behind a facade so that the core movement code can be used regardless of whether I’m using 2D or 3D collision. I’m taking things I’ve learnt from doing Tom Sparks (top down shooter/platformer), Neon Shadow (FPS) and my own 2D platformers and making the system generic enough to be able to support any of those types of games. So far it seems to be working out OK and the player character is feeling pretty good to move about.
Here’s a shot of what most of the configurable systems looks like (I’m using Hercules sprites for the main character from http://www.spriters-resource.com which is an awesome resource when you’re prototyping things and are rubbish at art)
First up, I have a class called MovementSenses which constantly updates with information about the character’s surroundings which I use to determine how the character should react. Like “Am I on the ground?”, “Is there ground in front of me?”, “Is there a ledge near my hand that I can grab?”, etc. There are a few rays that I can drag around to configure to the current character showing things like where the hands will be for ledge grabs and that kind of thing.
Next I have the main movement controller class which has a ton of tweakable values to get the movement I want. One thing I quite liked is the “Jump Gravity Arc” curve which is an animation curve that controls the character’s gravity while they’re jumping. Doing this enabled me to generate a huge array of jump arcs and to be able to tweak the arc until I was happy with it. I ended up using a base gravity on the jump, reducing gravity near the top of the jump to give a bit of hang time and then increasing it past the original value to pull the character down quite hard which gives the character a sense of weight but still feels agile and makes sticking landings more intuitive too. The movement controller is a state-machine inside but I’ve written it in a way that is (hopefully) easily extendable to be able to add new movement states as they are required. For example: the base MovementController class is only able to do running and jumping. Then I have the derived PlayerMovementController which adds more abilities like dodging, ledge grabs, wall jumps, etc. I’m still trying to decide what abilities are generic enough to be put into this class and which ones I should move into a more specific RebornMovementController class, but for now it’s fine. There are a lot of little tweaks in here that aren’t technically right but make the game feel better. For example, there is a period after running off a ledge when you can still jump; if you jump when you’re close to the ground but not on the ground, the character will jump when he hits the ground; if you’re not holding a run direction when you land after a jump, the character decelerates much faster (helping to stick landings); etc. These things are all cheating and being nice to the player, but without them players will find that your game controls feel loose/sticky/unfair/just plain bad. Player’s aren’t computers, so we need to help them translate their intent into the game world (or just try to predict their intent) without taking the control and challenge away from them.
As you can see, for this game I’m using the 2D physics system which is OK, but not great. I found a few instances of the character getting stuck in geometry or collisions not happening the way I’d expect and having to add work-arounds for some other things, but it’s functional for the most part and I think I’ll stick with it as it provides some functionality that the 3D one doesn’t and is supposed to be less expensive in terms of processing. The one thing I really liked is the PolygonCollider in that I can adjust it in the editor without having to create my own specific MeshCollider so that I can have a more complex collider shape than a capsule. Fil and I decided that we didn’t want to do the whole typical run into an enemy, take damage and be pushed back thing, but then I had to solve the problem of what happens if you jump on an enemy. Standing on them or floating above their heads wasn’t really that great so I went with the sort of crystal shard shaped collider which causes the player to slide of the top of enemies as you can see below. Herc’s friend there is titled Mr Bonjangles and hails from Golden Axe
Sometimes it feels perfectly fine and other times feels a bit weird and floaty, so I might need to address this in the future by either refining the collider shape or putting in something that, when colliding with an enemy, will increase gravity a bit or push the player further off the enemy to make sure they continue to fall at an acceptable rate and not slowly slide off at the rate of my daughter’s porridge on our walls.
Well, I think that’s enough for now. Will talk about the weapons system and combat or the camera controller next I think unless there are other requests… or I just find something else to talk about.