Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

3D platformer movement

Discussion in 'Scripting' started by madeer, Jan 24, 2020.

  1. madeer

    madeer

    Joined:
    Aug 2, 2018
    Posts:
    5
    Hi,
    i am having trouble figuring out the proper way to move my character left to right how i want. Currently i am moving him with this script, and its working fine, except that the distance the player is moving to the side is not always the same.
    Code (CSharp):
    1.  
    2. if (Input.GetKeyDown(KeyCode.A))
    3. {
    4.                 myRb.velocity = new Vector3(myRb.velocity.x, myRb.velocity.y, sideMoveMultiplier);
    5. }
    6. if (Input.GetKeyDown(KeyCode.D))
    7. {
    8.                 myRb.velocity = new Vector3(myRb.velocity.x, myRb.velocity.y, -sideMoveMultiplier);
    9. }
    10.  
    I would like the player to be able to move left and right always the same distance. I have tried with transform.Translate but that teleports the player to the position rather then playing an animation and moving the distance in time. I also found the GridMove script but it is not fluid enough.

    Thank you all for any kind of info and help you can give.
     

    Attached Files:

  2. Inxentas

    Inxentas

    Joined:
    Jan 15, 2020
    Posts:
    277
    How is the variable sideMoveMultiplier constructed? If that value doesn't change over time, and external force must be working on the object. What is your ground like? A slight rotation of a plane could make your RigidBody "slip" if it doesn't have enough friction. Yet you don't mention it moving around when idle, so my best guess is that sideMoveMultiplier isn't a constant value.

    I'm not sure if this is causing the issue, but you'd typically use AddForce() to move RigidBodies around by script instead of directly affecting velocity value. You should treat that value as the "end result" of all physics calculations. A similar problem is described here.

    Tip: Using ForceMode.VelocityChange for the second parameter of AddForce() will ignore mass and generally give you more tight control.
     
    madeer likes this.
  3. madeer

    madeer

    Joined:
    Aug 2, 2018
    Posts:
    5
    Thank you for the reply, the ForceMode.VelocityChange fixed the problem with uneven side movement and its working great. The sideMoveMultiplier is a constant float that i just change before trying it in play mode, nothing is changing that value during runtime.

    But now i have another problem, the add force is working fine as long as i don't spam. I would like the player to always snap to a position, if they change their mind mid movement to the side. The end result of their side movement will always be either at 0,1,-1,2,-2 and so on.
    On the picture i wanted to demonstrate the lines where the player will be moving, if the player is on 0 and pressed left they will go to -1 but if they change their mind mid way and press right the player will end up on 0.
     

    Attached Files:

  4. Inxentas

    Inxentas

    Joined:
    Jan 15, 2020
    Posts:
    277
    Glad it helped!

    I could be wrong, but it seems to me you're going for one of these games where the player is only allowed to snap to a lane. If that's the case, you might be better served by game rules that don't use physics for input control.

    Imagine a lane switch taking X time. When the Input's horizontal axis becomes higher then zero, the player is trying to switch lanes. If the axis becomes zero again before "half of X" has passed, the player's move is cancelled and he snaps back to his previous lane. If the time is above "half of X" then the move can no longer be cancelled and the player snaps to the lane right or left of him (depending on the axis).

    Example: suppose you give the player 1 second of "switch lane time". When the horizontal axis is not zero, an internal stopwatch resets and starts counting. When the axis is zero again, the script checks the time. If the button was released within a 0.5 second window, the move is canceled. When the stopwatch does reach 1 second, the full move is executed and the timer resets.

    Since you know how long a move takes and how much space there is between lanes, you could animate the whole process. In this case I'd make my player have a kinetic rigidbody and a collider so I could still use phyics to check for collisions along the track.
     
    madeer likes this.
  5. madeer

    madeer

    Joined:
    Aug 2, 2018
    Posts:
    5
    Yeah that's what i'm going for, and i started like that because it felt right and the way i wanted(with my very limited knowledge).
    The example you explained sounds just what i needed. And i found a free asset that helps with paths the player can take, if anybody will be interested.