Search Unity

Creating a 2D Platformer Controller

Discussion in 'Community Learning & Teaching' started by SebastianLague, Apr 4, 2015.

  1. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    OboShape, phelpscd and jhocking like this.
  2. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    I've uploaded episode 02
     
  3. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    And episode 03
     
  4. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    And episode 04
     
  5. romi-fauzi

    romi-fauzi

    Joined:
    Aug 16, 2013
    Posts:
    161
    Thanks a lot for the tutorial, kinda hard to understand the code at first, but after a couple times watching, I'm getting the grip....This is a really nice technique, and the movement it is really precise..
     
  6. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    Hi Romi, thanks for the feedback! Let me know if you have any questions, I'd be happy to answer them.

    In other news, episode 05 is out:
     
  7. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    Episode 06 covers the main part of the moving platform implementation:
     
  8. hasen

    hasen

    Joined:
    Apr 1, 2015
    Posts:
    29
    It looks great, I'll check it out. Although I did kind of hope it would cover realistic rotation of the character on slopes in line with the angle as well. Very posh accent btw...:D
     
    Last edited: Apr 28, 2015
    diegoadrada likes this.
  9. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    Thanks Hasen, I'll add that to the list of things I might cover :)

    Episode 07 allows passengers of a moving platform to collide with other objects:
     
  10. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    Episode 08 is now up. It covers a waypoint system for controlling the movement of platforms.
     
  11. Shadeless

    Shadeless

    Joined:
    Jul 22, 2013
    Posts:
    136
    Hey Seb,

    Thanks for the excellent tutorial series. Not only is it a really cool looking controller but it also teaches you some cool ways to structure your code.

    I think that One Way Platforms are a must in any 2D platformer and you should cover it. It would also be awesome if you covered one way slopes that could be used like stairs to get on the One Way Platforms. And of course you should be able to drop down from the platforms as well.

    Something like this:
    OneWayStairs_Example.png

    Which is something I really badly need! :D

    Cheers!
     
    malialis likes this.
  12. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    Thanks for the great ideas Shadeless, I'll integrate those as soon as possible :)
     
    diegoadrada likes this.
  13. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    Here is the latest episode on wall jumping:
     
  14. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    Episode 10 covers variable jump height and jumping/falling through platforms.
     
  15. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    Hi again, here's episode 11 on camera following:
     
  16. Senladar

    Senladar

    Joined:
    Jan 1, 2015
    Posts:
    45
    Thanks for the tutorial, I've definitely learned some new tricks and the controller works fairly well. Few comments from a newer/learning programmer:

    - The first few tutorials had a lot more "teaching" then the later ones. I find by the slopes I was just struggling to keep up with your typing speed with little context into what we were actually doing until I paused the video and spent time reading the code line by line, some of which I'm still not 100% clear on.

    - The math explanations were great. I'd have a hard time knowing to use them with a blank sheet and an idea, but I definitely understanding how they work in this context.

    Few ideas:
    - One way platforms
    - Rotating the character on a slope
    - Ladders/ropes
    - Setting up sprite (looking correct direction, etc)
    - Hit reaction (pushed backwards/up when hit by something, etc)

    Thanks again!
     
  17. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    Thank you Senladar, for your feedback and your suggestions. I'll strive to bring more actual teaching back into future episodes. Sorry if it got a bit lost along the way ^^
     
  18. yagumo

    yagumo

    Joined:
    Jul 20, 2015
    Posts:
    1
    I did a lot of platformer tutorials before and I've been wanting to come back to Unity. This seems to be a good restart! I'll try this one! Thanks!
     
  19. Abhijit-Mukherjee

    Abhijit-Mukherjee

    Joined:
    Jan 9, 2015
    Posts:
    193
  20. shivanshu

    shivanshu

    Joined:
    Apr 27, 2015
    Posts:
    1
    Hi,
    Have you implemented the leaser beam type effect as you showed in first tutorial of your pervious thread.Please share that like effect.
    Thanks !

    "
    "
     
  21. Sniperninja564

    Sniperninja564

    Joined:
    Nov 18, 2015
    Posts:
    4
    I'm stuck on episode 2 because the player colour won't change and goes through the object the rays also aren't showing under the block even though it was working fine when I started Here's the picture and code bellow:
    Capture.PNG
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. [RequireComponent(typeof(Controller2D))]
    5.  
    6. public class Player : MonoBehaviour
    7. {
    8.  
    9.     float moveSpeed = 6;
    10.     float gravity = -20;
    11.     Vector3 velocity;
    12.  
    13.     Controller2D controller;
    14.  
    15.     void Start()
    16.     {
    17.         controller = GetComponent<Controller2D>();
    18.     }
    19.  
    20.     void Update()
    21.     {
    22.  
    23.         Vector2 input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
    24.  
    25.  
    26.         velocity.x = input.x * moveSpeed;
    27.         velocity.y += gravity * Time.deltaTime;
    28.         controller.Move(velocity * Time.deltaTime);
    29.     }
    30. }
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. [RequireComponent(typeof(BoxCollider2D))]
    5. public class Controller2D : MonoBehaviour
    6. {
    7.  
    8.     public LayerMask collisionMask;
    9.  
    10.     const float skinwidth = .015f;
    11.     public int horizontalRayCount = 4;
    12.     public int verticalRayCount = 4;
    13.  
    14.     float horizontalRaySpacing;
    15.     float verticalRaySpacing;
    16.  
    17.  
    18.     BoxCollider2D coll;
    19.     RaycastOrigins raycastOrigins;
    20.  
    21.     void Start()
    22.     {
    23.         coll = GetComponent<BoxCollider2D>();
    24.         calculateRaySpacing();
    25.     }
    26.  
    27.     public void Move(Vector3 velocity)
    28.     {
    29.         UpdateRaycastOrigins();
    30.         if (velocity.x != 0)
    31.         {
    32.             HorizontalCollisions(ref velocity);
    33.         }
    34.         if (velocity.y != 0)
    35.         {
    36.             VerticalCollisions(ref velocity);
    37.         }
    38.         transform.Translate(velocity);
    39.     }
    40.  
    41.     void HorizontalCollisions(ref Vector3 velocity)
    42.     {
    43.         float directionX = Mathf.Sign(velocity.x);
    44.         float rayLength = Mathf.Abs(velocity.x) + skinwidth;
    45.  
    46.         for (int i = 0; i < horizontalRayCount; i++)
    47.         {
    48.             Vector2 rayOrigin = (directionX == -1) ? raycastOrigins.bottomLeft : raycastOrigins.bottomRight;
    49.             rayOrigin += Vector2.up * (horizontalRaySpacing * i);
    50.             RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.right * directionX, rayLength, collisionMask);
    51.  
    52.             Debug.DrawRay(rayOrigin, Vector2.right * directionX * rayLength, Color.red);
    53.  
    54.             if (hit)
    55.             {
    56.                 velocity.x = (hit.distance - skinwidth) * directionX;
    57.                 rayLength = hit.distance;
    58.             }
    59.         }
    60.     }
    61.  
    62.     void VerticalCollisions(ref Vector3 velocity)
    63.     {
    64.         float directionY = Mathf.Sign(velocity.y);
    65.         float rayLength = Mathf.Abs(velocity.y) + skinwidth;
    66.  
    67.         for (int i = 0; i < verticalRayCount; i++)
    68.         {
    69.             Vector2 rayOrigin = (directionY == -1) ? raycastOrigins.bottomLeft : raycastOrigins.topLeft;
    70.             rayOrigin += Vector2.right * (verticalRaySpacing * i + velocity.x);
    71.             RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.up * directionY, rayLength, collisionMask);
    72.             Debug.DrawRay(rayOrigin, Vector2.up * directionY * rayLength, Color.red);
    73.  
    74.             if (hit)
    75.             {
    76.                 velocity.y = (hit.distance - skinwidth) * directionY;
    77.                 rayLength = hit.distance;
    78.             }
    79.         }
    80.     }
    81.  
    82.     void UpdateRaycastOrigins()
    83.     {
    84.         Bounds bounds = coll.bounds;
    85.         bounds.Expand(skinwidth * -2);
    86.  
    87.         raycastOrigins.bottomLeft = new Vector2(bounds.min.x, bounds.min.y);
    88.         raycastOrigins.bottomRight = new Vector2(bounds.max.x, bounds.min.y);
    89.         raycastOrigins.topLeft = new Vector2(bounds.min.x, bounds.max.y);
    90.         raycastOrigins.topRight = new Vector2(bounds.max.x, bounds.max.y);
    91.  
    92.     }
    93.     void calculateRaySpacing()
    94.     {
    95.         Bounds bounds = coll.bounds;
    96.         bounds.Expand(skinwidth * -2);
    97.  
    98.         horizontalRayCount = Mathf.Clamp(horizontalRayCount, 2, int.MaxValue);
    99.         verticalRayCount = Mathf.Clamp(verticalRayCount, 2, int.MaxValue);
    100.  
    101.         horizontalRaySpacing = bounds.size.y / (horizontalRayCount - 1);
    102.         verticalRaySpacing = bounds.size.x / (verticalRayCount - 1);
    103.     }
    104.  
    105.  
    106.     struct RaycastOrigins
    107.     {
    108.         public Vector2 topLeft, topRight;
    109.         public Vector2 bottomLeft, bottomRight;
    110.     }
    111.  
    112. }
    113.  
    Pls Help
     
  22. phelpscd

    phelpscd

    Joined:
    Aug 17, 2013
    Posts:
    4
    This is a great tutorial, thanks for posting it.
     
  23. fredzh

    fredzh

    Joined:
    Dec 5, 2013
    Posts:
    4
    Hi Sebastian,
    your tutorials are excellent. Thank you so much. While following the first part of the tutorial I got a compiler warning which I don't understand.

    In the Controller2d script, we create a reference to the BoxCollider2d with the name "collider". When compiling, I get the message: "Controller2d.collider hides inherited member 'UnityEngine.Component.collider'.Use the new keyword if hiding was intended*

    Ok so the Component class defines a member called "collider" I thought. but the script reference of the Component class does not mention the member variable. Also creating an empty script extending MonoBehavior does not bring up the variable "collider" in the code-completion.

    While I could easily make the warning go away by naming the reference boxCollider or so, I would like to understand this warning. Did you also get the warning?

    Thanks for any hint on the topic.

    kind regards
    Fred
     
  24. fredzh

    fredzh

    Joined:
    Dec 5, 2013
    Posts:
    4
    Found this:
    Removed in version 5.3.2p2
    Property collider has been deprecated. Use GetComponent<Collider>() instead. (UnityUpgradable)

    There used to be a reference which was filled if a Collider was attached to the GameObject and null if not.
     
  25. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    Hi everyone, this series has been dormant for about a year, but I've recently decided to take it further.
    Here is the latest episode:
     
  26. SebastianLague

    SebastianLague

    Joined:
    Aug 31, 2014
    Posts:
    111
    Episode 13 is now out. It covers auto sliding down steep slopes.
     
  27. delphifissure

    delphifissure

    Joined:
    Apr 20, 2017
    Posts:
    6
    @SebastianLague Hi Seb - Awesome tutorials btw. Were you ever able to make a tut for Castlevania-style stairs? Or know of any good resources online?
     
  28. Gamingbir

    Gamingbir

    Joined:
    Apr 1, 2014
    Posts:
    195
    Is this the end of this series or you are adding anything else? @SebastianLague
     
  29. barnacle-balogh

    barnacle-balogh

    Joined:
    Jan 22, 2016
    Posts:
    3

    Totally late to the game question!

    When putting two moving platforms next to each other, the player moves to the one of them:


    https://imgur.com/LLOtEol

    Any ideas on how to make that not happen?

    Thanks!
     
  30. barnacle-balogh

    barnacle-balogh

    Joined:
    Jan 22, 2016
    Posts:
    3
    Hmm...looks like it's being pulled both ways: