Search Unity

[Released] 2D Platform Controller

Discussion in 'Assets and Asset Store' started by JohnnyA, Mar 11, 2013.

  1. sirius_002

    sirius_002

    Joined:
    Aug 16, 2012
    Posts:
    65
    Hi Johnny,

    I would like to add an animation frame for when the character hits the ground after a jump, I know you added fall damage so there must be a state for that already. Thanks!
     
  2. secret-arts

    secret-arts

    Joined:
    Oct 4, 2012
    Posts:
    9
    Hi there,

    I'm really enjoying the versatility of this controller! It's saved me a ton of time and I can already predict a few dozen games that it will be perfect for. I'm heading directly to the Asset Store to write a glowing review!

    Quick question: I'm trying to implement a float-on-jump-button-held function in my current game. I'm fine with the detection of the button held etc., but I'm trying to see if there's an accessible variable to slow the character's descent. I had thought it would be fall velocity under jump details, but that appears to be a detector for when the Fall state begins.

    I'm sure I can manage something but I wanted to make sure I haven't missed something simple and built in (especially since I've otherwise been able to simply and easily do everything else I wanted to).
     
  3. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    I think there's a float sample a few pages back, its included in the next release. But if you wnat to do it yourself then simple adjust the charaacters velocity.y when they are in the FALL state and jump is held.

    Sirius, look for state IDLE/SLIDE/WALK/RUN when the previous state is FALLING.
     
  4. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    I would expect so as there is nothing platform specific to it, although I can't absolutely confirm it. I can tell you about Windows phone in about a week (I just ordered some which should be here soon).

    - John A
     
  5. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    The colliders can be attached to bones if you want, although its probably better to create new bones which simplify movement so your colliders aren't bouncing about everywhere. For 2D you need to create your own "bones" (i.e. transforms that move with the character). Note that this is not often needed, usually you can leave your colliders static and just add code or a transform that moves for a few specific states.
     
  6. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    PS Sorry for the short replies this week guys, getting hammered at work. I'll put aside a few hours on the weekend for more detailed responses.

    PPS Ladders is done although not yet submitted, I'm trying to sneak a few other minor thing sin to the release to.
     
  7. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Forgot to say ... awesome work! Platform mechanics aside it looks like an interesting game to play, I can see a lot of depth present just from the menu's and the like.

    Thanks for posting,

    John A
     
  8. sirius_002

    sirius_002

    Joined:
    Aug 16, 2012
    Posts:
    65
    Works like a charm, thanks Johnny!
     
  9. orokborokhulu

    orokborokhulu

    Joined:
    Sep 20, 2012
    Posts:
    9
    Hi Johny

    I tried the demo and it was best 2d platform movement for unity so far.
    but it need a little improvement:
    - make it more longer you push the button, then more high the player can jump (very basic in 2d platformer).
    - make player movement based on mouse position! (casual gamer doesn't like put the both hands on keyboard, they only put one hand on the mouse and the other hand carry the food or beer) example game: jumpin'jack and many more. And the player movement speed depend on mouse position too, if mouse far from him then he moves faster and otherwise.
    that enough for now.

    thanks
     
  10. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    1. That is an option already in the kit.
    2. Note that the input mechanism is flexible; you could create that behaviour in a few lines of code. However its a good candidate for the Extra Features folder.

    - John A
     
  11. BigBite

    BigBite

    Joined:
    Feb 20, 2013
    Posts:
    108
    Hi John, I'm hoping you could help me out with an issue I'm running into. I'm currently using 2D Toolkit and I've created a simple level. The Raycast Controller collides with everything just fine, however, it refuses to ledge grab. Is there something special that I have to do?
     
  12. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    The usual issue with ledge grab is the edge detection offset. This tries to find another collider near the ledge and if it does it stops the ledge climb (it primarily there to stop you ledge climbing tiled walls). Next release has a special case if you set y = 0 it tuns off this check. For now the best thing to do is set x to a very small or even negative number, and y to a positive value that will ensure the raycast doesn't hit anything (try 0.25f).

    Also note ledge hang is based on the highest side collider on each side. If your character is oddly shaped you might have longer middle colliders which push the character away from the ledge before the higher side colliders get a chance to catch it. In this case you could increase the autograb distance.

    Beyond that... make sure the character has ledge hang on (can ledge hang), and maybe screenshot your settings and your character with the collier gizmos so I can take a look :)

    - John A
     
  13. BigBite

    BigBite

    Joined:
    Feb 20, 2013
    Posts:
    108
    $Ledge Grab Setting.png

    These are my current settings for ledge grab. It seems that the Edge Detection Offset for X was already set to .1. I'm using the HeroCharacterWithCrouch prefab. All I've done to it is disabled the mesh render. I'll keep playing with it, maybe I'm missing something.
     
  14. Dan_Tsukasa

    Dan_Tsukasa

    Joined:
    Jan 26, 2013
    Posts:
    155
    I'd have to disagree with this, though it might be an interesting feature, platform games generally use only a few buttons and those are used with both hands, I don't think I've ever played a platform game (outside of mobile), that took use of the mouse for actual platform mechanics, puzzles (ala Trine) yes, but platforming Mechanics no.

    Though I do think it'd be an interesting thing, it'd enable people to make those endless jumping games (you know the sort of flash games). People move the mouse where they want to jump, for these games it'd work brilliantly.
     
  15. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    If you haven't changed the prefab (minus the mesh) I would certainly expect it to work. Is there anything you would consider special or unusual about your level geometry (i.e. colliders)? Other than that try -0.1 for your offset this should effectively disable the check.
     
  16. Bast-I

    Bast-I

    Joined:
    May 28, 2013
    Posts:
    18
    Hi Johnny,

    I tried to implement the behavior that sirius_002 suggested: passing through platforms requiring pressing down and jump. I did like you suggested and added a method to the SimpleCharacterInput script that sets jumpButtonDown to false:

    Code (csharp):
    1. public void SetJumpButtonDown () {
    2.         jumpButtonDown = false;
    3.     }
    I put it behind update. I noticed two things:
    First, it works, but only most of the time. About every second or third time the character jumps normally -- even without passing through the platform eventually. I cannot tell why and there seems to be some pattern in the unexpected behavior. I think I can exclude wrong or sloppy or too quick input as cause but that is about it. My console output suggests that the method is not called every time it should.
    Second, since you suggested playing around with the velocity parameters in the passthrough platform script to get a good result, I made them public variables and tried different values. But doing that resulted in no observable difference (y-axis) or strange behavior (x-axis). Using the values you had in your example (0,5) seems to make the passthrough work a little more consistently (?) but still ...

    Here is the Platform script:

    Code (csharp):
    1. public class PassthroughPlatformEnhanced : Platform {
    2.    
    3.     public float fallThroughTime = 1.5f;
    4.     public SimpleCharacterInput input;
    5.     public float jumpDownwardX;
    6.     public float jumpDownwardY;
    7.    
    8.     override public void DoAction(RaycastCollider collider, RaycastCharacterController character) {
    9.         if (collider.direction == RC_Direction.DOWN  character.characterInput.y < 0.0f  character.characterInput.jumpButtonDown) {
    10.              input.SetJumpButtonDown();
    11.              character.Velocity = new Vector2(jumpDownwardX, jumpDownwardY);
    12.              character.FallThroughTimer = fallThroughTime;
    13.         }
    14.     }
    It would be brillant if you could help me once more!

    Bast I
     
    Last edited: Aug 10, 2013
  17. BlueByLiquid

    BlueByLiquid

    Joined:
    Jul 30, 2013
    Posts:
    13
    Has anyone got a basic example using Futile?
     
  18. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    @Bast I

    Hmm, DoAction isn't guaranteed to fire every frame (sometimes you are bouncing upwards very slightly and don't trigger it), usually you can work around it but in this case maybe not.

    Although its a simple change for me to fix this (just cast a little further), it may have unexpected changes on other code.

    I'll make the change, but I'll have to do a bit of testing.

    - John A

    EDIT: Seems I have already fixed that. This works for me every time on HeroSample:

    Code (csharp):
    1.  
    2. public class PassthroughPlatform : Platform {
    3.    
    4.     public float fallThroughTime = 1.5f;
    5.     public bool requireJump;
    6.    
    7.     override public void DoAction(RaycastCollider collider, RaycastCharacterController character) {
    8.         if (character.FallThroughTimer <= 0.0f  collider.direction == RC_Direction.DOWN  character.characterInput.y < 0.0f  (!requireJump ||character.characterInput.jumpButtonDown)) {
    9.             character.FallThroughTimer = fallThroughTime;
    10.             character.characterInput.CancelJump();
    11.         }
    12.     }
    13. }
    14.  
    Where CancelJump is a new method on the input that sets both jumpButtonDown and jumpButtonHeld to false.

    Note there is definitely an issue with the small jump before the passthrough which will take some core code changes. WIll try and look at it before I submit the update tomorrow.
     
    Last edited: Aug 10, 2013
  19. sirius_002

    sirius_002

    Joined:
    Aug 16, 2012
    Posts:
    65
    Sounds great and thanks for taking the time to add this feature!
     
  20. Bast-I

    Bast-I

    Joined:
    May 28, 2013
    Posts:
    18
    Thank you, Johnny! This is great!
     
  21. TheValar

    TheValar

    Joined:
    Nov 12, 2012
    Posts:
    760
    Got a couple feature requests here:

    These are simple enough that I've already integrated them in my own project but they seem sensible enough to warrant being in the package

    1: allow jumping while falling. So if the player walks off a ledge they can still jump. Maybe add a timer setting for this or something

    2: allow running in the air. so that you can jump farther using the spring button even if you press it midair. This is how it is in super meat boy I believe

    3: a way to disable sliding to a stop. It would be a nice option to let the player instantly halt horizontal movement regardless of the value for drag.

    Anyway awesome plugin!!!
     
  22. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Thanks for the points Valar, as you may have noted most of them are pretty easy to add, and I should get them in. My only concern at the moment is the ridiculous amount of controls, I think I might need to right an editor which has simple and advanced modes or maybe a set-up wizard.

    3. I have been planning on doing this for ages (actually the controller used to work like this in v0.1), but I keep forgetting due to the simple workaround (large drag, increase speed for idle).

    After ladder update (submitted today) I'll probably look at a few minor updates before moving on to push and pull.

    Thanks for purchase and keep the suggestions rolling.

    - John A
     
  23. AMO_Noot

    AMO_Noot

    Joined:
    Aug 14, 2012
    Posts:
    433
    Heya Johnny,

    Looking forward to the push and pull!

    I had a quick question for you:

    To prevent the sprite from rotating on slopes, I added a little No-rotation script and popped it onto the child sprite. This works well, but
    I noticed that it brings up another problem, which is a little floating with the sprite while on slopes.

    http://i.imgur.com/ZaC3zHL.jpg

    I was wondering if you had any recommendations or advice on how to make it look a bit better.

    Edit: I also noticed that when approaching the bottom of a steeper slope, such as 45 degrees, there's a small jolt when the controller has to rotate for the slope. It can be a little jarring and can feel like a collision bug. Is there a way to better smooth it out, besides make smaller slope inclines?

    Looking forward to the next few updates!
     
    Last edited: Aug 11, 2013
  24. BlueByLiquid

    BlueByLiquid

    Joined:
    Jul 30, 2013
    Posts:
    13
    A thought would be to make your character two sprites and rotate the leg with the slope and keep the upper body vertical (The same way a person would when standing on a slope.
     
  25. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Hey mate the only thing I can suggest is customisation to move your sprite around based on the angle. In your no rotation script transform the character left or right based on the angle (k * sin(a)) where k is some constant based on your characters shape. That will likely be a bit abrupt so you might need to smooth it out (instead of applying the transform set it as a target and slowly transform towards the target each update).
     
  26. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    PS Little update, figured I might try and do some editor scripting today before submission of ladders (given I've been doing a bunch of editor scripting on this: http://forum.unity3d.com/threads/190298-Point-and-Click-Adventure-Kit/page2)

    Hoping to create:

    a wizard for creating ladders
    auto generate colliders button (simple static colliders to bounding box only)
    and maybe a character settings XML format to be used to move character settings around
     
  27. AMO_Noot

    AMO_Noot

    Joined:
    Aug 14, 2012
    Posts:
    433
    Thanks, I thought something like this might be the most suitable solution as well; just wanted to double-check.

    True! But that may actually look even more awkward with so few pixels :D
     
  28. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    If changing graphics is an option (I'm a coder so I always think of that last), maybe simply have sprites/animations for angles greater than some threshold (i.e. walking down angle animation, jumping from angle animation, etc).
     
  29. BlueByLiquid

    BlueByLiquid

    Joined:
    Jul 30, 2013
    Posts:
    13
    This was my first thought for him but I thought that might be a lot of work to handle all those states as you would probably want multiple angles animations (maybe not though if you let the player stand a bit into the floor)
     
  30. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Ladder wizard seems to be coming along so I think it should make the update. A sneak peek:

    $Screen Shot 2013-08-11 at 11.43.44 AM.png

    All items have descriptive tool tips and the recalculate now button makes a best estimate of the settings for step size, step distance and top offset based on your characters raycast collider settings.
     
  31. BlueByLiquid

    BlueByLiquid

    Joined:
    Jul 30, 2013
    Posts:
    13
    @Kirbychwan,

    So I thought I would see how well rotating the torso would look in case i ever needed to do that myself so I took your image and tested it real quick. I think it looks pretty decent (But maybe I am crazy. I think if you set a max angle it could work fine. Also if you had better legs it would look less broken legged than mine but I didn't have long legs to work with. :)
     
  32. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Better Ladders ... on film:

    [video=youtube_share;1SyzoY4E9lc]http://youtu.be/1SyzoY4E9lc​
     
  33. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Submitted.
     
  34. FelipeKras

    FelipeKras

    Joined:
    Apr 28, 2013
    Posts:
    5
    That's what I was looking for! Better ladders. :D

    Thanks for giving attention to this feature, it looks really nice.
     
  35. sirius_002

    sirius_002

    Joined:
    Aug 16, 2012
    Posts:
    65
    Hi Johnny, kind of a long shot, but do you have an example for a melee attack (sword)? If not I'll just wait and continue with level art first. Thanks!
     
  36. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    NO sample as such. Basic philosophy is:

    1. Trigger animation
    2. After some time turn on a hit box.
    3. After sometime turn off the hit box.
    4. Return control back to the controller.
     
  37. sirius_002

    sirius_002

    Joined:
    Aug 16, 2012
    Posts:
    65
    That sounds totally doable, I guess I've been depending on your framework a little too much. Which is an easy mistake to make because you've facilitated so many features already. Anyway, each game should have at least some originality even if it's a retro inspired one.
     
  38. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Well I'm sure an example will make it in eventually, there is a melee attack animation for the Hero character, its just a matter of timing. It's probably going to be some time away.

    Regards,

    John A
     
  39. Mmarzex

    Mmarzex

    Joined:
    Aug 13, 2013
    Posts:
    2
    Hi, I'm trying to use the 2d toolkit sample and am wondering how exactly the maps are created? Also is there a way to use the 2d toolkit tilemap feature with this?
     
  40. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,422
    I just wanted to mention something the developer of 2DToolkit told me:
    Do NOT turn on/off the hitboxes/box colliders, instead ignore the Physics. It's way more efficient.

    I made a custom collider with 2DToolkit around my Attack-Animation and just detect collision with the Enemy-Hitbox when the Attack itself is triggered, apart from that certain box collider ignores every other collision all the time. Works great for me.
     
  41. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Sounds like a case of premature optimitis to me :)
     
  42. Mmarzex

    Mmarzex

    Joined:
    Aug 13, 2013
    Posts:
    2
    I've been messing around with the 2d toolkit sample and I'm a bit confused. How exactly did you create the level and then the function for changing level called in the input Application.loadLevel(0). Where exactly is that function located?
     
  43. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,422
    Does it?

    Well I don't know it for myself. I made a custom collider for some Attack-Sprites in my 2DToolkit SpriteCollection. And if you do that, a Box Collider will be automatically attached to the Sprite-GameObject. The thing is, that collider is enabled all the time of course, and I wanted to know if I could disable it via 2DToolkit or had to code it. Dev suggested to ignore collision.

    I tried enabling/disabling Hitbox before, worked for me. But then I got told ignoring collision and only detecting it in certain states would be more efficient and I went for it. For now I didn't "feel" any performance differences.

    If you, Johnny, have a different view I would like to read it! The more information, the better :)
     
  44. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    My philosophy is don't optimise unless you need to (except in a few cases where there are clearly problems). Just for some perspective I did a quick test with 25 overlapping triggers and 25 overlapping kinematic rigidbodies each one being enabled or disables each frame. Without enables the frame time was ~0.7ms. With enables the frame time was ~1.1ms. In other words the cost (on my 2009 Mac) was less than 0.01ms per collider.

    Not that there's anything wrong with using an alternative approach, but to me it seems like most of the time it will be a non-issue.
     
  45. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    The level was just manually created, I dropped a few sprites on some cubes and moved them around. I'm no expert on 2DTK although I think it has some kind of tile system.

    I'm not quite sure what your second question is about? Could you rephrase?
     
  46. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,422
    Excellent, thank you very much for that information :)
     
  47. EskemaGames

    EskemaGames

    Joined:
    Jun 23, 2010
    Posts:
    319

    I agree with that, turning on/off objects causes delay and garbage collection at some point. I also use the "ignore collision" method a lot, you have some kind of state machine and only do an action when the state is what you want, otherwise just ignore the collider.
    Even if as johnnyA pointed out the cost is really low, in mobiles the cost is NOT low, at least you cannot afford to be wasting time on certain things.
     
  48. nab

    nab

    Joined:
    Aug 2, 2013
    Posts:
    8
    hey johnny,
    great asset, thanks for the hard work.

    I wanna ask about CurrentDirection inside the RaycastCharacterController
    in the beginning of the game it's acceptable that it's 0, but why does it revert to 0 after stopping ? is there a way to find the last position it was in without keeping track of it inside the update method ?

    I'm basically doing a 2d platformer, and only check CurrentDirection if the player pressed the button for using a tool, and i expected it to give me the direction the character is facing especially after he stopped.

    Edit:
    never mind, solved it by implementing my own direction checker.
    for reference, my solution was:
    Code (csharp):
    1. public class MyDirectionChecker : DirectionChecker{
    2.     public override int CurrentDirection{
    3.         get{
    4.             if (direction == 0) direction = startingDirection;
    5.             return direction;
    6.         }
    7.     }
    8.     private int direction;
    9.     public override bool UpdateDirection(RaycastCharacterController character)
    10.     {
    11.         bool result = base.UpdateDirection(character);
    12.         if (result) direction *= -1;
    13.         return result;
    14.     }
    15. }
    let me know if i missed anything
     
    Last edited: Aug 14, 2013
  49. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Hi nab, direction is provided by the direction checker class if one is assigned. If you need an alternate behaviour to the default write your own direction checker. Something like this could be your starting point:

    Code (csharp):
    1.  
    2. public NabsDirectionChecker : DirectionChecker {
    3.     override public bool UpdateDirection (RaycastCharacterController character) {
    4.         int newDirection = CurrentDirection;
    5.         if (character.Velocity.x > 0.0f) {
    6.             newDirection = 1;
    7.         } else if (character.Velocity.x < 0.0f) {
    8.             newDirection = -1;
    9.         } else if (character.characterInput.x > 0.0f) {
    10.             newDirection = 1;
    11.         } else if (character.characterInput.x < 0.0f) {
    12.             newDirection = -1;
    13.         }
    14.         if (newDirection != CurrentDirection) {
    15.             CurrentDirection = newDirection;
    16.             return true;
    17.         }
    18.         return false;
    19.     }
    20. }
    21.  
    (Note this is not to say your idea is not a reasonable default given that many games do not have a neutral position, but I would be loathe to change something that could quite easily impact a lot of people when there is already a mechanism for specifying your own method for calculating direction).
     
    Last edited: Aug 14, 2013
  50. nab

    nab

    Joined:
    Aug 2, 2013
    Posts:
    8
    Thanks for the reply johnny
    I agree that the default behaviour shouldn't change since it would probably break somebody's already working code.
    I just added my code for reference for those who might face the same problem and arrive here through searching.

    and I'm really impressed with how easy extending the basic features is in the framework, good work thinking ahead.