- Home /
 
How to make a physics based jump with button hold effect
Hi I have made a character jump script for a sphere character which will make my character jump higher when the button is held.
(I have a wall jump mechanic as well.)
It works rather well, but it has a slight inconsistency in how high it jumps.
I don't know what causes this.
Can anybody help me out?
Here is my code:
 using UnityEngine;
 using System.Collections;
 
 public class BallController_Script : MonoBehaviour {
 
     //*Rigidbody to use
     private Rigidbody body;
     public float bodyZspeed;
     public float bodyXspeed;
 
     //Player input
     private float moveXinput = 0;
     private float moveYinput = 0;
     private bool jumpInput = false;
 
     //*Gravitation alteration variables
     //Used for rotation
     private float grafDirectionY = 0;
     private float grafDirectionX = 0;
     private float grafDirectionZ = 0;
     //Variables used for normalization of rotation's grafDirection (Normalization means the vectors axis are set to a scale of 0 to 1 where 1 is all the axis combined)
     private float grafDirection100Percent = 0;
     private float grafDirection1Percent = 0;
     //Used for jump (Jump does use negative values)
     private Vector3 grafDirection;
 
     //*Targeted objects
     public Transform CameraPivot;
     public Transform PlayerCamera;
     public Transform GravityPivot;
 
     //*Move by rotation variables
     //Acceleration/Deceleration
     public float accelerationSpeed = 0f;
     public float decelerationSpeed = 0f;
 
     //*Air movement
     //Acceleration
     public float airAccelerationSpeed = 0f;
     //Max velocity
     public float maxAirVelocity = 0f;
     //Temporary Vector
     private Vector3 tempVector;
     //Air moveInput
     private float airMoveXinput = 0;
     private float airMoveYinput = 0;
 
 
     //*Jump variables
     //The force wich is added overtime to jump
     public float jumpForce = 0f;
     //Some extra force used for opposite graf velocity
     public float jumpForceExtra = 0f;
     //How long the jump script will respond to Player input
     public float jumpTimeMax = 0f;
 
     //Used to reset jumpForce
     private float jumpForceBaseMemo = 0f;
     //How long the jump script is active
     private float jumpTime = 0f;
     //Used to block jump script
     private bool jumpNo = false;
 
     //*Collision variables
     //Stores the value of the last normal the object touches when it collided with a ground label object
     public Vector3 normal;
     //Used to store the angle betwean the up direction of gravity and the last touched normal
     public float normalAngle;
     //A variable used to see if the object is colliding with a ground label object
     public float Colide = 0;
     //Determines when the object may jump
     private bool onGround = false;
     //Delays the time the object isn't touching the ground (According to the offGround variable)
     public float offGroundDelay = 0;
     //Stores how long the object was actually off the ground before onGround is turned off
     private float offGroundTime = 0;
     //Stops the offGround script from looping
     private bool alreadyOffGround = true;
 
     void Start()
     {
         //Stores the start value of jumpForce
         jumpForceBaseMemo = jumpForce;
 }
 
     void Update()
     {
         //*Set's rigidbody to use
         body = GetComponent<Rigidbody>();
         bodyZspeed = body.velocity.z;
         bodyXspeed = body.velocity.x;
 
         //*Gets gravity direction
         //Gets my GravityPivot script
         GravityPivot_Script gravityPivot_Script = GravityPivot.GetComponent<GravityPivot_Script>();
         //GrafDirection jump
         grafDirection = gravityPivot_Script.grafDirection;
         //GrafDirection rotation
         grafDirectionY = gravityPivot_Script.grafDirection.y;
         grafDirectionX = gravityPivot_Script.grafDirection.x;
         grafDirectionZ = gravityPivot_Script.grafDirection.z;
         
 
         //*Move by rotation
         //Get move input
         moveXinput = Input.GetAxis("Horizontal");
         moveYinput = Input.GetAxis("Vertical");
 
         //Get camera axis
         Vector3 CamF = PlayerCamera.forward;
         Vector3 CamR = PlayerCamera.right;
 
         //Inverts grafDirection if negative (I don't need to make a diffrence in up and down the camera axis will determine that)
         grafDirectionY = (grafDirectionY < 0) ? grafDirectionY * -1 : grafDirectionY;
         grafDirectionX = (grafDirectionX < 0) ? grafDirectionX * -1 : grafDirectionX;
         grafDirectionZ = (grafDirectionY < 0) ? grafDirectionZ * -1 : grafDirectionZ;
 
         //Normalizes grafDirection vector (Normalization means the vectors axis are set to a scale of 0 to 1 where 1 is all the axis combined)
         //determines what is value graph direction is as a whole
         grafDirection100Percent = grafDirectionY + grafDirectionX + grafDirectionZ;
         //calculates the smallest value in 0 to 1 form
         grafDirection1Percent = 1 / grafDirection100Percent;
         //calculates what percentage a grafDirection is compared to 100% in 0 to 1 form
         grafDirectionY = grafDirectionY * grafDirection1Percent;
         grafDirectionX = grafDirectionX * grafDirection1Percent;
         grafDirectionZ = grafDirectionZ * grafDirection1Percent;
         //turns 0 to 1 in 1 to 0 (This is to calculate how much a Cam vector axis is turned on)
         grafDirectionY = grafDirectionY * -1 + 1;
         grafDirectionX = grafDirectionX * -1 + 1;
         grafDirectionZ = grafDirectionZ * -1 + 1;
 
         //Turns a Cam vector axis on or off depending on the grafDirection (The axis that is in the same direction as the grafDirection is turned off)
         CamF.y *= grafDirectionY;
         CamR.y *= grafDirectionY;
         CamF.x *= grafDirectionX;
         CamR.x *= grafDirectionX;
         CamF.z *= grafDirectionZ;
         CamR.z *= grafDirectionZ;
         //Normalizes the Cam vector's (Normalization means the vectors axis are set to a scale of 0 to 1 where 1 is all the axis combined)
         CamF = CamF.normalized;
         CamR = CamR.normalized;
 
         //Checks if object is onGround and gets no move(X/Y)input and then if so it decreases the rotation speed
         if (moveXinput == 0 && moveYinput == 0)
         {
             if (onGround)
             {
                 body.AddTorque(-body.angularVelocity * decelerationSpeed * Time.deltaTime);
             }
         }
         else //else it will add rotation force allong the camera axis (With the one that is in the grafDirection's direction turned off ofcourse)
         {
             body.AddTorque(CamR * moveYinput * accelerationSpeed * Time.deltaTime);
             body.AddTorque(CamF * moveXinput * -1 * accelerationSpeed * Time.deltaTime);
         }
 
 
         //*Air movement
         if(!onGround)
         {
             if (moveXinput != 0 || moveYinput != 0)
             {
                 if (maxAirVelocity > CamF.x * body.velocity.x && maxAirVelocity > CamF.y * body.velocity.y && maxAirVelocity > CamF.z * body.velocity.z && moveYinput > 0)
                 {
                     airMoveXinput = moveXinput;
                     airMoveYinput = moveYinput;
                     airMoveXinput = (airMoveXinput < 0) ? airMoveXinput * -1 : airMoveXinput;
                     airMoveYinput = (airMoveYinput < 0) ? airMoveYinput * -1 : airMoveYinput;
                     airMoveXinput = airMoveXinput * -1 + 1;
                     airMoveYinput = airMoveYinput * -1 + 1;
 
                     body.AddForce(CamF * moveYinput * airMoveXinput * airAccelerationSpeed * Time.deltaTime, ForceMode.Impulse);
                 }
                 if (maxAirVelocity > CamF.x * body.velocity.x * -1 && maxAirVelocity > CamF.y * body.velocity.y * -1 && maxAirVelocity > CamF.z * body.velocity.z * -1 && moveYinput < 0)
                 {
                     airMoveXinput = moveXinput;
                     airMoveYinput = moveYinput;
                     airMoveXinput = (airMoveXinput < 0) ? airMoveXinput * -1 : airMoveXinput;
                     airMoveYinput = (airMoveYinput < 0) ? airMoveYinput * -1 : airMoveYinput;
                     airMoveXinput = airMoveXinput * -1 + 1;
                     airMoveYinput = airMoveYinput * -1 + 1;
 
                     body.AddForce(CamF * moveYinput * airMoveXinput * airAccelerationSpeed * Time.deltaTime, ForceMode.Impulse);
                 }
                 if (maxAirVelocity > CamR.x * body.velocity.x && maxAirVelocity > CamR.y * body.velocity.y && maxAirVelocity > CamR.z * body.velocity.z && moveXinput > 0)
                 {
                     airMoveXinput = moveXinput;
                     airMoveYinput = moveYinput;
                     airMoveXinput = (airMoveXinput < 0) ? airMoveXinput * -1 : airMoveXinput;
                     airMoveYinput = (airMoveYinput < 0) ? airMoveYinput * -1 : airMoveYinput;
                     airMoveXinput = airMoveXinput * -1 + 1;
                     airMoveYinput = airMoveYinput * -1 + 1;
 
                     body.AddForce(CamR * moveXinput * airMoveYinput * airAccelerationSpeed * Time.deltaTime, ForceMode.Impulse);
                 }
                 if (maxAirVelocity > CamR.x * body.velocity.x * -1 && maxAirVelocity > CamR.y * body.velocity.y * -1 && maxAirVelocity > CamR.z * body.velocity.z * -1 && moveXinput < 0)
                 {
                     airMoveXinput = moveXinput;
                     airMoveYinput = moveYinput;
                     airMoveXinput = (airMoveXinput < 0) ? airMoveXinput * -1 : airMoveXinput;
                     airMoveYinput = (airMoveYinput < 0) ? airMoveYinput * -1 : airMoveYinput;
                     airMoveXinput = airMoveXinput * -1 + 1;
                     airMoveYinput = airMoveYinput * -1 + 1;
 
                     body.AddForce(CamR * moveXinput * airMoveYinput * airAccelerationSpeed * Time.deltaTime, ForceMode.Impulse);
                 }
             }
         }
 
 
         //*Jump
         //Get jumpInput
         jumpInput = Input.GetButton("Jump");
 
         //Checks if jump is not pressed and if object is not onGround; if so turns jump off
         if (!jumpInput && !onGround)
         {
             jumpNo = true;
         }
 
         //Jump script
         if (!jumpNo) //blocks jump script if necessary
         {
             if (jumpInput) //checks if jump is pressed
             {
                 if (jumpTime < jumpTimeMax) //checks if jumpTime has not run out
                 {
                     jumpTime += Time.deltaTime; //adds pased time to jumpTime
 
                     grafDirection = grafDirection.normalized * -1; //normalizes and inverts grafDirection (The jump direction is opposite to the gravity's direction of course)
                     
                     normal = normal.normalized; //normalizes normal (Normalization means the vectors axis are set to a scale of 0 to 1 where 1 is all the axis combined + the normal vector got normalized lol)
                     normalAngle = Vector3.Angle(grafDirection, normal); //calculates the angel betwean grafDirection and the normal (This is used to gradually turn on and off the scale of the grafDirection and the normal's influence)
 
                     if (normalAngle <= 90) //determines wether normalAngle is greater than 90 or not (Past 90 it reverses the efect of normal + grafDirection)
                     {
                         body.AddForce(grafDirection * normalAngle * jumpForceExtra * jumpForce * Time.deltaTime); //adds force in the grafDirection's direction (grafDirection scales up when the normalAngle becomes greater)(Uses jumpForceExtra to upscale the force since it has to fight gravity midair)
                         body.AddForce(normal * (-normalAngle + 180) * jumpForce * Time.deltaTime); //adds force in the normal direction (The normal variable scales down when the normalAngle becomes greater)
                     }
                     else
                     {
                         body.AddForce(grafDirection * (-normalAngle + 180) * jumpForceExtra * jumpForce * Time.deltaTime); //adds force in the grafDirection's direction (grafDirection scales up when the normalAngle becomes greater)(Uses jumpForceExtra to upscale the force since it has to fight gravity midair)
                         body.AddForce(normal * normalAngle * jumpForce * Time.deltaTime); //adds force in the normal direction (The normal variable scales down when the normalAngle becomes greater)
                     }
                 }
             }
         }
 
         if (offGroundTime > 0)
         {
             offGroundTime -= Time.deltaTime;
             alreadyOffGround = false;
         }
         else
         {
             if (!alreadyOffGround)
             {
                 onGround = false;
                 alreadyOffGround = true;
             }
         }
 
         if (onGround)
         {
             jumpForce = jumpForceBaseMemo;
             jumpTime = 0f;
             jumpNo = false;
         }
     }
 
     private void OnCollisionStay(Collision colA)
     {
         if (colA.collider.tag == "Ground")
         {
             Colide = 1;
             onGround = true;
             normal = colA.contacts[0].normal;
         }
     }
     private void OnCollisionExit(Collision colB)
     {
         Colide = 0;
         if (colB.collider.tag == "Ground")
         {
             offGroundTime = offGroundDelay;
         }
     }
 }
 
 
              
               Comment
              
 
               
              Your answer
 
             Follow this Question
Related Questions
Make player only jump as long as the button is held? 1 Answer
Input press to play different animation to input hold? 0 Answers
Jump with physics 1 Answer
Game not working on Tizen 0 Answers
Detect Button Being Held Down 1 Answer