Search Unity

[Released] 2D Platform Controller

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

  1. kraaijmakers

    kraaijmakers

    Joined:
    May 2, 2013
    Posts:
    14
    OK, thank you very much JohnnyA. :)
     
  2. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,422
    Hey John, did you receive my message?
     
  3. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Yes, reply sent.
     
  4. NeilMeredith

    NeilMeredith

    Joined:
    Jul 15, 2013
    Posts:
    81
    Hi Johnny,

    I purchased a 3d model that I want to use your raycast character controller with. The problem is the 3d model is not facing towards the x axis by default. So when I rotate the 3d model and then apply the character controller, my character moves forward and back along the world z axis instead. How do I adjust this to take the rotation into account so my character will move along the world x axis? Thanks.

    -Neil
     
  5. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Firstly ensure your model is a child of the controller. The controller should NEVER be rotated. After that you have two options

    1. Add a transform between the character and the controller which makes him face the correct way (so you would have 3 GO's.)

    2. (Preferred method) Update the animator code so that when it changes the character's direction instead of right = 90 right = 270 (or whatever is right for your character.
     
  6. johot

    johot

    Joined:
    Apr 11, 2011
    Posts:
    201
    Hi Johnny!

    This looks great and i'm thinking of buying it. I have 3 questions however that I hope you can answer:

    1. Can acceleration be turned off completely, so that movement is instant?
    2. Can the amount you can move in the air be set also? Is that the drag setting? Can I make my character able to fully move (left and right) while falling down?
    3. Is this implemented by using raycasts only? I once created such a script, I even have a thread here on the forums about it (http://forum.unity3d.com/threads/10...-game-raycasting-vs-colliders-and-performance). I hope it works like that because I remember I got much better performance that way + I could check collision before moving the character which made sure I never clipped anything. I also remember that I had optimizations in my code that for example didn't cast rays upwards if I was falling down (or cast rays to the right if I was moving left). Are optimizations such as that in place here also?

    Btw, did you ever find any research on the acceleration, slide etc settings used in the original mario games and how they implemented it? Would be cool if you could set up the exactly same parameters in your script, unless you already done that :)
     
  7. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    1. Yes, there is a setting called DITIGAL movement (and also DIGITAL WITH SLIDE).

    2a. To some extent although I do plan on updating this a bit. Currently in DIGITAL mode the character can move in the air at either run speed or jump speed (your choice). PHYSICS LIKE mode is a bit more complex. In that mode you can jump at run speed, but when you change direction you slwo down to walk speed (actually a little more complex than that, but you get the idea).

    2b. You can move freely in the air (although I have a sample script to stop it if you don't want to be able to do this).

    3. Collision is handled with raycasts. I originally had a bunch of optimisations for stopping raycasts in various directions, but in the end it turned out to be a lot of complexity for no real reason. Raycasts just don't cost that much and can cause issues e.g. If you don't cast up while falling, what happens if something falls on your head.

    Short answer: You can comfortably run multiple characters on mobile devices two generations old. If you have some really complex requirement I'm happy to help you tweak to improve performance further.
     
  8. kraaijmakers

    kraaijmakers

    Joined:
    May 2, 2013
    Posts:
    14
    Hey JohnnyA,

    I don't know if it has been asked already, but I keep getting errors in MonoDevelop about Default parameter specifiers are not permitted (CS0241).
    I get this error in PushablePullableBox.cs (Line 263) and in RaycastCharacterController.cs (Line 269).

    How can I fix this?

    I already fixed the warnings about extent being obsolete, so I changed it to size.

    But I'd rather not mess with your code, so if you can just tell me what to add in the current code, that would be cool :).
     
  9. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Change projects mono target framework in mono develop to 4.0 ( in Project->Assemply CSharp Options->General).

    EDIT: Also are you using vanilla install of latest version? I don't get these errors and only recently did an upgrade. Possibly my MonoDevelop settings carry over, but then I would expect to get a lot more people mentioning this (you are the first).

    I need to add some defines for the removal of extents, so the warnings will go away soonish (darn you 3.5 users making me use #defines:) ).
     
    Last edited: Nov 1, 2013
  10. kraaijmakers

    kraaijmakers

    Joined:
    May 2, 2013
    Posts:
    14
    Ah, this fixed it, at first I got alot of errors, then I restarted MonoDevelop, then I thought lets change the Editor extensions too, that fixed all errors :)

    Thanks JohnnyA :D

    And I use the latest one, 1.8.0, the one with swimming and such.
     
  11. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Hey mate, glad its working. Regarding version I meant Unity version :)
     
  12. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Was about to post a video of the Mecanim Animator, but it seems Unity decided to delete all the transitions from the Any State in my model.

    Grrr, the Mecanim Editor is not good!

    Note to self, commit more often.

    Lets see how quickly I can restore it...
     
  13. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Okay didn't take long, video being uploaded right now (will probably take 20 minutes or so):

     
  14. fryiee

    fryiee

    Joined:
    Jan 28, 2013
    Posts:
    18
    Long time no see.

    Still having trouble with getting sonic like loops etc to work. My demo doesn't seem to have correct parabolic motion (or it might just be something to do with the speed). I'm having trouble correctly identifying the exit angle in order to make the parabolic arc correct. Unfortunately, physics isn't my strong suit.

    Here's the demo:
    http://excaliburdesign.com.au/demo/demo.html

    Control to slide, space to jump, R to reset.

    Here's my code:
    Code (csharp):
    1. public class SlopeCharacterInput : RaycastCharacterInput {
    2.  
    3.     public RaycastCharacterController controller;
    4.     public static SlopeCharacterInput Instance;
    5.     public bool alwaysRun;
    6.     public float acc = 1.5f;
    7.     public float drag = 0.5f;
    8.     public float fallTime = 0.125f;
    9.     public float SlideTime = 0.1f; // Time required to start 'sliding' - ie move the colliders
    10.     public float MaxSlideRotation = 180f; //Max rotation of character during a slide
    11.     public float SideColliderDesiredOffset = -0.1f; //The Offset the side colliders will be moved up to during a slide
    12.     public float MinStartSlideVel = 10f; // Velocity required to start the adding to slidetimer - stops 'mini' slides taking you up ramps
    13.     public float TimeAllowedStationary = 0.1f; //How long we're allowed to be stationary before we're taken out of a slide
    14.     public float ThresholdVelocity = 0.2f; // Threshold velocity to continue a slide - lower will start the timer to take us out of a slide
    15.     public int[] SideColliderElements; // The lowest side colliders to be moved up during slide
    16.     public bool isSliding;
    17.    
    18.     private int n; //counter
    19.     private int currentCollider; //counter
    20.     private float slideTimer = 0;
    21.     private float stationaryTimer = 0;
    22.     private float fallTimer;
    23.     private float prevAngle;
    24.     private float[] sideColliderOriginalOffset;
    25.     private Vector3 originalLoc;
    26.    
    27.     void Start() {
    28.         Instance = this;
    29.         sideColliderOriginalOffset = new float[SideColliderElements.Length];
    30.         prevAngle = controller.slopes.maxRotation;
    31.         for (n = 0; n < SideColliderElements.Length; n++) {
    32.             currentCollider = SideColliderElements[n];
    33.             sideColliderOriginalOffset[n] = controller.sides[currentCollider].offset.y;
    34.         }
    35.         controller.transform.position = CheckpointManager.Instance.CurrentCheckpoint;
    36.     }
    37.  
    38.     void Update () {
    39.             jumpButtonHeld = false;
    40.             jumpButtonDown = false;
    41.             x = 0;
    42.             y = 0;
    43.             /*  This is johnny's check, based automatically on angle
    44.              * if (!isSliding  Mathf.Abs (controller.transform.localEulerAngles.z) > 5.0f  Mathf.Abs (controller.transform.localEulerAngles.z) < 355.0f) {
    45.                 isSliding = true;
    46.             }
    47.             */
    48.             if (!FollowCam.Instance.InCinematic) {
    49.             if (Input.GetKeyDown(KeyCode.R)) {
    50.                 CheckpointManager.Instance.Respawn(controller);
    51.             }
    52.             // to do here: implement ability to have holdslide without it erroring out on levels without one
    53.             //if ((Input.GetKey(KeyCode.LeftControl) || HoldSlide.Instance.holdSlide == true)  stationaryTimer < TimeAllowedStationary) {
    54.             if (Input.GetKey(KeyCode.LeftControl)  stationaryTimer < TimeAllowedStationary) {
    55.                 isSliding = true;
    56.                 controller.slopes.maxRotation = MaxSlideRotation;
    57.             } else {
    58.                 isSliding = false; 
    59.                 for (n = 0; n < SideColliderElements.Length; n++) {
    60.                     currentCollider = SideColliderElements[n];
    61.                     controller.sides[currentCollider].offset.y = sideColliderOriginalOffset[n];
    62.                 }
    63.                 controller.slopes.maxRotation = prevAngle;
    64.                 slideTimer = 0;
    65.                 // if the player lets go, we can reset the timer and let him initiate a slide again
    66.                 if (Input.GetKeyUp(KeyCode.LeftControl)) stationaryTimer = 0;
    67.             }
    68.             if (isSliding) {
    69.                 //only move the colliders up if we've been sliding a little while and at a certain speed
    70.                 if (controller.Velocity.x > MinStartSlideVel || controller.Velocity.x < -MinStartSlideVel) slideTimer += Time.deltaTime;
    71.    
    72.                 if (slideTimer > SlideTime) {
    73.                     for (n = 0; n < SideColliderElements.Length; n++) {
    74.                         currentCollider = SideColliderElements[n];
    75.                         controller.sides[currentCollider].offset.y = SideColliderDesiredOffset;
    76.                     }  
    77.                 }
    78.                 // Reduce drag each frame to make it easier to slide
    79.                 controller.SetDrag(drag);
    80.                 // Add velocity based on slope
    81.                 float angle = controller.transform.localEulerAngles.z;
    82.                 if (controller.CurrentDirection == 1) {
    83.                     //sliding forwards, good to go
    84.                     if (angle > 180) angle -= 360;
    85.                     angle *= -1;
    86.                     #region test slope speed at constant vel
    87.                     /*
    88.                     Debug.Log(angle);
    89.                     if (angle < -90) {
    90.                     //threshold point
    91.                         controller.Velocity = new Vector2(controller.Velocity.x + (drag * RaycastCharacterController.FrameTime), controller.Velocity.y);
    92.                     } else if (angle < 0  angle > -90) {
    93.                         //we're heading up a slope
    94.                         controller.Velocity = new Vector2(controller.Velocity.x + (10f * RaycastCharacterController.FrameTime), controller.Velocity.y);
    95.                     } else {
    96.                         //we're sliding down a slope
    97.                         controller.Velocity = new Vector2(controller.Velocity.x + (50f * RaycastCharacterController.FrameTime), controller.Velocity.y);
    98.                     }*/
    99.                     #endregion
    100.                     controller.Velocity = new Vector2(controller.Velocity.x + (acc * angle * RaycastCharacterController.FrameTime), controller.Velocity.y);
    101.                 } else {
    102.                     //sliding backwards - code to be edited
    103.                     if (angle > 180) angle -= 360;
    104.                     angle *= 1;
    105.                     controller.Velocity = new Vector2(controller.Velocity.x - (acc * angle * RaycastCharacterController.FrameTime), controller.Velocity.y);
    106.                 }
    107.                 // Check for exit
    108.                 if (!controller.IsGrounded(0.25f)) {
    109.                     fallTimer += Time.deltaTime;
    110.                     //seeing as we've left the ground, we can reset the rotation here
    111.                    
    112.                 } else {
    113.                     fallTimer = 0.0f;
    114.                 }
    115.                 if (fallTimer > fallTime) {
    116.                     isSliding = false;
    117.                     controller.slopes.maxRotation = prevAngle;
    118.                 }
    119.                
    120.                 // if we're moving too slow and still 'sliding', start the counter to take us out of a slide
    121.                 if (controller.CurrentDirection == 1) {
    122.                     if (controller.Velocity.x <= ThresholdVelocity  isSliding) {
    123.                         stationaryTimer += Time.deltaTime;     
    124.                     }
    125.                 } else {
    126.                     if (controller.Velocity.x >= -ThresholdVelocity  isSliding) {
    127.                         stationaryTimer += Time.deltaTime;     
    128.                     }
    129.                 }
    130.                 // Change animation state to show its sliding
    131.                 controller.ForceSetCharacterState(CharacterState.CROUCH_SLIDING);
    132.             } else {
    133.                 if (Input.GetKey("right") ) {
    134.                     x = 0.5f;
    135.                 } else if (Input.GetKey("left") ) {
    136.                     x = -0.5f;
    137.                 }
    138.                 // Shift to run
    139.                 if (alwaysRun || Input.GetKey(KeyCode.LeftShift)) {
    140.                     x *= 2;
    141.                 }
    142.                 //climbing up / down
    143.                 if (Input.GetKey("up") ) {
    144.                     y = 1;
    145.                 } else if (Input.GetKey("down") ) {
    146.                     y = -1;
    147.                 }
    148.                 if (Input.GetKey(KeyCode.Space) ) {
    149.                     jumpButtonHeld = true;
    150.                     if (Input.GetKeyDown(KeyCode.Space)) {
    151.                         jumpButtonDown = true;    
    152.                     } else {
    153.                         jumpButtonDown = false;
    154.                     }
    155.                 } else {
    156.                     jumpButtonDown = false;
    157.                 }
    158.             }
    159.         }
    160.     }
    161. }
     
    Last edited: Nov 3, 2013
  15. SnakeTBs

    SnakeTBs

    Joined:
    Sep 24, 2013
    Posts:
    2
    How create a different jump (looks like SMB), short (tap button) and long(hold button)?
     
  16. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Do you want two jumps, short and long, or do you want holding the button to make you jump higher (so you can control the height by holding for longer).

    Option 2 can be done with the jumpHeldTime and jumpFrameVelocity settings. I think thats how most games work.

    Option 1 would require a few extra lines of code in your input control. The idea would be that if the user holds the jump button down you use the jumpHeldTime... BUT instead of releasing when the user releases, you have your own timer that always "holds down" the button for the same time. You might need to adjust the jumpFrameVelocity from your input control too.
     
  17. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    I'll try to take a look in the next few days.

    - John A
     
  18. kraaijmakers

    kraaijmakers

    Joined:
    May 2, 2013
    Posts:
    14
    Hey Johnny, I am using the latest stable version of Unity. 4.2.2f, the free version :)
     
  19. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Submitted 1.8.1 - This includes the Mecanim Beta (I've decided to call it a beta to make it clear I still plan on improving it).

    Next up will be a bug fix update hopefully in the next week or so and then a decision on what the next major update should be.
     
  20. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    A few people have been pretty happy with this asset and even offered to pay more. I don't want more, but if you would like to donate to the Movember charity on my behalf here's a link:

    https://www.movember.com/au/donate/payment/member_id/8439981/
    (plus you get to see me with by beard shaved off ... a rare thing)

    Movember is a charity (yes you should be able to write it off come tax time ;) ) promoting mens health with a focus on various cancers (of which I have had some personal experience). Its very big in Australia not sure how if its taken off much world wide.

    Find out more about Movember here: movember.com
     
    Last edited: Nov 6, 2013
  21. Dan_Tsukasa

    Dan_Tsukasa

    Joined:
    Jan 26, 2013
    Posts:
    155
    It's pretty big in England too, all for a good cause.

    I did it last year but this year I unfortunatly don't have the chance to give it another go, somehow borderline badly grown comical Mustaches aren't so useful for client facing positions.
     
  22. derkoi

    derkoi

    Joined:
    Jul 3, 2012
    Posts:
    2,260
    Johnny, can you help me please. For some reason I just can't get a touch controller to either double jump or jump hold for a different height.

    I tried modifying your simplecharacterinput:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. /// <summary>
    5. /// A simple character input. Arrows to move, left SHIFT to run, SPACE to jump.
    6. /// </summary>
    7. public class SimpleCharacterInput : RaycastCharacterInput
    8. {
    9.  
    10.     public TouchController  touchCtrl;
    11.  
    12.     void LateUpdate ()
    13.     {
    14.         x = 0.5f;
    15.        
    16.         TouchZone leftTouch = this.touchCtrl.GetZone(1);
    17.         TouchZone rightTouch = this.touchCtrl.GetZone(0);
    18.        
    19.         jumpButtonHeld = false;
    20.         jumpButtonDown = false;
    21.  
    22.             if (rightTouch.Pressed(0, true, true)) {
    23.                 jumpButtonDown = true; 
    24.                 jumpButtonHeld = true; 
    25.             } else {
    26.                 jumpButtonDown = false;    
    27.                 jumpButtonHeld = false;
    28.             }
    29.        
    30.     }
    31.    
    32. }
    I'm using Controlfreak. It works but just jumps. Previously I tried playmaker and NGUI. All the same, but with the keyboard it works fine.
     
  23. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Firstly input should run in Update() not LateUpdate(). If you do it in LateUpdate you would have to set script execution order to ensure that it happens BEFORE the controller movement executes.

    Beyond that jumpButtonDown should be set in the first frame that you press jump, but no other frames.

    jumpButtonHeld should be set for every frame that you have the button pressed.

    Certainly there seems to be an issue in your current code because you treat jumpButtonHeld and jumpButtonDown the same. They are not the same.

    It should be like this:
    Code (csharp):
    1.  
    2. jumpButtonDown = false; // default to false;
    3. jumpButtonDown = false; // default to false;
    4.  
    5. if (buttonPressedDownThisFrame()){
    6.   jumpButtonDown = true;
    7.   jumpButtonHeld = true;
    8. } else if (buttonHeldDown) {
    9.   jumpButtonHeld = true;
    10.   // Notice that if jump button is not pressed in this frame we leave jumpButtonDown = false;
    11. }
    12.  
    Obviously that is psuedo code.

    I have no idea how ControlFreak works so I don't know what Pressed(0, true, true) is exactly. Do you have API doc for it?
     
    Last edited: Nov 7, 2013
  24. Dre_On_Unity

    Dre_On_Unity

    Joined:
    May 22, 2013
    Posts:
    16
    I'm not sure if this is covered earlier in the thread, but I read through about 25 pages before I gave up. So here's the question/problem. When I'm using passthrough platforms, pushing down will make the character fall through every passthrough platform until he hits solid ground. So if I have a vertical sequence of 3 jumps to go up 3 floors, pushing down on the third floor causes you to fall all the way to ground, despite the other passthrough floors being there. How can I just tap down to go through a single platform?
     
  25. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Pretty sure there's a timer on it. Reduce the timer to the minimum amount to clearly make it through the platform, but no more.

    Thats a quick solution, to be honest as long as your platforms are normally sized it should work pretty well.

    The alternative would be to write your own platform class extension. One possibility would be to simply turn off the platforms collider (or set ignore collisions) when the user presses down. Turn it back on after a timer expires (or after the character has passed through it if you prefer). You should be able to start with the existing pass through code, and instead of setting the fall through timer when user presses down you can turn off the collider and start an internal timer.

    EEDIT: Not sure of your background, but if its not in coding I'd be happy to write this up when I am in front of Unity.
     
  26. Dre_On_Unity

    Dre_On_Unity

    Joined:
    May 22, 2013
    Posts:
    16
    Durrrr. I guess I should have looked at the script a little closer. Thanks for the quick response. Works just fine. :)
     
  27. derkoi

    derkoi

    Joined:
    Jul 3, 2012
    Posts:
    2,260
    Thanks Johnny, i couldn't find an API for it online, so uploaded the included HTML API here
     
  28. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Submitted bug fix for the walk speed clamping in Physics like movement (raised a few pages back). Heres the line that needs to be fixed if its bugging you now:

    Change < to > in line 579:

    } else if (velocity.x > movement.walkSpeed * -1 characterInputX <= 0.0f) {
     
  29. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    The wording isn't very clear but I think what you would be looking for is

    jumpButtonDown = JustPressed

    and

    jumpButtonPressed = Pressed
     
  30. SteveJ

    SteveJ

    Joined:
    Mar 26, 2010
    Posts:
    3,085
    Quick question...

    In the animator Update() function, the following code rotates the player character toward their facing direction:

    Code (csharp):
    1.  
    2. transform.localRotation = Quaternion.RotateTowards(transform.localRotation, targetRotation, Time.deltaTime * 400.0f);
    3.  
    Can anyone think of a simple way to have them rotate in the opposite direction? i.e. currently my character rotates to his left, AWAY from the camera, so you see his back as he turns. I'd like him to rotate to his right so that his face passes the camera as he turns.

    I've tried a few things and come up empty. It's got me stumped, but I'm guessing it should be fairly simple.
     
    Last edited: Nov 8, 2013
  31. secret-arts

    secret-arts

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

    I'm still really loving 2D Platform Controller, so thank you for all your hard work in supporting it.

    I have a quick question that may have already been addressed: is there exiting functionality in platforms to register when the character controller is no longer touching it? In short, in my game I want to have pressure switches that react when a character stands on them and slowly go back in place when the character is no longer standing on them. As far as I've seen, it doesn't look like that's built-in already (i.e. DoAction only detects when the controller is in contact).

    Thanks again!
    --Chris
     
  32. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Hi Steve the basic idea would be that you want to turn using the shortest rotation (which the helper function gives you) except in the case where you are very close to a 180 degree turn in which case you want to force the character to rotate first to a direction facing the camera.

    Another option would be to do it "manually" which might be easier to understand. Get the angle for the rotation by doing

    float angle = Quaternion.Angle(transform.localRotation, targetRotation);

    eventually you will apply this rotation, something like:

    transform.RotateAround (transform.position, Vector3.up, angle * Time.deltaTime * speed);

    The final step is to constrain the value of angle, based on what you want to do. For example if characters CurrentDirection == 1 you would want to rotate in a negative direction instead of a positive so you could do:

    if (controller.CurrentDirection == 1) angle *= -1;

    You would also likely want to cap the angle so the character doesn't turn really fast when they start to turn then gradually slow down:

    angle = Mathf.Min(angle, 1);

    Finally you would need some additional controls for facing ladders/ropes.

    This will give you total control of the rotation but obviously takes a few more lines of code.

    If you get stuck let me know and I'll take a look at putting something together.
     
  33. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Or instead of writing all that I could just open Unity and write the solution:

    Code (csharp):
    1.  
    2.     void Update() {
    3.         CheckDirection ();
    4.         transform.localRotation = Quaternion.RotateTowards (    transform.localRotation,
    5.                                                                 (Quaternion.Angle (transform.localRotation, targetRotation) >= 180) ? Quaternion.Euler(0, 180, 0) : targetRotation,
    6.                                                                 Time.deltaTime * 400.0f);
    7.     }
    8.  
    You might be better off using a slightly smaller value than 180 (e.g. 179), not sure if floating point errors could cause an issue.
     
  34. Kafar

    Kafar

    Joined:
    Nov 29, 2012
    Posts:
    220
    Hi Johnny,

    I'm using your controller on my project but I have a bit issue with Jump movement on my character. I'm using the controller code inside your 2DTK sample.
    In a few words, when I press space to jump my character from ground cross the ground and go down, but not jump. Other movements are ok, the problem is with jump only.
    What I'm missing?

    Thanks in advance

    -Kafar
     
  35. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Hi Kafar,

    are you saying you go downwards when you press jump? Did you start with the prefab?

    Maybe your axis are XZ instead of XY? You should be viewing/building your scene from the 'back' view with Y going up and X going right.

    Check jump values like velocity and acceleration are positive.

    Other than that, send my a copy of your project so I can take a look, or if thats not possible screenshot your colliders in your level and your character setting and send them to me (best to use support email address supplied in the documentation, please include your order number in any email).

    Regards,

    John A
     
  36. secret-arts

    secret-arts

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

    I think you may have missed my question above :) Basically what I'm looking for is a way to handle making a platform as an on/off switch based on having the character stand on it. Thanks again!
     
  37. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Hi mate,

    I did miss it :)

    There's no built-in way to do this, but you can emulate it pretty easily using a short timer that resets whenever the character is on the platform (see the Decaying Platform and its characterIsOnMe variable as an example).

    Also if you aren't affecting movement consider just using a normal Unity trigger. I usually use them for damage, collectibles and switches.

    By the way if anyone is interested you can search just this thread in google using:

    site:http://forum.unity3d.com/threads/173640-Released-2D-Platform-Controller <YOUR SEARCH TERMS HERE>

    Doing that I found the following relevant results:

    http://forum.unity3d.com/threads/173640-Released-2D-Platform-Controller/page47

    It's only per page results, but its better than trawling 50+ pages :)

    - John A

    PS If that isn't clear enough Secret Arts let me know and i'll write an example.
     
    Last edited: Nov 9, 2013
  38. Dre_On_Unity

    Dre_On_Unity

    Joined:
    May 22, 2013
    Posts:
    16
    Here's another problem I'm having. I'm using your touch inputs on android. When I use your run button, the character automatically moves at run speed despite the button not being pushed (or on screen even). On the touch controller script I have checked and unchecked "allow run." Even with it off, the character only moves at running speed. I have set the color of the held texture to show when it's being touched and it changes when touched, but doesn't change back when released (as if it's still being held). I'm not sure what to do. Some help would be greatly appreciated.
     
  39. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Hi,

    firstly do the other buttons work? They all use identical code.

    Secondly, can you double check the value for "xButtonValue". If this is 1.0f or bigger the character will run anyway, for walking I usually go with 0.5 (although anything under 1.0f should work). This is obviously not a great default although it does get a mention it in the comments/documentation.

    Can you check colliders are in the right spot and of the right size (maybe you are moving the button not the collider)?

    Is the button on the right layer? Is that layer set up so nothing can collide with it?

    Is the button in the list:
    public List<TouchControllerButton> buttons;

    After that it if the other buttons are working it seems a bit strange (there is only one piece of button code, not different code for each button). We will have to dig deeper, maybe something to do with the button events sent by your device (but then why would the others work).


    - John A

    PS Sorry if these things seem trivial, need to ensure they are all okay before moving on to anything more complex.
     
    Last edited: Nov 9, 2013
  40. Dre_On_Unity

    Dre_On_Unity

    Joined:
    May 22, 2013
    Posts:
    16
    Changing the Xbutton Value worked. I set it to .75 because at .5 everything felt like it was going in slow motion. What does it do? Do a sort of analog version of the button where instead of pushing it 100% it gives it a partial press? Also, the graphical issue button press still exists, although it isn't an issue for me as I only use it to debug. Thanks for the quick reply.

    Also, the other buttons all work fine and are on the same layer.
     
    Last edited: Nov 9, 2013
  41. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    At its core input control class is analog and if you use physics style movement this analog nature will affect your game. This allows for various effects like changing speed the longer you hold the button, or joysticks for variable speed, etc. On a touch control the analogue doesn't make a lot of sense (although you could make it so that your position on the button controlled the speed ... i.e. moving further left goes faster to the left).

    For most mobile implementations pick a value that works and stick with it :)
     
  42. Dan_Tsukasa

    Dan_Tsukasa

    Joined:
    Jan 26, 2013
    Posts:
    155
    If you're looking for suggestions I have one or 2, nothing too specific.

    Improved Push/Pull, but using Hinge joints, this would mean terrain wouldn't have to be flat in order to work, it'd also mean it takes the objects weight into account.

    Swinging platform (hanging on a rope or something).

    Curious if you ever had a shot at the Limbo-esque tree push at all.
     
  43. SteveJ

    SteveJ

    Joined:
    Mar 26, 2010
    Posts:
    3,085
    Hey thanks for this. I'll play around with it some more and post back if I find a workable solution.

    EDIT: I'm also needing to have the character face "in" to the screen on a forward press of the joystick/keyboard and have that fire an event. I think that's something that would be worth you implementing as a "feature" of the asset as it's fairly common in a platformer (e.g. Wonderboy Monsterland type doors, Cave Story, etc).
     
    Last edited: Nov 11, 2013
  44. Brutang

    Brutang

    Joined:
    Nov 1, 2013
    Posts:
    23
    Hello,

    I wrote a script to make the character face the mouse. It works properly if you're not moving, or moving in the direction your mouse is pointed.

    My issue is if your mouse is on the Left of the character (and you're character is looking Left) then move Right, the RaycastCharacterController updates your rotation to face the direction you're moving. After that, if I move my mouse from Left to Right of the character's position, he then flips backwards. Moving the mouse left and right over him makes him flip flop the opposite direction until I move the direction of the mouse to correct it.

    My question is, how can I disable the rotate chracter's X rotation on move input so I can use my script to control 100% of the character's rotation?

    Code (csharp):
    1.  
    2.  var Player:GameObject;
    3. private var targetrotation:int=0;
    4.  function Update()
    5. {
    6.     CrossHair = GameObject.Find("Crosshair");
    7.     if (CrossHair.transform.position.x < Player.transform.position.x)
    8.     {
    9.         targetrotation=180;
    10.     }
    11.         if (CrossHair.transform.position.x > Player.transform.position.x)
    12.     {
    13.         targetrotation=0;
    14.     }
    15.     transform.eulerAngles.y-=(transform.eulerAngles.y-targetrotation);
    16. }
    17.  
    EDIT: for clarity, I should say the player rotates to the crosshair game object which is bound to the mouse X,Y.


    Thank you!

     
    Last edited: Nov 11, 2013
  45. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    SteveJ ... you did see the next post where I posted the solution right...
     
  46. SteveJ

    SteveJ

    Joined:
    Mar 26, 2010
    Posts:
    3,085
    I'm nothing if not unobservant :)
     
  47. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,422
    Any news on a ropebridge sample or some code for the behaviour?
    I'm struggling to get it work.

    For now I have this:

    Code (csharp):
    1. override public void DoAction(RaycastCollider collider, RaycastCharacterController character)
    2.     {
    3.        
    4.         if (collider.direction == RC_Direction.DOWN) {
    5.             characterIsOnMe = true;
    6.             myTransform.position = new Vector3(myTransform.position.x, myTransform.position.y+pressureForce, myTransform.position.z);
    7.            
    8.             if(characterIsOnMe)
    9.             {
    10.                 if(myTransform.position.y <= max)
    11.                 {
    12.                     myTransform.position = new Vector3(myTransform.position.x, max, myTransform.position.z);
    13.                 }
    14.             }
    15.         }
    16.     }
    But this does not look nice. Besides I can't figure out how to get the platform back to it's initial y-position after the character leaves the platform.

    Would appreciate some help on this.
     
  48. StephanM

    StephanM

    Joined:
    Aug 20, 2013
    Posts:
    25
    Hi Johnny, I just got this yesterday. Looks like the best asset for a 2.5D platformer. A couple questions...

    1) Can you make the 3D model work with 2D Toolkit levels or something like Ferr2D Terrain Tool?
    2) Can you swap out character models but keep all the animations?
    3) Can you add animations to the existing list?

    Thanks,
    Stephan
     
  49. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    @BTStone I've got some time tomorrow to work on 2DPC I'll make a rope bridge a priority.

    @StpehanM

    1. Yes, there's not really anything you need to do to mix up 2D and 3D other than ensuring colliders are at the same z position. Not sure on Ferr2D as I haven't used it, but if it generated colliders it should be fine.

    2. If you use mecanim yes. Legacy animations don't automatically retarget.

    3. Yes. The animator code is just a sample and easy to extend. For example to add a "Teeter on Ledge" animation you might add this to the Idle animation code:

    Code (csharp):
    1.  
    2. if (controller.groundedFeetCount = 1) { // If only one of our colliders is on the ground we are on an edge
    3.   animation.CrossFade("Teeter");
    4. } else {
    5.   animation.CrossFade("Idle");
    6. }
    7.  
     
  50. Seven

    Seven

    Joined:
    Apr 23, 2012
    Posts:
    111
    They play along fine together so far for me, the only issue being that ledge grabs teleport the player to an invisible edge. Assuming it's something to do with how i'm setting up colliders though lol.