Sunday 12 October 2014

3DS National Open Tournament, October 2014: What When Down?

I just finished watching the VOD of the first official SSB4 open tournament hosted by Nintendo, in NYC, and it was a blast. I was surprised, delighted, and intrigued by several aspects of them, and I am super excited to see more tournament play in the future. I will discuss the characters used in the tournament, which were somewhat diverse. First, though, I will examine the rules of the tournament, crafted by Nintendo, which show design from the creators beyond just crafting the game. To be clear, I'm discussing solely the top 16 bracket shown on October 11 live from Nintendo World in NYC.

Thou Shalt Smash (Finally)

The first thing I noticed tuning into the starting matchup of Mario VS Kirby was that they were playing on the Paper Mario stage. Not the Omega Form one either - the moving, dynamic, and frankly dangerous one. Very much a This Is Not Evo kind of stage. It's really four or five stages, taking the players through an epic journey, winding up in Bowser's Castle, one of the most unforgiving play areas imaginable. Then a Smash Ball appeared and well... shit got real.

Turns out, the rules for the first two rounds (Top 16 and Top 8) of the tournament were as follows:


  • Single Elimination
  • Random Stage, No Omega Form
  • Character Customisation Allowed
    • All Special move variants
    • Limited Equipment (only stat boosts, no Start-With-Item stuff. They didn't say exactly what the limitations were)
  • No Items, Except Smash Ball.
  • 6 minutes per mach

These are not rules we'd see in a community-organised event like Evo or The Big House. Typically, Smash tournaments have striven to be as even as possible, making skill the deciding factor. No items, few if any stages with hazards of any kind, and character customisation is new to SSB4. This is a bold statement from Nintendo: our game, our rules. I respect that attitude. They built this game knowing there was going to be a competitive following. They are aware of the intense skill to be found among their fans. With these rules, they are challenging those players to learn everything about the game - not just For Glory mode.

Allowing character customisation was something that surprised me a bit, but I mean, why not? It's there, and it adds a lot of complexity to the game. Megaman becomes a much different character if his Side B is a freeze ray and his Neutral B explodes all but himself.

As a point of interest, the rules for the Top 4:
  • Single Elimination
  • Random Stage, No Omega Form
  • Character Customisation Allowed (same as top 16/8)
  • No Smash Ball
  • 6 minutes per match
And the finals:
  • Best 2 out of 3
  • Random Stage, ONLY Omega Form
  • Character Customisation
    • Same as before, and player can alter their customisation between games
  • No Items
  • No Time Limit
So, the rules do level out to something you'd expect from a high level Melee tournament, notwithstanding character customisation. Luck can carry you to the finals, but not to the prize. One (of three) Rosalina & Luma player, Dabuz, got Jungle Japes for his first two rounds, a stage which is advantageous for the character. If he didn't deserve those victories, we'd know it by the finals - but he 2-0'd his opponent to win, proving his worth.

This kind of rules design is something Nintendo has been doing with Pokémon for years. The Pokémon Championships have different rules each year, restricting Pokémon choice, item use, battle format (usually Doubles), and move selection, fostering creativity by limiting options. With Smash, the opposite is true: they're limiting dominant strategies by rewarding familiarity with all the game's elements. It's not enough to say "I'll play Little Mac because he's the best on Final D." If you aren't prepared for other stages, you won't make it through to the end.

New Tech For A New Era

The Top 16 character representation was a healthy mix of new and old characters, and each was unique (even among ostensibly identical picks).

The characters were:
  • Kirby
  • Captain Falcon
  • Ganondorf
  • Fox
  • Zelda
  • Robin
  • Little Mac
  • Samus
  • Yoshi x 2
  • Mario x 3
  • Rosalina & Luma x 3
The finals were, as statistics would dictate is the most likely outcome, Mario VS Rosalina. Notably missing from this array: Sonic, Duck Hunt, Pikachu, Meta Knight, Sheik, Marth, Link, Olimar, Pit, R.O.B., Villager, Pac-Man... all characters I've heard people call top-tier in past or present. "Top Tier" may be a thing of the past; with so many characters being viable, it will come down to which characters counter the most popular choices, and therefore, who has the bigger roster.

Rosalina & Luma were the grand winners of this tournament, and there were 3 in the top 16 (2 in the top 4!). The next step for you, O Community, is to come up with a counter to the puppet character, which is a new concept in Smash. So, the tech war begins....

This has made me more excited than I anticipated for future grand tournaments of Smash. Mew2King and ZeRo have been spending a lot of time in the game, analysing characters, practising. Armada has declared he wants to be the first world champion of the game. Dabuz, who won this tournament, was a big player in the Brawl scene. This game is taking players from all iterations of Smash, and who knows what will happen as a result?

Until next time...

Stay excited, Star-Shooter.

-mysteriosum(the deranged hermit)

Wednesday 8 October 2014

Reading Smash: Soft Combos vs. True Combos

"AUGH! How did he do that?! I didn't have time to move, even!"
-Noobs everywhere, on combos

Combos are the soul of any fighting game. In more conventional fighting games (looking at you, Street Fighter), combos are discovered and then memorised. You practice that 40% damage combo for weeks before the tournament, and then practice getting that opening. Then the time comes and you just have to go through the motions, if you manage to execute under the pressure. In this sense, it's much like classical music.

Combos in Smash (I believe it was Prog who said this) are more like jazz. You gotta improvise. You know the moves, but you never know what the other player is going to do so you gotta be able to keep up. Players are given more freedom of movement than in normal fighting games, and that makes for unpredictable, beautiful, astounding play.

The Platforming aspect of Smash is real, and it's what separates the Smashes from the MKs. Understanding the physics of platform games, and those of Smash in particular, is tantamount to victory. If you know how all the movement works, you know how your opponent can move, and you can capitalise on that knowledge to make combos.

I'll point out a few terms that you will need to know if you want to get serious about your smash game. This time I'll talk about the game mechanics and techniques for combos specifically. Next time I'll detail mechanics about the attacks that make the combos


  • DI: "Directional Influence"
    • DI means the influence a player has over its character's input when you are incapacitated. If you get punched by DK, you're going to go flying, this much is certain: how far you go, and how high, will alter slightly based on where you hold the control stick. Down throws usually involve slamming the throwee to the ground; they will bounce up, but whether they arc to the right, left, or straight up depends on the direction held by the throwee.
  • Tech: quick recovery (NOT to be confused with Technology)
    • Teching, or Ukemi (a Japanese tumbling technique) are a vital basic technique in Smash. When you get hid hard enough that you can't regain control of your character before you hit a wall, floor, or ceiling, you can hit the Shield button right before landing and quickly get up, offering a few frames of invulnerability, followed by a couple of frames of helplessness.
    • You can tech to the right, left, or in place, offering that versatility which rewards skilled play.
  • Reads: predicting your opponent's DI
    • A soft read is one which involves little risk. You know the 3 ways your opponent can go, so you move or make an attack that covers 2 or all of those possibilities. Typically, this results in sub-optimal punishment (but a successful read is a successful read)
    • A hard read is all-or-nothing: you predict your opponent is going to Tech to the left, so you begin charging a smash, and release just as they're vulnerable.
  • Tech chase: following the tech
    • Tech chase is akin to a soft read, but involves waiting to see what they do and reacting after. It is, of course, possible to jump the gun and tech chase in the wrong direction (which would be seen as a failed hard read)
  • Combos: the bread and butter
    • A True Combo leaves no chance for your opponent to escape them. They are incapacitated, and have few DI or Tech opportunities. In my reckoning, a True Combo can include soft reads, as long as they cover all escape possibilities.
    • A Soft Combo requires hard reads, or other mind games, to work. They are less reliable, but more impressive!

The folks at Smash have been nerfing the True Combo ever since SSB64, preferring to focus on the jazz-like gameplay that the mechanics want to encourage. If you learn how to read your opponents, get in their heads, and stay one step ahead of them, you'll prosper.

Check out my next article, which breaks down attack mechanics and how to know which ones to use when. 

Until then, stay mindful, skilled playa!

-mysteriosum(the deranged hermit)

Sunday 5 October 2014

Super Smash Bros 4: Surface Impressions

I have been awaiting the release of Super Smash Bros 4 (henceforth: SSB4) for a long while. Melee was the only other Smash game I ever owned, and I played it extensively. I have also watched a fair amount of competitive play of all the series' games. I know much about the games, but not as much as I should like about the competitive scene and the techniques used therein.

That's why I'm starting this series of analyses. I love esports and have thought about chronicling one before. This is the perfect opportunity. I will post about my experiences, characters, tournaments, strategies, counter-strategies, and anything else that tickles my fancy.


For now: what's different?

The first thing I want to touch on is how SSB4 is different from Melee or Brawl. Perhaps the most vital aspect is combo potential. Combo potential has been nerfed with each iteration of Smash, for better or for worse.

In SSB64, or OG Smash, according to the Smash Bros Wiki, every character except Samus is capable of performing a combo that will "zero-to-death" an opponent. That doesn't make for a great metagame. You have players playing super cautiously until someone gets hit, at which point the match is over (at a high enough level of play). So, not a very high skill ceiling.

For Melee, the developers decided to speed things up a little. Players were able to move and react much more quickly than in OG Smash, allowing for lightning-fast matches between pros. The fast pace of the characters means you can still have "true combos" while allowing opponents to disrupt soft combos with a quick enough nair, dodge, counter, etc.

A quick little aside on the nature of combos. I consider combos in Smash to be in 2 categories:

  • True Combos mean your hits flow seamlessly from one to the next, allowing no chance for your opponent to break it. This is what most people are thinking of when they say things like "there are no combos in Brawl."
  • Soft Combos mean you must read your opponent for your combo to work. For instance: if Mario throws Marth straight up, the Marth player can control their trajectory somewhat (this is called DI, or Directional Influence). Mario will have to predict which way Marth will choose to go (left, right, or straight up) and attempt to follow up with a fair. If Mario succeeds, the soft combo is a success; otherwise, he can be punished. (See more on Prediction: Hard Read vs. Soft Read)

In Brawl, there are few (if any) True Combos. If you look at the Zero-To-Death article here, you'll see the largest section of any game, but read into it and you'll see that many of these require specific setups, opponents, or an extreme level of skill to execute. Effort was put into lowering the skill ceiling in Brawl: everyone was slower and had longer ending lag. This made the game less competitively viable, since the community revelled in Melee's pace and the challenge wrought by the high skill ceiling. They were also mad about tripping.

Enter SSB4. Impressions (including my own) have been very positive, with Melee pros declaring their support for it, and their intentions to compete. Nintendo is even organising tournaments, which is a welcome step away from their "please no competition" attitude they had for Brawl. It's quicker than Brawl, but not quite as quick as Melee; there are some true combos, but they're rare and tough to pull off (and may require opponents to land on platforms higher than where you hit them from).

A Roster to be Reckoned With

The most exciting thing, for me, is the roster: 48 competitively legal characters (I don't believe Mii fighters are allowed in tournaments), by far the largest cast of the series. The increase is not for nothing, either: each character plays differently, introducing unique mechanics, playstyles, and counter-strategies which the franchise has been wanting. Duck Hunt epitomises this, with an immense camp game and quality smashes which can counter close-quarters fighters that rely on closing gaps (which are the only types of fighters we see in Melee tournaments).

Show me your moves!

I am beyond excited to see what people come up with for the competitive scene. Next week I will post more about the new mechanics and balancing issues the developers have employed.

Stay smashing, super brother.

-mysetriosum(the deranged hermit)


Monday 18 August 2014

Nintendo's real appeal (not nostalgia)

There was a thread on Facebook with some of my friends discussing this article about one lady's rediscovery of Nintendo. It's pretty good, you should check it out. I have my own two cents to add, though. It's not directly related, nor do I disagree with anything she says. It relates specifically to the ubiquitous argument that Nintendo focuses mainly on nostalgia for its success.

If you ask me, the argument that this conjecture is a failure to understand what Nintendo does. They use the same characters, but that's where the nostalgia ends. But even that is dubious: would you ever argue that an adaptation of Shakespeare is trying to use nostalgia to grip its audience? or that the 8th season of a TV show is resorting to nostalgia to keep its audience around?

This guy is one of the best Donkey Kong players in the world, and not because he's nostalgic.


No, Nintendo is about so much more than nostalgia. For me at least, nostalgia plays little to no part in my continued obsession with their stuff. Quite the opposite, in fact. The reason I'll always be with them is because their stuff is always new: new challenges, new skills to develop, new Mario to play.

I'm playing Super Mario 3D World right now, and it's so different from all the other Mario games it doesn't feel nostalgic at all. Mario isn't a series as much as it's a genre: like reggae, or blues. When you listen to one of those styles, you expect certain things: instruments, tempo, style of play, subject matter.... If you're a fan and someone makes a good blues album you'll listen to it. There's no nostalgia, it's a new thing. The notes are different. The people who made it are different. There's a different soul, a different message.

Mario is the same way: we expect certain colours, enemies, and characters, but the notes are all different, and the instruments are evolving. In this case, 3D World is to original generation Mario platformers as Led Zeppelin is to Muddy Waters. You think Nintendo is one big machine with exactly the same parts all the time? The team that made New Super Mario Bros. U is not the same one which made Super Mario 3D World. They're different people, they have different things to say. It's not a story thing either (obv). It's about challenges. The Japanese are all about having skills: bushido is a perfect example. He who is great with a sword will have great glory & honour. Nintendo games are tools to train players, to challenge them, and to make them feel honourable!

So no, I don't play Mario because it reminds me of the good old days. I hate thinking about the past. Hell, I think Mario's a dick who deserves to be imprisoned.

I am a Mario master. That's why I play Mario games.

Sunday 8 June 2014

2D Platforming in Unity using Raycasts - Moving Platforms

Ooh how good it feels to be writing this series again. I have been thinking about this topic for a long time since one reader, one +Jesse LeBlanc, requested it. I have been crazy busy but now I've got some time so MOVING PLATFORMS!

The Goal

Okay, so we want a moving platform. What does that mean, really? Does the platform just move side to side? Up and down? Either or both? In circles? On a track? A series of them going from one side of the screen to the other, spawning ad infinitum?

Before I move on:



I have found the simplest and most useful system for moving a platform is with Nodes. Nodes in this case are [nearly] empty Game Objects whose only purpose is to serve as a target for a moving platform. Much of this is done in Unity's magnificent Inspector. Here's a screenshot of my moving platform and its nodes in-engine:



The Platform has a public Transform[] (array) which you can drag and drop as many things as you want into. Our aim then is to move the platform towards a node, and when it's close enough change the target to the next node.

How is it done? This is my method:



First, I determine my velocity by getting the direction towards the platform (the difference between my position and his, normalized) times my speed (in units per second) times Time.deltaTime (seconds). The resulting product's unit is distance (units) which makes the physics nerd in me happy (u/s * s = u). The next step is checking the distance between the platform's position and the node's position. If it's less than or equal to my speed, I make sure that this frame I'm going to move no more than that distance (Vector2.ClampMagnitude). Then I set my current node to the next node. What is NextNode? It's a Property I define here:



Okay, so your platform moves. What now?

I did two things beyond make a platform move between nodes. First, I made the platform push the player if the platform is moving side to side. Second, I made the platform carry the player around when you're standing on it. I'll explain them in the opposite order, though.

Ride that platform

Once I figured out how to do this, it was the simplest part of the whole procedure. The most important thing I realised is that the platform can't do this alone. It needs the player to store some information: in this case, whether the player is on top of the platform.

Since we already have a method of detecting what's underneath the player, I'm really just going to plug some code into that part of my player's gravity handling section.



If I connect with the ground, I use Unity's GetComponent function to see if it's a moving platform, then assign my variable myMovingPlatform to that. It's important to set the Moving Platform variable to null if you're not grounded! Later, the platform will ask the player if it's the platform the player is on, using this code:



...and that's it! Your player should ride the platform now. But our task is only half done. Now comes the arduous task of checking if the platform intersects with the player.

DISCLAIMER: This method is not very optimal, and if you have a bajillion moving platforms in your scene may eventually slow it down. If you want to optimise this code I suggest adding some system which checks what platforms are close enough to perform this test.

I find Unity's Rect (rectangle) class quite useful, but there is one function glaringly missing from its base functionality. It's something to check if two Rects overlap. I found it on the internet, though, after a minute of Googling. In addition, the BoxCollider2D class is sadly missing an inherent Rect variable which tells you the bounds of an object's collider. Here are my utility functions I'm using for this section:



Now that I have this, all I have to do is put the platform's Rect and the player's Rect into this function, and see if it returns True:



The next step is to set the player's position to flush with the platform:



And there you have it! Your platform should move smoothly.

Above and Beyond
There are lots of things moving platforms have done in different games. Just to name a few:

  • platforms that don't push you and that the player can walk right through;
  • keeping the momentum of a platform you're on and modifying the player's jump velocity with it;
  • platforms that start when you land on them;
  • platforms that disappear after a certain amount of time when you land on them;
  • or reappear after this last;
  • platforms that move any object that lands on it...
The list is endless. This is just the beginning. I hope you are inspired to put a fun new type of platform in your game!

Thanks for reading.
Stay moving, jumping dinosaur.

-mysteriosum(the deranged hermit)




Thursday 17 April 2014

Recess Race: Updates coming soon!

Recess Race development is coming along. We released the first open beta at the start of the month, and it has revealed a few (big) flaws the game currently has. We are happy to say we know exactly what they are and how to fix them.

One of the big issues we have with the game is conveyance. Specifically, the method I tried to use to convey the controls has not been working, so (a) new one(s) must be implemented. For now, know this: press Z to jump and X to use items! These will also be customisable in the next version.

 Another feature we're adding is letter grading for each level. Depending on your performance (placement, style, garbage collected), you'll receive a letter grade from F to S+. F for FUN!

So, keep update so as not to miss a thing! Prove this bully wrong!



Thanks for reading. Until next time...

Stay powerful, lithe hunter.
-mysteriosum(the deranged hermit)

Thursday 3 April 2014

Recess Race: Get ready...

A little while ago I wrote about how awesome having a team is. Having more talented, dedicated people divides production times immensely. Well, now we're releasing something, and it's because of those same people that it was possible!


Temp8 is the company of my buddy Will Farr, who is the artist for the game I'm working on, Recess Race. Hopefully you've both heard of it! He's been awesome, and so has our programmer, Richard Rail, who developed an entire ai for the bullies of Recess Race (calculating how to get perfectly from one end of the level to the other - not too shabby!).

I will be updating more, soon, with a build of the game! We're going into open beta, and we really need your help. We also have a survey that we hope you'll take the time to fill. It will help us figure out what to prioritize in the development in the game. Though the game is very close to my heart, I would like to get feedback from you guys to know what aspects of the game I should focus on in the spilling of my guts!

Thanks for reading. You guys are awesome.

Keep fighting, noble soldier.

-mysteriosum(the deranged hermit)

Saturday 15 March 2014

Level Design and Flow

So Recess Race is coming along nicely, and I couldn't be happier about that.

What I am working on most right now is level design. I've had formal training in level design, but my experience in this field is still only a couple of years old. There's a lot I have to learn, and I learned something recently that I would like to share.

First, if you don't know about Flow - specifically the flow state as described by Mihaly Csikszentmihalyi - you may want to read up on it a little. If not, a whole lot. Like read the book of the same name.

tl;dr: the flow state is where you are so focused on a task or activity that you lose track of time, yourself, and everything unrelated to the task. Ever been so involved with something that when you looked at the clock you realise you should have left for work ten minutes ago? It's because you were in a flow state.

Video games aim to get the player into a flow state. It's how they hold your attention and get you addicted. Because the flow state is very addictive and a game that can reliably produce it is valuable to an individual.

One of my best friends was playing a level last night, and brought to my attention that certain specific spots were flow-breaking. I was defensive at first (as we always are... pff, artists, amirite?). Then I realised that was just about the worst thing my level could be. It should be catalytic to flow in as many ways as possible.

What breaks the flow?

This is one of the specific points my friend pointed out:



The black line is the jump arc of the character. The red box is the character's collision box. As you can see, jumping from that point, the player will collide with the side of that platform. I don't have ledge grabs in Recess Race; this means the player will have a hard time getting up to the top platform without being conscious of this. They will have to hold the jump button to get enough height to clear the platform, and also hold left for enough time to get on top of it - but not for too long, or they won't have time to turn around, and they'll fall off the other side.

This problem makes the player feel there's something wrong with the physics or the level. That's the problem right there: if the player knows it's their fault that's fine, they'll be willing (even excited) to try again. If they feel it's the level/game's fault, they'll get frustrated and become more likely to ragequit.

RULE: The player must know exactly why they failed, and must feel it's their own fault. Otherwise the flow will be broken and they will want to quit.

How difficult is too difficult?


Difficulty is a problem I've always had. I, like many young designers, tend to crank the difficulty when something is too easy for me. This is deadly. If something is difficult for you, who designed the level and have been working with the mechanics of the game for months, that means it will be nearly impossible for a player picking it up for the first time.

The philosophy I've adopted for Recess Race has been: easy to play, hard to master. This is something Nintendo has done best for decades, and it's present in every game they release. It's particularly important to inducing a flow state. Consider this flow chart (pun intended):



A condensed version of the theory behind this: when the challenges presented to you are appropriate to your skill level, you will be more likely to be in a flow state. If a challenge is too difficult you'll get anxious, and if it's too easy you'll get bored. You'll also notice there's some wiggle room here: that's because sometimes a challenge is just a bit too hard for you, and knowing "Oh man I can totally make this if I try for a few minutes" is an awesome feeling. Then you beat the challenge and your skills have improved, meaning challenges of that difficulty are no longer as daunting. And you climb the "Flow channel".

So, how does Nintendo do it? I'll make a list.

1) Simple or recognisable gameplay: everyone knows how to play a 2D Mario game, and if they don't then they're likely playing with someone who does and they'll learn. They've never necessitated players to learn more than 2 buttons: Jump and Run; A and B. This means that players can feel comfortable that they'll never have to learn another button, which is reassuring.

2) Secrets. Secrets everywhere: discovering a secret is fun. It's so satisfying! In pretty much every circumstance. Because there's lots of different kinds of secrets. To name a few:

  • Hidden mechanics or abilities: Super Mario 3D Land/World has a bunch of jump types. Crouch-jump, long jump, cartwheel jump (running in one direction, snap to the other direction and jump, gives you a higher jump than usual). None of them necessary to get to the end boss, but each super fun to discover/experiment with.
  • Collectibles: again, in Super Mario 3D Land, each level contains 3 star coins that are usually difficult to find or present an optional challenge. These are great because they can be as hard to get as the designers want, because they're not necessary to complete the game. The player knows there's 3 in each level, so they might not be a secret per se, but they are often well hidden which makes them nonetheless fun to find.
  • Secret collectibles: in Braid, there is a type of collectible that I didn't even know about after having (in my view) 100%'d the game. Someone told me they were there... and I had 20 more hours of gameplay in front of me. Sadly, this is an area Nintendo is not wont to delve into. They have in the past, but not for decades.
3) Difficulty settings: done wrong, difficulty settings are stupid and useless. However, done right, they can feel organic, empowering and enhance every user's experience. The Legend of Zelda: The Wind Waker HD is a great example. Right off the bat, you have the option of playing the game in Hero Mode. Wait, what? Awesome! I want to be a hero! ...I take double damage? And there are NO RECOVERY HEARTS?! Oh dear... well, here goes nothing. This difficulty setting was a fantastic move from Nintendo: they know a lot of people have played the game before, so they don't want those guys to get bored with the same challenges, and this is super easy to implement. It also shifts the player's focus considerably: I had to keep track of every fairy fountain and constantly go back to visit my grandma to get soup. Going into a Gauntlet room unprepared was deadly (but super fun, I'd recommend it :D ).

I feel strongly about difficulty settings and some day I'll do an article all on those. Point out some shining examples.

So how does this apply to Level Design?


Most of the points in the previous points are actually about game design. I'll list some things I think are important for your level to be fun from beginning to end.

Difficulty curve: the most important. If you aren't conscious of how difficult your level is at each point, it will be impossible to shape an enjoyable experience for the player. Your difficulty curve should actually look a lot like the wavy line of the Flow Channel chart above. To make your own difficulty curve, look at each challenge in your level and rate it on a level from 1-10. Then look at the figures: do they generally increase as the level goes on? Is there ever a jump of 3 or more units (that's generally bad)? Are there 'break' spots where the difficulty decreases after a particularly hard spot?

Placing ingredients: when I say ingredients, I mean anything in the level that the player interacts with. It can be a special type of platform, or an enemy, or a pick-up, or even a specific platform formation that requires a specific skill. Always introduce these on their own before placing them in combination with other ingredients. 


Here, the goomba is entirely on its own. You will either figure out a) it kills you, b) you can jump on it, or c) that you can jump over it and it's ok. Later on, you'll see it between two pipes so it patrols between them, or in combination with other types of enemies, or even just with more goombas. The challenge is much greater in combinations like these, so use them wisely. They can also be the most interesting and exciting moments for a player.

Give the player something to look forward to: this is difficult to explain, let alone pull off. It involves giving the player some kind of hook: something they know is going to come back later, or a task they need to work at for the whole level, or a big looming structure they hope they'll be able to visit later on. Some sort of mystery to keep them guessing; to give them a reason to keep playing. In Recess Race, it's the desire to finish well; to beat the other racers (bullies) who will beat you up/call you names if you get too close. You want to prove your worth! And the only way I let the player do that is by being awesome at the game. So the plan is to make the player feel as awesome as possible for as long as possible, and that means keeping them in a flow state :)

Well, that will be all for now. I hope you enjoyed these musings, and implement them in your game (if that's what you do!).

Until next time,
Keep flowing, super surfer.

-mysteriosum(the deranged hermit)

Thursday 6 March 2014

Recess Race Announced!

This week has seen a big step for the deranged hermit and his friends. It is my pleasure to announce our game, Recess Race!



Many Hands Make Light Work


I've been working on Recess Race for months (as some of you know...). I've done several prototypes, and gone through many design transitions as a result. But, when I felt I had the final design down, Serendipity played her part and a team fell into my lap! I am working with Will from Temp8 and Richard-Bananas now, and after one month of production, we're already nearly done the alpha.

It is wonderful to work with other people, especially if those people are fun, intelligent, hard-working and like-minded. I recommend, to any of you lone indies reading this blog, find someone to work with whose skills differ from your own, but who shares similar goals. And trust fate! If you happen to meet someone who vaguely fits this description, do not hesitate! Pounce upon them and never let go.

Concept art: in-game "screenshot" mock-up

So... What IS Recess Race?


Recess Race is a 2D platformer racing game. It takes place at an elementary school, where the administration has organised a race event with the ulterior motive of cleaning up the yard. The participating children must race to the finish, all the while picking up as much trash as possible. But, the other racers are bullies! If you get too close, they'll beat you up or call you names.

Recess Race is a game that comes from the very depths of my soul. It has spawned from a tortured elementary school experience, where I was bullied more than anyone enrolled (in my head at least). I had to cope somehow, and that how was video games (and my awesome family). No matter how badly people treated me, I knew I could go home at the end of the day and play a video game. I could have an impact! I could use my skills to do some good. Whether that 'good' was rescuing a princess, getting food back from the malicious Dedede, or smiting the Maverick leader Sigma, I was responsible.

In-game screenshot! Pinky is this alternate universe's Kirby


I bring elements of these games into Recess Race. Mario Kart-style power ups include: booger armour that give you a Megaman X wall jump; a dapper tail coat which allows you to glide as in many Mario games; and a magic hat that allows you to float-jump like Kirby.

Next step: pre-alpha web release!


In the next week we're going to have a playable pre-alpha version on our website. If you would like to keep abreast of our activity, you may follow me on Twitter: @derangedhermits, or find Recess Race on Facebook here.

More news forthcoming! 

Thanks for reading. Until next time...
Stay strong, stalwart stewards.

-mysteriosum(the deranged hermit)

Monday 3 March 2014

2D Platformer Collision Detection with Raycasts: One-Sided Platforms & LayerMasks

Something that happened magically while developing this system was one-sided platforms. That is, platforms that you can go through easily on one side, but from the other side it doesn't work, it's a wall.

I stumbled upon an elegant solution I love very much, and I will now share it with you!

These platforms are rad


Lots of platforms in Kirby can be accessed from underneath


So you may be asking yourself, "Why do I want these platforms?" The answer is usually: they're rad (sometimes, it's: you don't). They can add a lot of depth to your game. They give options during level design, opening up puzzles, dexterity challenges, and other such intricacies.

OK that's enough talking let's code.

Layermasks & Bitwise Operations


Layermasks are integers that inform a Raycast what to pay attention to. They are key. Once you start using them, you'll never go back and you'll be very glad you have this skill in your pocket.

What is a Bitwise operation? In this case, we'll be dealing with a bit shift. This requires a little bit of binary, so if you know all this stuff you can skip right to the line of code where the binary operation is.

Binary is a counting system exactly like our normal one (Decimal), but instead of counting all the way to 9 before reaching 10, we count to... 1. 0, 1, 10, 11, 100 are 0, 1, 2, 3, 4, respectively.

In any number system, the leftmost digit (or bit in binary) refers to how many of the highest exponent of the base are in the total value. In Decimal, 854 is literally 8 * 10^2 + 5 * 10^1 + 4 * 10^0. A 0 exponent always gives you 1 no matter what you're putting to it.

So, 11011001 is:
1 * 2^7 + 1 * 2^6 + 0 * 2^5 + 1 * 2^4 + 1 * 2^3 + 0 * 2^2 + 0 * 2^1 + 1 * 2^0
which simplifies to
2^7 + 2^6 + 2^4 + 2^3 + 2^0
which simplifies to
217

For Layermasks, we will go from 2 ^ 0 to 2 ^ 31. This is because we have 32 different layers in unity, each of which is assigned an integer from 0 to 31. If you say Layermask.NameToLayer("normalCollisions") in my code it will return 31.

So, the Layermask is always a 32 bit integer. But, what matters in a Layermask is not the value in Decimal, but the status of each bit. Each  Let's say your Layermask look like this:
1000 0000
0000 0000
0000 0000
0000 0000
The value is 1, but that doesn't matter. In this case, the Layermask tells the Raycast only to pay attention to 1 layer, Layer 0. If it looked like this:
1000 0000
0000 0000
0000 0000
0000 0001
then it would look at the first and the last layer. Its value is 2147483649 but again, that doesn't matter.

So how do we make a number look like this? Luckily you don't have to spell out your own binary numbers and convert them to Decimal. You just have to do a bit shift. A bit shift looks like this:

int collisionLayer = 1 << 31;

This means you're shifting a 1 to the 31st position in a binary sense. But that's just one layer. What if we want to do more than one layer? Easy.

int collisionLayerPlus = 1 << 31 | 1 << 30 | 1 << 0;

The | character indicates we're shifting more than one bit in an integer. Now the Layermask will look for collisions in the 31st, 30th and 0th layers. For fun, this is what the bit will look like:

1100 0000
0000 0000
0000 0000
0000 0001

If you're having trouble with any of this, please google Bitwise operations, or bit shifting, or even just layer masks and someone else will give you a better explanation (because there's lots out there :).

What I did was set up a class with static variables that contain these bitwise operations so I don't have to keep doing them in my code. This is what it looks like.







That's it! That's all it is. Now we use it elsewhere.

...What? You want an explanation of this too? OK fine...

Well first you'll notice the class doesn't inherit from MonoBehaviour. That's because it doesn't need to! I'm not going to put it on an object - in fact, I'm never even going to instantiate one. All it needs is those static ints that can be accessed from anywhere, at any time. I'll do that later.

The other fun thing in here is the static constructor. I don't fully understand how a static constructor works, but I guess it probably calls that when it needs to to give values to the variables I declare above. I can't use functions like Layermask.NameToLayer in a variable declaration like that so I had to use a static constructor.

Last, softBottom is what I call the kind of platform you can jump up through. softTop is what I call platforms you can fall through but can't jump up through. They're evil. And fun! :D

Now let's use the darn things!


Let's start with platforms that you don't hit your head on. Ones you can jump through from underneath but will then land on stably. Find the code where you look for things to bump your head on.

....we haven't done that, have we? Oh...

Well, we'll do it at the same time! It's related.

Here's the final code.



You'll notice it looks a lot like our other directional checkings. That's because it is pretty much the same.

There are two main points of interest here:



Here is where the character hits his or her head. If a platform is there, teleport to the point of contact, and set your velocity to 0. The other option (a la Mario) is to have a little rebound. I like to use a fraction of the upward velocity you were moving at, assigning it as a negative velocity.

And...



This is where we use the Raylayers class. It dictates what I'm going to detect with my up-layers. In this case, I will only bump my head on things in the NormalCollisions or SoftTop layers.

Now all you have to do is assign a platform the SoftBottom layer and you won't hit your head on it!

It's really that simple. A few lines of code and a lot of functionality. It's just as easy to add the SoftTop platforms (just add the right layermask) and to add one-way sideways platforms (which are also quite interesting).

I know my explanations in this post may be a little hasty, so if you have any questions please feel free to leave them in the comments and I'll get back to you as soon as I can. This was supposed to be a really short tutorial but it ended up... not being. ^_^

Thanks for reading!

Until next time...
Stay smart, little mite.

-mysteriosum(the deranged hermit)

Thursday 13 February 2014

2D Physics in Unity with Raycasts: Slopes

Hello, faithful readers!

I have promised this update for a while, but have failed to deliver on account of being busy. I have done lots of acting in the last couple of weeks, and it has been great fun, but I'm starting to be sick of people and want to hole myself up with my squirrels for a while! Doing this tutorial (and more in the future) will help me forget other people exist for a while.

I actually did the coding for this within days of receiving the request, so this is far overdue.

The last post I did talked about jumping, and if you missed that you may want to look at it, though it's not necessary for this tutorial. What is necessary, though, is a basic understanding of the system: how I deal with gravity, and how I deal with lateral movement. Without having read these I'm afraid you'll be lost =)

Now, On To The Good Stuff

The first thing I did while trying to develop this system was put a slope in my scene and try it out. Turns out it kind of works already! Because of the way it's set up (the downward rays checking from the middle of the character), it teleports you to the point of contact in any case, so whether going up or down you'll still be in line with the slope in some respect.

It's far from perfect though. At first glance:
  • the character stops every time he reaches something like his max speed, because the side-check rays find the slope and think it's a wall;
  • the system only works when going up slopes of more than 90º (as in running to the left); 5+º (running to the right) slopes have you sink into them most of the way and cause all sorts of bugs;
  • we move the same speed as we would on a flat surface (which may or may not be desired); and
  • we jump straight up (again, we might want this but we'd like to have the option).
So that's just a couple of problems but they're still going to take a lot of work to sort. We're going to need some inspiration...

Case Studies

An important thing to do when tackling this sort of problem is ask yourself, "what have other people done?"

Super Mario World

For the first problem, I'm going to call on Super Mario World for the SNES.

What I'm going to for this is calculate the angle of the slope we're standing on. I will then use that  For reference, I'm going to link another guy, Jdaster64, who did an in-depth analysis of this stuff. Astounding.


From this, we see there are 4 angles of slope in Super Mario World: 11º, 23º, 45º and 67º. For 11º, there's no change for anything. So that tells us: we should consider implementing some threshold angles. For instance:
  • At 23º we reduce the player's max speed going uphill, and increase it going down;
  • At 45º the player starts moving automatically down the hill;
  • At 67º the player will have a very hard time controlling movement, and will even fall off the platform should they move with the slope enough.
We don't have to choose these exact angles, but we should set it up so that no matter the angle, we react accordingly. This means we're doing a general system, not a specific one - which may be the wrong thing to do, but that's what programming is all about!

Guacamelee

Guacamelee takes a much more laissez-faire approach to slopes, which is appropriate for its genre as Metroidvania (which always includes lots of combat). Ease of control is of paramount importance in this genre, so introducing hidden mechanics like those in SMW is not practical.

Guacamelee only has a couple of slope values, but in general it's a binary issue: either you can walk on the slope, or you can't. If you can walk on the slope you move at the same X speed as normal and jump straight up.

Frankly, this is the modern trend. Most platformers choose to doff the slope physics given to us by arguably Nintendo's greatest platformer. That's fine! Things are moving forward! With that in mind I won't go into how to bring SMW style slope mechanics to our projects just yet. I will focus on the most important problems.

Disclaimer: since the last tutorial on lateral movement, I changed this whole system to Unity's 2D physics. I did this because it's much easier to achieve a slanted collision with the 2D Polygon Collider than it is to make a 3D mesh in Blender or something and import it. If you can manage that last part go ahead; the system is almost identical.

What's Different in Physics2D?

Not much, really. The biggest thing is the Raycast method. Instead of returning a boolean, it returns a value directly to a RaycastHit2D object (making this a required step instead of an optional one). This is okay since we use RaycastHits anyway and it's just as easy to check if a RaycastHit2D hits something than it is to check a boolean.

Here's what the code now looks like:



Each Vector3 has been replaced with Vector2, we now test to see if (hitInfo.fraction > 0) instead of if (connected). hitInfo no longer has a .distance variable, so we have to make due with the hitInfo.fraction they give us. Other than those, pretty much the same thing.

Fix: Collision Problem (slopes aren't walls, silly)

The most immediate concern for us is the fact that we collide with slopes as if they're walls. I noticed this even on the slightest of curves, so it's time to mess with our lateral movement scripts a little.

What do we need to change?

The problem with the code as it stands is that the moment one of the rays hits something, the system goes "OH YEAH I got something it's a wall f'sho don't worry about it I got dis." This is not necessarily the case! I'll need to check how many rays hit, and retrieve the normal of the surface I hit. After all, if the slope is steep, we might hit the wall with multiple rays. This will also give us the tools to apply this to the downward rays.

This is what the new version of my Raycast section for lateral movement looks like:

The first thing you may notice reading from the top is that I've removed the +/- margin from the start and end points. This means I'll be checking right from the bottom to the very top of my character's collider:




The whole reason I had that margin to begin with was so that I wouldn't collide against the floor as if it were a wall. Now that I'm going to be calculating the angle between multiple rays' connection points, this is no longer relevant.

You'll also notice that instead of just using one RaycastHit2D, I'm using an array of them. This way I can reference any or all of them in or out of my for() loop.

When One Ray Just Isn't Enough

Now, first: how do we know we've connected with more than one ray? With a little variable I like to call lastFraction.




lastFraction does what it suggests: stores the value 'fraction' of the previous connecting ray's RaycastHit2D object. If its value is 0, that means no other ray has connected thus far, and we won't bother checking an angle or anything. We will simply store the current fraction in lastFraction.

Disclaimer: As it is, lastFraction is within the if(hitInfos[i].fraction > 0) clause, which means it doesn't get reset after a successful connection. As a result, any two successful rays will trigger a check. If you want to make it so that only 2 consecutive rays trigger it, put the last line of this block of code as the last note of your for () loop.

What's Your Angle?

To calculate the angle between two points, we'll use Vector2.Angle(). At first I tried just plugging both points into this and using that but that's not how Vector2.Angle() works. No, for Vector2.Angle, you pretty much always want the first argument to be Vector2.right, which is (1,0), or 0º. Then give it the difference between the two points, which will give you the delta of that Vector:



Now we see if it's within the proper range of what we want. In this case, I've set angleLeeway to 5, meaning if angle is less than 5 (or more than -5), we'll ignore it because it's not a wall. Of course, you may want to tell the player he can't climb up an 85º wall, so you can change angleLeeway as you see fit.

That's it for that! Your player should no longer think slopes are walls.

Fix: Sink Problem (The One Ray To Rule Them All)

The other major problem is that the player object seems to sink into the slope. In fact, the script will always use the first ray that connects as the reference for where it should be along the y axis. In this case, it's ray on the far left, so that's why when travelling right, he'll 'sink' into the slope.

So, to solve this problem, I've once again conjured Guacamelee as my reference. Here's how much Juan cares about slopes:
Why yes, this costume does imply that I 100%'d the game! Thanks for noticing! ^_^
Wow, Juan. Your one foot is barely touching the floor. Very suave. Realistic... oh well, we can't all be perfect!

This is actually a very sensible and intuitive solution. As a player, you might not even notice it without having it pointed out! It's certainly much less weird than if his foot were inside the floor. This also allows the level designer to put slopes of any angle and it doesn't matter a bit.

The Short Stick

Achieving this is surprisingly simple, from what we have so far. The system shoots multiple rays down from the central X axis of the player. All you have to do is determine which of those rays is the shortest, and use that in your calculations!

Here's what the final code looks like for this:



The first thing you'll notice if you're clever is that I'm once more using an array of RaycastHit2D. This is important for this problem, but we'll also use it later if we're going to implement slide-down-the-slope or jump-at-an-angle features down the line.

For Loop, For Loop on the Wall, Who's the Shortest of Them All?

To find the shortest ray, all you have to do is declare the variable smallest fraction and assign it later on.




We start it at Mathf.Infinity because everything is smaller than infinity :)

Also declare indexUsed, which will tell us what position of our RaycastHit2D array we want to reference when we finally give the command to hit the ground.

Then we want to assign these variables. Again, it's trivial:








Any fraction smaller than the smallestFraction value will set a new smallestFraction, and with it, the indexUsed variable. We use the index after the for() loop if connected is true, and go about our business as usual.



Since the system already teleports you to where the ray hit, there's no need to change anything else!

That's it for now...

I hope this helped those of you who are following me and have wanted to use slopes in your games. This system makes it so you can have slopes of any angle, with a cutoff angle where they start to be considered walls.

Next time I will go into more complex nuances of slopes, as described in the SMW breakdown. I don't think it'll be super complicated but it will be worth doing! If you have any questions at all, feel free to leave a comment. I will answer as soon as I can!

Thanks for reading.

Stay bright, burning star!

-mysteriosum(the deranged hermit)

Tuesday 28 January 2014

2D Platforming Physics With Raycasts: Jumping

Hello, faithful reader(s)!

It occurs to me that I didn't actually explain how I do the jumping in my system. It's simple, but there's a couple of nuances that should be discussed.

Basic Version

Jumping in Unity can be as simple as:

void Update (){
     if (grounded && Input.GetButtonDown("Jump"){
          velocity = new Vector2(velocity.x, impulse);
     }
}

This works, but there's a hidden mechanic in most of the platformers you play that you might not realise: you can actually press the jump button right before you land, and jump immediately as you hit the ground. If this feature is absent, your game will feel glitchy. The player expects this leeway. This means we're going to have to record when, not just whether,  the jump button is pressed.

Disclaimer: Unity has a function, Input.GetButtonDown(). I don't trust it - I find sometimes it just doesn't register. So I work around it with Input.GetButton, which returns true every frame the button is pressed.

Better version

My code looks something like this:

void Update (){
     bool input = Input.GetButton("Jump");
     if (input && !lastInput){
          jumpPressedTime = Time.time;
     }
     else if (!input){
          jumpPressedTime = 0;
     }

     if (grounded && Time.time - jumpPressedTime < jumpPressLeeway){
          velocity = new Vector2(velocity.x, impulse);
          jumpPressedTime = 0;
     }

     lastInput = input;
}

So a couple of things at work here. First, the time we pressed the jump button is recorded only if the previous frame, it wasn't pressed. Every frame we're grounded, we'll test the current time against the pressed jump time, to see if it's less than our jumpPressedLeeway variable (which is usually like 0.1). Then we jump if that's true (if we're grounded).

Setting the lastInput at the end is essential to check if this is the 'JumpDown' frame.

Disclaimer: I haven't tested this code. How fun! Check it, see if it works. Let me know what's wrong!

You can also add other conditions to the jump check. If you have a double jump, your condition may want to read:

if ((grounded || !hasDoubleJumped) && Time.time - jumpPressedTime < jumpPressedLeeway)

This way, grounded and not having double jumped will both satisfy the jump condition - but you'll also have to add:

     if (!grounded)
          hasDoubleJumped = true;

Then when you land, set it to false again.


That's it for now. Soon, I will go into doing slopes with this kind of system. I will also discuss jumping in a little more detail as it pertains to the system of checking downward for stuff. You'll see.

Thanks for reading!

Until next time: stay real, natural numbers.
-mysteriosum(the deranged hermit)

Monday 20 January 2014

2D Platformer Collision Detection with Raycasts, Part 2: Lateral Movement

This is part 2 of a series; click here for part one.

Hello again, faithful squirrels - err, readers. This is the second post in a series wherein I discuss my home-brewed 2D platformer physics in Unity3D. Last time I talked about the basics of Raycasts, then applied them to movement in one direction (gravity). This time I'll be talking about applying my Raycasting method to lateral movement. The process, as you may have guessed, is the same for lateral movement, so it won't be as long to explain as gravity since we're already familiar with the method. I'll then explain jumping, which is also super easy (1-5 lines of code, tops).

DISCLAIMER: I discovered after writing the last article that Unity implemented native 2D physics and collision detection in a version of Unity I hadn't updated to yet. I've implemented my whole thing with 2D box colliders and 2D Raycasts, but it works the same either way. So I'm going to continue this tutorial with 3D box colliders which will be handy for anyone doing a 2.5D platformer, or for other fun experimentations.

Recap

To implement gravity and collision detection, I use the following steps:


  1. Set up variables, like gravity and max fall speed, and gather information about the GameObject;
  2. Apply acceleration to my movement: in this case, downward acceleration due to gravity;
  3. Determine whether it makes sense for me to check below me for collisions (am I on the ground? or if not, am I falling?);
  4. Determine where the rays I'm casting will begin (a few of them in a line);
  5. Determine the length of all rays (they'll be the same, and check as far as my downward velocity);
  6. Cast each ray and ask if it hit anything;
  7. Use the result (if I'm on the ground and I didn't hit something, now I'm falling, and vice versa).
Here's what the rays would look like if we drew them:


For checking above, the lines will look identical but face up, and for lateral movement they will start along a vertical cross-section and reach out to the side.

Let's Boogie

Now let's take a look at the system applied to lateral movement. Here's what the code looks like:




There are lots of similarities but also some key differences. Let's go through them.




Input

Since we're now responding to the player's input, we have to get it from somewhere. My input code looks like this:




and that's it! Unity's inputs are generally set up well enough for this purpose, but if you want to play with it then go to Edit > Project Settings > Input to look at the data structure.

One thing to note about this is I use Input.GetAxisRaw instead of Input.GetAxis. The difference between the two is when it comes to keyboard input. All Input.Axis functions return a float between -1 and 1. When reading input from a keyboard, Input.GetAxis moves slowly toward the limit rather than snapping to it (which GetAxisRaw does). For example, if I want to move the character left using the keyboard, I'll press A or the left arrow. The first frame, using Input.GetAxis, will return something like -0.15. Then each frame it will go up by that amount until it caps at -1. This isn't what we want here, since we'll be multiplying things by our input. So, we use GetAxisRaw, which will only ever return -1, 0, or 1 when using a keyboard.

Applying movement

This was simpler with Gravity. We just checked if the player was grounded, and if they weren't, we subtracted from their vertical velocity (capping at a maximum fall speed). This is what I do to apply lateral movement.












I like to work with local variables - in this case newVelocityX. In C#, there's no way to alter one component of a Vector directly (in Javascript you could write "velocity.x += acceleration * input").  So, it's simpler to work with a new variable.

We're going to deal with an input of 0 differently, since that's deceleration and not an acceleration. Add acceleration * horizontalAxis to newVelocityX, then make sure it's not gone past the maximum speed. The principle is similar for deceleration.

Raycasts

This operation is nearly identical to that of gravity, with one exception: the direction of the rays is determined by our velocity. See here:



If we are going left, we check left, otherwise we check right. If there's no input we don't check at all. If the player holds a direction towards the wall, we know it connects on that side. There is the unfortunate side effect of doing a Translate of 0 every frame this happens but the pros outweigh the cons here. If I want to code Megaman's wall jump for example, I just have to set a variable like "bool wallHanging" to true if one of my rays connects. Then I can use the input and invert it to determine the direction he'll be jumping away from the wall (or hitInfo.normal for that matter).

Only the beginning

From here, the possibilities are endless. Try something fancy! For starters I suggest figuring out how to check above the character as it's jumping, to react to ceilings using this method.

I never even got into layer masks in this explanation. A layer mask will let you pick and choose what objects you want to detect. So if you want to make a platform you can jump through from underneath, just tell the rays you send up not to detect those platforms. Then when you're falling the downward ray will find it and you'll be golden.

Using this method you can implement: moving platforms; slanted surfaces; icy surfaces or other movement detriments; or a whole thwack of other things I can't think of right now.

I am really enjoying doing this sort of work, and I believe my next tutorial will be about bouncing off walls (like for an astronaut in a pinball machine, let's say).

Thank you so much for reading. Until next time, keep moving, kinetic beings!

-mysteriosum, the deranged hermit.

Saturday 4 January 2014

2D Platformer Collision Detection with Raycasts, Part 1: Gravity

Hello, squirrelfriends! Today I'll be writing about one of the things I've done in Unity: specifically, coding my own collision detection using certain aspects of Unity's physics, and simple maths & physics (for Recess Race!).

Why not just use Unity's physics?

Good question! The short answer is Unity's physics are meant for 3D movement, and they're great for that. Their basic character controller uses a capsule collider. It's pretty essential for 3D, but it doesn't work for classic SNES era 16 bit platformer tropes.

Consider this image:
Wile E. Coyote wishes he could do this

Now, that's not realistic. You can't stand like that! but it makes sense when you think about the strictly-rectangular collision detection they had at the time. It was a hardware/software restriction but they ran with it and made the restriction into an asset. Here's the same image with an approximation of his hit box:

He benefits from intangible toes, forehead, and right fist

The tiny part of the box touching the collision tiles supports him. Walk any further and you fall off. This feels very fair for the player: he's allowed to put his centre of gravity over a pit, but he can't support himself with just his toes. A little 'cheating' is enough. It also allows for what feels like really close calls - if an enemy swoops down and skims your helmet, but you don't get hurt, it creates a "WOW that was close" moment, which is fantastic.

Consider the same scene with a capsule collider now:

Paint capsules!

The only point that will touch the floor on a capsule is the bottom point. Since it's not touching anything, you'll fall. Then the curve of the capsule hits the corner of the tile, and you slide away from the wall and you fall. It's a different effect, and not one I'm going for in Recess Race,

Build it from the ground up (using Unity's construction materials and power tools)

So it's clear we can't use the packaged Unity character controller. It is impossible to separate from the capsule collider. So we'll have to build our own, using a box collider!

Aside: Unity Colliders, Events, and Rigidbodies

When you make a new script in Unity, it gives you the Start() and Update() functions built in. These are events that are called when Unity feels like it. Among these are the OnCollisionEnter() and OnTriggerEnter() functions. Their utility is paramount, but there are some issues. Both of them require having a Rigidbody class on one of your objects. It makes sense, because if it didn't discriminate it would be checking every collider against every collider every frame and that would take aeons.

Solution: put a Rigidbody (Component > Physics > Rigidbody) on your controller, uncheck 'Use gravity', open the Constraints class and check all of the boxes. This way we can have it use the Collision events and also control its movements at all times.

This is what your Rigidbody component should look like

Intro to Raycasts

If you're familiar as heck with Raycasts, a "Ray-man" if you will, you can skip this section.

Setup

The Raycast is a versatile tool in Unity, and it's surprisingly cheap. You can probably do hundreds of raycasts per frame and it won't do much to slow down your processing speed (but, the fewer the better).

A basic raycast in code looks like this:



This bit of code shoots a ray straight up from the object's pivot (transform.location) and tells you if there's anything above you (Raycast always returns a boolean). Not super useful on its own, but that's just the beginning. There are multiple ways we can call the Physics.Raycast function (12 overloads!). Let's add a couple more to add some more utility:


Here, we've added 2 new arguments to the Raycast function: a float, 'distance', and a RaycastHit. The float just tells the engine how far to check. In this instance, it will only check as far as I'm going to move this frame, which is very useful. It will tell me if I'm going to hit the ceiling! (This code is a little dubious and I'll explain why later).

The other addition is the RaycastHit, which uses the 'out' keyword next to its argument because it receives information (is assigned values) from the function if the Raycast returns true. This is supremely useful, as it tells you exactly how far the ray travelled before it connected, the normal of the surface it connected with, as well as a reference to the collider it hit. We will be using this to great effect later on.

The last thing we'll add to the Raycast function is the Layer mask. This tells the system to look for (or ignore) specific Layers. In Unity, you can give every object a different layer (up to 32 different ones), so this is handy when checking for collisions. In this case, I've set my collision objects to the layer, "normalCollisions". Here's what it should look like in code:



You can use a layer mask to check more than one layer. This post has an explanation of how.

So now we have a ray that only looks for collisions, it's time to make multiple rays shooting out in every direction to look for collisions ^_^

The Nitty Gritty

This is the method I've developed. It's probably been developed other places, but I don't have a single place to attribute my ideas, just a lot of bits and pieces which culminated in this system.

The Gist

The idea is to shoot a number of raycasts out each side of your box collider, and if any of them connect with something, do stuff. If you're checking underneath you, you're now grounded. If you're looking left or right, you hit a wall, and if you're checking up you've hit the ceiling. It's elegant, but tricky.

Setup

So first, let's set up some variables. Here's what I've got

Disclaimer: I use FixedUpdates for my velocity calculations, and update movement in the LateUpdate() function using Time.deltaTime as a multiplier. This gives precise, predictable movements.


This should keep us going through most of the explanation
Here's what I have in functions already:
  • set up of Layer Mask;
  • definition of 'box' and 'position'. On their own they do nothing, but it saves us a lot of typing later on. Mark every time I use 'box.x' I could instead type 'collider.bounds.x' but it's much longer;
  • and the application of movement at the end. Since it happens after everything else (LateUpdate), I can use the velocity variable knowing the object hasn't moved that distance yet.

Gravity

Let's start with the simplest operation: gravity. Gravity is present in every platformer (uh, I think), so it's a good place to start. This is all in the FixedUpdate() function.

Here's what the final thing looks like:



First, let's the actual gravity numbers to the velocity. We do this first so we can predict its location when we look for the ground.



Next, I figure out exactly where I want to check beneath me. For this I'll use the 'box' variable I define at the beginning of my FixedUpdate. One of the tricky things about Raycasts is that it only connects going in to a collider, not coming out of one. We can take advantage of this, though, by starting the rays in the middle of the player's box collider, so that it doesn't ever detect it, but will detect anything outside.

My method for determining where each of my rays starts uses the Vector3.Lerp function. I figure out where  my first ray and my last ray will start, then use the Lerp function to iterate from one to the other. These are vertical rays, and will all start from the same y position in the scene.

We also have to determine how long we want these rays to be. If we're on the ground, just using a flat number (in this case I'm just using my 'margin' variable). Otherwise, we want to base it on our velocity. The trouble is, if we're falling, our velocity is negative, and Raycasts need the 'distance' variable to be positive (this is the dubiousness I spoke of earlier). So, we're going to check down only if our 'falling' variable is set to true, which happens if our velocity is below 0. Then we have to make it positive with a Mathf.Abs() function. Also add half the box height since we're starting in the middle of the box.


These two points should look like this on our box:


All of our rays will start between those two points (inclusively). To iterate between them, use a 'for' loop. Before going into the loop, set up a boolean so we can use it afterwards.



Use the Lerp to pick the start point, then add your already-determined ray length.

Finally, when we determine if all of the rays hit or not, we deal with the results.

There is a mistake here - I multiply the ray's distance by Time.deltaTime which is unnecessary and causes you to float to the ground. Ignore it!


If we're in the loop, and we meet something, we're going to want to get out of the loop so the next ray doesn't set connected to false or something silly. You'll also want to make sure you're flush with the ground, by immediately translating down to the surface, and set your vertical velocity to 0. If you're not finding anything, you're no longer grounded (then the rest takes care of itself).

Also note: you can slip in an Event or Delegate function to call when you land (or as Unity likes to do, use the "Send Message" function for something like "OnLand"). This makes it easy to set land animations, or for other objects to pass functionality for this kind of event (like if you want to poison your character and have it end when they hit the ground or something).

That's it for now

That's it for gravity, really. There are fancier things you can do like determining the slope of the platform you're on, or move with a moving platform, which are all pretty easy to do with this foundation.

All the code is in screen shots, deliberately - I have always found it more beneficial to type stuff out yourself, even copying it directly, than pasting it and checking to see if it works. I hope you agree!

Next time I'll be talking about moving left and right and hitting the ceiling. However, the techniques are largely the same, so I encourage you to give it a go yourself :)

Thanks a lot for reading. Until next time!

Stay grounded, earth wizard.

-mysteriosum(the deranged hermit)