Search Unity

Momentum with Character Controller

Discussion in 'Scripting' started by TheDuples, Dec 13, 2018.

  1. TheDuples

    TheDuples

    Joined:
    Nov 13, 2018
    Posts:
    39
    I'm really not sure how to accomplish this. I would like my character to retain the speed at which they jumped instead of just dropping out of the sky when I release the jump button. Any advice or examples on how I could go about this?

    Code (CSharp):
    1. public class Movement : MonoBehaviour {
    2.    
    3.     public float speed;
    4.     public float airTime;
    5.     public float jumpForce;
    6.  
    7.     private float moveHorizontal;
    8.     private float moveVertical;
    9.  
    10.     public CharacterController player;
    11.     public GameObject cameraReference;
    12.  
    13.     private Vector3 moveDirection;
    14.  
    15.     public float gravityScale;
    16.     private float invertGravity;
    17.  
    18.     void Start () {
    19.        
    20.         invertGravity = gravityScale * airTime;
    21.         player = GetComponent<CharacterController>();
    22.      
    23.     }
    24.  
    25.     void Update () {
    26.         moveHorizontal = Input.GetAxis("Horizontal") * speed;
    27.         moveVertical = Input.GetAxis("Vertical") * speed;
    28.  
    29.         moveDirection = new Vector3(moveHorizontal, moveDirection.y, moveVertical);
    30.  
    31.         if (player.isGrounded)
    32.             {
    33.                            
    34.                 moveDirection.y = 0f;
    35.                 invertGravity = gravityScale * airTime;
    36.                
    37.                 if (Input.GetButtonDown("Jump"))
    38.                 {          
    39.                     moveDirection.y = jumpForce;
    40.                 }
    41.            
    42.             }
    43.        
    44.         if (Input.GetButton("Jump") && moveDirection.y != 0)
    45.             {
    46.                 invertGravity -= Time.deltaTime;
    47.                 moveDirection.y += invertGravity * Time.deltaTime;
    48.             }
    49.  
    50.         moveDirection.y = moveDirection.y + (Physics.gravity.y * gravityScale * Time.deltaTime);
    51.         player.Move(cameraReference.transform.TransformDirection(moveDirection * Time.deltaTime));
    52.    
    53.     }
    54. }
     
  2. JuozasK

    JuozasK

    Unity Technologies

    Joined:
    Mar 23, 2017
    Posts:
    84
    Does your character have a rigid body attached to it?

    If you want momentum, you could handle the jump by using Add Force on a Rigidbody object
     
  3. TheDuples

    TheDuples

    Joined:
    Nov 13, 2018
    Posts:
    39
    I'd rather not use rigidbodies for my character, they are too unpredictable. I'm using a character controller because the movement is much more precise.
     
  4. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    Just store the upward velocity in a Vector3 so you can continue to apply it, even when the player is not holding the button.

    When you press the jump button, create an upward velocity Vector3 so that you can store the upward velocity. During update. If the character is not grounded, add (gravity * Time.deltaTime) to your upward velocity vector, then add the upward velocity vector to your movement whether the person is holding the jump button or not.
     
  5. TheDuples

    TheDuples

    Joined:
    Nov 13, 2018
    Posts:
    39
    I'm not sure I understand, I created a vector3 called playerVelocity, but I can't seem to add (gravity * Time.deltaTime) to it, I get an error.

    Code (CSharp):
    1. if (Input.GetButtonDown("Jump"))
    2.                 {
    3.                     playerVelocity = new Vector3(0, moveDirection.y, 0);
    4.                     moveDirection.y = jumpForce;
    5.                 }            
    6.         }
    7.         if (player.isGrounded == false)
    8.         {
    9.             playerVelocity = playerVelocity + gravityScale * Time.deltaTime;
    10.         }
    Code (CSharp):
    1.  player.Move(cameraReference.transform.TransformDirection(playerVelocity + moveDirection * Time.deltaTime));
     
  6. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    Oops. I was thinking of Gravity as a Vector3 also, but yours is a float.

    You can just change :
    playerVelocity + gravityScale * Time.deltaTime;

    into
    playerVelocity + (Vector3.down * gravityScale * Time.deltaTime);

    and that should be more like what I had in mind.
     
    TheDuples likes this.
  7. TheDuples

    TheDuples

    Joined:
    Nov 13, 2018
    Posts:
    39
    I'm sorry for the late response, I haven't had time to work on this. When I try your code, my character no longer jumps high, it just kind of hops very briefly and there is still no momentum.
     
  8. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    Increase the initial upward velocity, and your character will jump higher. -or do you want to make it so that the player jumps higher the longer you hold the button down?
     
  9. TheDuples

    TheDuples

    Joined:
    Nov 13, 2018
    Posts:
    39
    Yes, I would like it to behave in the same way that my current jump script behaves.
    Code (CSharp):
    1. void Start () {
    2.      
    3.         invertGravity = gravityScale * airTime;
    4.         player = GetComponent<CharacterController>();
    5.    
    6.     }
    Code (CSharp):
    1. if (player.isGrounded)
    2.             {
    3.                          
    4.                 moveDirection.y = 0f;
    5.                 invertGravity = gravityScale * airTime;
    6.              
    7.                 if (Input.GetButtonDown("Jump"))
    8.                 {        
    9.                     moveDirection.y = jumpForce;
    10.                 }
    11.          
    12.             }
    13.      
    14.         if (Input.GetButton("Jump") && moveDirection.y != 0)
    15.             {
    16.                 invertGravity -= Time.deltaTime;
    17.                 moveDirection.y += invertGravity * Time.deltaTime;
    18.             }
    In my jump script I apply a downwards force when the jump button is let go.

    EDIT: sorry, I mean that I simply allow gravity to force the object down when the jump limit is reached, but if you hold the button, the amount of time it takes for that to happen is longer.
     
  10. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    My method was sort-of general-purpose method.
    To be honest, I don't really understand what you are doing with that whole invertGravity thing. I think I'd have to run this script myself if I were to be of any further help. I'll have to wait til I get home though.
     
    goodgamershow likes this.