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)




3 comments:

  1. Thanks a lot! I can't wait to go through this when I get the time.

    Another challenge I want to do is to try making those platforms in MegaMan X2 where you land on the platform with the button and it changes the direction it moves with the little arrow shown on it.

    ReplyDelete
  2. Thanks for the articles! This is the best slopes solution I've found anywhere, by a long shot. I really appreciate you taking the time to write them.

    The only issue I'm seeing -- including in the version of your script that you made available on GoogleDrive in the comments of a previous article -- is that angleLeeway seems to not work. No matter what value it's set to, you can still walk up any slope, of any angle, that isn't a perfect 90-degree wall. I've tried a bunch of variations, but it seems to be a problem with the raw code. Any ideas?

    ReplyDelete
  3. Hey Muir,

    Thanks for your input! I'm glad I could help.

    Yes, I don't think I ever got AngleLeeway to help, either....

    I'll tell you the idea behind it and I hope you will be able to make it work.

    When you hit something you should get a normal which would, interpreted correctly, give you the angle of the impact. Then you could use that info however you wanted, including by stopping the effect and using instead that of a wall.

    In theory.

    Yours,
    -the deranged hermit

    ReplyDelete