'Movement, Mouselook, and Gravity work but Jumping does not
I started creating a game with unity a couple of months ago and just swtiched to the new Unity Input System and my Unity Editor version is 2019.4.22f. I was using a tutorial and write a script for mouse look and Movement, jumping and gravity. I wrote the mouselook script and it worked fine. Then I also finished writing the Player Controller Script and tested it, the movement, mouse look, and Gravity worked like a charm but then jumping was not, I tried other tutorials and the same thing repeated. Now, I tried to do it with only the Input System, because before i was using the "both" option in the player option in project settings. I also don't have any console warnings or errors. Does anyone have a solution or this problem?
using UnityEngine;
public class Movement : MonoBehaviour {
[SerializeField] CharacterController controller;
[SerializeField] float speed = 11f;
Vector2 horizontalInput;
[SerializeField] float jumpHeight = 3.5f;
bool jump;
[SerializeField] float gravity = -30f; // -9.81
Vector3 verticalVelocity = Vector3.zero;
[SerializeField] LayerMask groundMask;
bool isGrounded;
private void Update ()
{
isGrounded = Physics.CheckSphere(transform.position, 0.1f, groundMask);
if (isGrounded) {
verticalVelocity.y = 0;
}
Vector3 horizontalVelocity = (transform.right * horizontalInput.x + transform.forward * horizontalInput.y) * speed;
controller.Move(horizontalVelocity * Time.deltaTime);
// Jump: v = sqrt(-2 * jumpHeight * gravity)
if (jump) {
if (isGrounded) {
verticalVelocity.y = Mathf.Sqrt(-2f * jumpHeight * gravity);
Debug.Log("isGrounded");
}
jump = false;
}
verticalVelocity.y += gravity * Time.deltaTime;
controller.Move(verticalVelocity * Time.deltaTime);
}
public void ReceiveInput (Vector2 _horizontalInput)
{
horizontalInput = _horizontalInput;
}
public void OnJumpPressed ()
{
jump = true;
}
}
Solution 1:[1]
The Problem you had with jump is this part here: Logic of the Code:
if (jump) == true (Meaning that it is asking, if The player is currenting in a jumping state and when the player is not In the jumping state it cannot be called as if(jump) would return false and not activate your function.
Next part is where it is done correctly if (isGrounded) == true then set the JumpHeight * gravity to your verticalVelocity.y
The problem with this is that, you have defined multiple vectors to your GameObject (Player) such as verticalVelecoity and horizontalVelocity consider only using one as Vector3 provides us with (x,y,z)
As we for Jump use .y Axis -1 or 1; for horizontal movement we use .x and vertical .z Meaning that we are trying to edit two different vectors and only using one of them _Horizontal which you are getting from " Input System ", though never setting these values correctly back to the "Input System."
// Jump: v = sqrt(-2 * jumpHeight * gravity)
if (jump) {
if (isGrounded) {
verticalVelocity.y = Mathf.Sqrt(-2f * jumpHeight * gravity);
Debug.Log("isGrounded");
}
jump = false;
}
Seeing the issue I would recommend such changes, in this change I am not using an "Input System (Package)", but these are the changes recommended, provided no (Input System variables or calls have been provided with in this question.
using UnityEngine;
public class MovementTest2 : MonoBehaviour
{
/* THINGS TO KNOW */
// Private - Only members of this class have access.
// Public -Can be accessed outside of the script.
// Public Static - Can be accessed in other scripts by using ( nameOfTheScript.VariableFromThatScript ) Which are called Pointers.
// Protected - Protected means it's only available in the class itself and any child-class.
// [SerializeField] private - Means that the variable is no longer publicly accessible, but can still be accessed inside the Editor of Unity
// Giving you the chance to Drag / Drop your Character controller and modify values of other variables (While not overwriting your values outside of your other scripts)
// Always define, if your variable is Public / Private or Protected
// By default variables are set to Public, if not defined otherwise.
// [SerializeField] makes your private variable shown within the inspector where the script is attached to.
[SerializeField] private CharacterController controller;
[SerializeField] private float gravity = -9.81f; // Set gravity to be the same as on Earth.
[SerializeField] private float playerSpeed = 11f;
[SerializeField] private float jumpForce = 3.5f; // Tells us the force applied to the "Player" with Jump
[SerializeField] private Transform groundCheck;
[SerializeField] private float groundRadius = 0.4f; // groundRadius ( defines the size of The Sphere made From GroundCheck GameObject)
[SerializeField] private LayerMask groundMask;
[SerializeField] private bool isGrounded; // Tells us if We are currently touching the ground of groundMask;
[SerializeField] private bool isjump = false; // Default value of isJump to be False;
// As we have one element / GameObject which moves (Player), we only need one Vector3 called velocity which offers us 3 Axis of (x,y,z).
private Vector3 velocity;
private void Update()
{
/* Explanation of what it does */
/* Check Ground position with a circle radius from GroundObjects */
/* transform.positon And CheckSpehre */
// transform.position Generally means that it will Look for the position of the Player (Since the position is at the centre of the Player)
// It will make a Sphere with a radius of ... and check if groundMask is found from that radius to define "Grounded" .
/* Make A new GameObject Called GroundCheck Inside of Player GameObject, Move GroundCheck Under the Player*/
// Define a seperate GameObject for position (checked) such as groundCheck.position (Which has to be a Child of the Player GameObject)
// For the groundCheck object to follow the position of the "Player GameObject".
isGrounded = Physics.CheckSphere(groundCheck.position, groundRadius, groundMask);
if (isGrounded)
{
isjump = false; // The player Is grounded set jumping to be False
}
Move(); // Check for movement on vertical and horizontal Movement ( See -> private void Move() )
Jump(); // Check if the Player is pressing "Jump" and then make it Jump. ( See -> private void Jump() )
velocity.y += gravity * Time.deltaTime; // Player getting applied gravity (falling)
controller.Move(velocity * Time.deltaTime);
}
private void Move()
{
// Get Horizontal And Vertical Axis From Unity Default Inputs
// Set Horizontal Values of Either (-1 or 1) to x
// Set Vertical Values of Either (-1 or 1) to z
float x = Input.GetAxis("Horizontal"); // <-- In Unity Click ( Edit -> Project Settings -> Input Manager -> Horizontal / Vertical
// Where you can Change Buttons on Which you Move with and Set Keys Used for them.
float z = Input.GetAxis("Vertical");
Vector3 move = (transform.right * x + transform.forward * z); // Move Player Speed Under controller.Move function.
controller.Move(move * playerSpeed * Time.deltaTime); // Update All of Velocity To be Associated with deltaTime.
}
private void Jump()
{
if (Input.GetButtonDown("Jump") && isGrounded) // if jump Button pressed == true And isGrounded == true
{
isjump = true; // When Spacebar is pressed or other keys set under Jump, then set its state to true
velocity.y = Mathf.Sqrt(-2f * jumpForce * gravity);
}
}
/* Remove these function as they are not used or called anywhere within this code. */
//public void ReceiveInput(Vector2 _horizontalInput)
//{
// horizontalInput = _horizontalInput;
//}
//public void OnJumpPressed()
//{
// jump = true;
//}
}
- GroundCheck object
- GameObject "Floor"
Add another "New GameObject" -> "Floor", and use a LayerMask called "Ground", which you have to make
Reference to add a new LayerMask can be found here with description : https://answers.unity.com/questions/8715/how-do-i-use-layermasks.html
- Player Components
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dharman |
