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

Question Jump pad With Character Controller

Discussion in 'Scripting' started by TheAPGames, Dec 6, 2022.

  1. TheAPGames

    TheAPGames

    Joined:
    Jun 1, 2020
    Posts:
    44
    Hello, I'm creating a jump pad that would launch the player up in the air. I'm using a character controller, in 3D. The issue seems to be that the character snaps up in Y, and without any "hang time" before it drops down. How do i polish the movement in my code? Thank you for taking a look.

    Code (CSharp):
    1. using DG.Tweening;
    2. using DG.Tweening.Plugins;
    3. using UnityEngine;
    4.  
    5. public class PlayerController : MonoBehaviour
    6. {
    7.     public static PlayerController instance;
    8.  
    9.  
    10.     public CharacterController controller;
    11.     public float moveSpeed;
    12.     public float jumpForce;
    13.     public float rotationSpeed;
    14.     public float gravityScaler;
    15.     public bool isGrounded;
    16.     public Animator myAnimator;
    17.     public GameObject playerModel;
    18.     private Vector3 moveDirection;
    19.  
    20.  
    21.    
    22.    
    23.     private Camera theCam;
    24.  
    25.     public GameObject jumpFx;
    26.  
    27.     public float jumpGracePeriod;
    28.     private float? lastGroundTime;
    29.     private float? jumpButtonPressedTime;
    30.  
    31.     private Vector3 jumpPadDirection;
    32.     public float jumpPadForce;
    33.  
    34.     public bool stopMove;
    35.  
    36.  
    37.  
    38.  
    39.     private void Awake()
    40.     {
    41.         instance= this;
    42.     }
    43.  
    44.  
    45.     // Start is called before the first frame update
    46.     void Start()
    47.     {
    48.      
    49.         theCam = Camera.main;
    50.     }
    51.  
    52.     // Update is called once per frame
    53.     void Update()
    54.     {
    55.  
    56.         if(!stopMove)
    57.         {
    58.             float yStore = moveDirection.y;
    59.  
    60.             moveDirection = (transform.forward * Input.GetAxisRaw("Vertical")) + (transform.right * Input.GetAxisRaw("Horizontal"));
    61.             moveDirection.Normalize();
    62.             moveDirection = moveDirection * moveSpeed;
    63.             moveDirection.y = yStore;
    64.  
    65.  
    66.  
    67.             //Jump
    68.             if (controller.isGrounded)
    69.             {
    70.  
    71.                 lastGroundTime = Time.time;
    72.             }
    73.             if (Input.GetButtonDown("Jump"))
    74.             {
    75.                 jumpButtonPressedTime = Time.time;
    76.             }
    77.  
    78.             if (Time.time - lastGroundTime <= jumpGracePeriod)
    79.             {
    80.                 moveDirection.y = 0f;
    81.  
    82.                 if (Time.time - jumpButtonPressedTime <= jumpGracePeriod)
    83.                 {
    84.                     moveDirection.y = jumpForce;
    85.                     jumpButtonPressedTime = null;
    86.                     lastGroundTime = null;
    87.                     myAnimator.SetTrigger("Jump");
    88.                     myAnimator.SetInteger("JumpIndex", Random.Range(0, 3));
    89.                     Instantiate(jumpFx, gameObject.transform.position, Quaternion.Euler(90, 0, 0));
    90.                     AudioManager.instance.PlaySFX(0);
    91.                     AudioManager.instance.PlaySFX(1);
    92.  
    93.                 }
    94.             }
    95.  
    96.  
    97.             //Gravity
    98.             moveDirection.y += Physics.gravity.y * Time.deltaTime * gravityScaler;
    99.             controller.Move(moveDirection * Time.deltaTime);
    100.  
    101.             //Camera
    102.             if (Input.GetAxisRaw("Horizontal") != 0f || Input.GetAxisRaw("Vertical") != 0f)
    103.             {
    104.                 transform.rotation = Quaternion.Euler(0f, theCam.transform.rotation.eulerAngles.y, 0f);
    105.                 Quaternion newRotation = Quaternion.LookRotation(new Vector3(moveDirection.x, 0f, moveDirection.z));
    106.                 playerModel.transform.rotation = Quaternion.Slerp(playerModel.transform.rotation, newRotation, rotationSpeed * Time.deltaTime);
    107.             }
    108.  
    109.             myAnimator.SetFloat("Speed", Mathf.Abs(moveDirection.x) + Mathf.Abs(moveDirection.z));
    110.  
    111.  
    112.         }
    113.         if (stopMove)
    114.         {
    115.             moveDirection = Vector3.zero;
    116.             moveDirection.y += Physics.gravity.y * Time.deltaTime * gravityScaler;
    117.             controller.Move(moveDirection);
    118.             myAnimator.SetFloat("Speed", 0);
    119.          
    120.  
    121.         }
    122.  
    123.  
    124.     }
    125.  
    126.  
    127.  
    128.     public void JumpingPad()
    129.     {
    130.         float yStore = jumpPadDirection.y;
    131.         jumpPadDirection.y = jumpPadForce;
    132.  
    133.         Vector3 moveUp = new Vector3(transform.position.x, jumpPadForce, transform.position.z);
    134.  
    135.         controller.Move(moveUp * Time.deltaTime);
    136.     }
    137.  
    138.  
    139. }
    140.  
    This is my Jump Pad Script.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using System.Security.Cryptography;
    4. using UnityEngine;
    5.  
    6. public class JumpPad : MonoBehaviour
    7. {
    8.     private Animator myPadAnimator;
    9.  
    10.     private void Start()
    11.     {
    12.         myPadAnimator= GetComponent<Animator>();  
    13.     }
    14.     public void OnTriggerEnter(Collider other)
    15.     {
    16.         if(other.tag == "Player")
    17.         {
    18.             PlayerController.instance.JumpingPad();
    19.             myPadAnimator.SetTrigger("PushUp");
    20.         }
    21.     }
    22.  
    23.  
    24. }
    25.  
     
  2. TheAPGames

    TheAPGames

    Joined:
    Jun 1, 2020
    Posts:
    44
    Here is the visual result :

    https://im5.ezgif.com/tmp/ezgif-5-534a75b815.gif

     
  3. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,612
    You should only make one call to
    CharacterController.Move()
    per frame.

    Said method takes a direction, and you can easily 'build' a direction by adding directional vectors together. So a jump pad would just add a large vertical directional vector to the vector you build each frame, which gets tapered off naturally via gravity.
     
    TheAPGames likes this.
  4. TheAPGames

    TheAPGames

    Joined:
    Jun 1, 2020
    Posts:
    44
    Thank you for your reply, could you explain a bit further? I didn't fully understand the logic here.
     
  5. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,612
    No problem.

    As mentioned it's pretty easy to add vectors together. A super basic character controller could be boiled down to:
    Code (CSharp):
    1. private void Update()
    2. {
    3.    float xInput = Input.GetAxis("Horizontal");
    4.    float zInput = Input.GetAxis("Vertical");
    5.  
    6.    Vector3 movementInput = new Vector3(xInput, 0, zInput);
    7.    Vector3 gravity = new Vector3(0, -9.8f, 0);
    8.  
    9.    Vector3 finalVector = (movementInput + gravity) * Time.deltaTime;
    10.  
    11.    characteController.Move(finalVector);
    12. }
    You make a vector for input, and for gravity, and just slap them together.

    Obviously this doesn't include jumping. But that should be easy to add. You simply maintain another Vector3 (one scoped to the class, rather than the method), modify it's y component over time, then add that plus your movement vector together for the right result.

    A jump pad follows pretty much the same logic as jumping.

    In a character controller I've done, it all boiled down to:
    Code (CSharp):
    1. Vector3 finalDirection = (movementInput + verticalVelocity + externalForces) * Time.deltaTime;
    2. characteController.Move(finalDirection);
     
  6. TheAPGames

    TheAPGames

    Joined:
    Jun 1, 2020
    Posts:
    44
    Thanks again, bare with me please, so i can get it right..
    So In the Playercontroller, i wouldn't need to have an extra method to be called from Jumping Pad script? Then how would i call it when player triggers the "jump Zone" ?
     
  7. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,612
    You'd still have a method, just not a 'jump pad' specific one. Instead a more general one that allows outside objects to mutate one or more of the directional vectors you build.

    Super basic example:
    Code (CSharp):
    1. //somewhere in your CC script:
    2. private Vector3 verticalVelocity;
    3.  
    4. public void ModifyVerticalVelocity(Vector3 velocity)
    5. {
    6.     verticalVelocity += velocity;
    7. }
    8.  
    9. //jump pad
    10. public class JumpPad : MonoBehaviour
    11. {
    12.     public void OnTriggerEnter(Collider other)
    13.     {
    14.         if (other.TryGetComponent(out PlayerController controller))
    15.         {
    16.             Vector3 velocity = Vector3.up * 10f;
    17.             controller.ModifyVerticalVelocity(velocity);
    18.         }
    19.     }
    20. }
     
  8. TheAPGames

    TheAPGames

    Joined:
    Jun 1, 2020
    Posts:
    44
    Thank you, i ll have a go and try to understand it all and will reply here. A lot of new content.
     
    spiney199 likes this.
  9. TheOriginal23

    TheOriginal23

    Joined:
    Jan 26, 2024
    Posts:
    1
    Why I am getting private modifier not valid?