Why can't I jump? - c#

When I try to run this code on unity,everything works expect the jumping.Anyone know why?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
public float speed = 12f;
public float gravity = -9.81f;
public float jumpHeight;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
Vector3 velocity;
bool isGrounded;
// Update is called once per frame
void Update()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if(isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * speed * Time.deltaTime);
if(Input.GetButtonDown("Jump") && isGrounded);
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity *Time.deltaTime);
}
}

For jumping in unity you can just add a Vector3 to the object you want to make jump, if it is in movement unity calculate automatic the trajectory of the object.

Your problem is with this line here
velocity.y += gravity * Time.deltaTime;
Don't try add gravity yourself, unity will be handing this for you if you have a character controller

As suggested in the comment, First make the isGrounded a little more stable.
Use the character's RigidBody and AddForce(Vector3 force, ForceMode mode = ForceMode.Force); to implement jumps, as a Jump is an impulsive force applied on the character in the up direction. Directly using Move is not the best way of implementing a jump force.
Documentation for RigidBody.AddForce

using System.Collections;
using System.Collections.Generic; // <-- Since these are not utilized and not necessary for this code, defined by being grey in their Colour.
// Consider Removing them, To stop using unnecessary Data / Library calls in your code
using UnityEngine;
public class PlayerMovement : 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 - 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 (Inspector) 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 they will be Public.
[SerializeField] private CharacterController controller;
[SerializeField] private float speed = 12f;
[SerializeField] private float gravity = -9.81f;
[SerializeField] private float jumpHeight; // !! On Default this Element is going to be 0, if Not Defined Within the Inspector !!!
[SerializeField] private Transform groundCheck;
[SerializeField] private float groundRadius = 0.4f; // groundDistance -> groundRadius ( As it defines the size of the Sphere made from GroundCheck element)
[SerializeField] private LayerMask groundMask;
private Vector3 velocity;
[SerializeField] private bool isGrounded;
void Update() // Called once per frame.
{
// Defines if the character IsGrounded ( True or False )
// 1) Find object groundCheck (dragged in the inspector for the code)
// .position Getting its position where GroundCheck is at the current moment
//,2) Make a Sphere with a radius of ..
// 3) Define what LayerMask is going to be checked.
isGrounded = Physics.CheckSphere(groundCheck.position, groundRadius, groundMask);
if (isGrounded && velocity.y < 0) // !! Issue fixed " if (isGrounded && velocity.y < 0); " You cannot have " ; " - breaker before your method brackets.
{
velocity.y = -2f;
}
/* Move these function into their separate methods.*/
/* Makes it easier to read as well as Debug,
in order to find where the issue in your code is taking place*/
Move();
Jump();
controller.Move(velocity * Time.deltaTime);
}
private void Move()
{
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * speed * Time.deltaTime);
}
private void Jump()
{
// Y Axis
if (Input.GetButtonDown("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime; // Applies gravity with (times) * Last updated frame to next update frame.
}
}
Make sure that you add : LayerMask to your object as well from which you are trying to jump from and check if you can jump. Found on this Picture ->
LayerMask Applied to The Floor Or Ground Object
On Player GameObject, Make sure that you have defined all variable values, as well as other GameObjects : such as " groundCheck " found on this Picture ->
Player Game Object Information In Inspector
Last put not least make sure you have defined JumpHeight in your Inspector of the Player
Though there are a lot of improvements still to make, this is what I would suggest, having provided you with commenting for Each Change or Explanation of a function.

Related

Why is my character's horizontal velocity lost when jumping?

GOAL
I'm relatively new to Unity and I want my character to be able to run and jump at the same time causing the character to go up diagonally.
PROBLEM
However after making some adjustments to give the character some acceleration, the jump seems to clear all existing velocity, meaning the character goes up and then to the side instead of both at the same time:
(I apologise if its a bit hard to see)
CODE
This is my character movement script:
Rigidbody2D rb;
BoxCollider2D bc;
[Header("Run")]
float xInput = 0f;
public float maxRunSpeed;
public float acceleration;
[Space]
[Header("Jump")]
public float jumpHeight;
public float lowJumpHeight;
public float fallSpeed;
public float airControl;
[Space]
public LayerMask groundLayer;
public bool onGround;
[Space]
public Vector2 bottomOffset;
public Vector2 boxSize;
public float coyoteTime;
void Start() {
// Gets a reference to the components attatched to the player
rb = GetComponent<Rigidbody2D>();
bc = GetComponent<BoxCollider2D>();
}
void Update() {
Jump();
// Takes input for running and returns a value from 1 (right) to -1 (left)
xInput = Math.Sign(Input.GetAxisRaw("Horizontal"));
}
// Applies a velocity scaled by runSpeed to the player depending on the direction of the input
// Increaces the velocity by accerleration until the max velocity is reached
void FixedUpdate() {
rb.velocity = Math.Abs(rb.velocity.x) < Math.Abs(xInput) * maxRunSpeed ? rb.velocity + new Vector2(acceleration * xInput, rb.velocity.y) * Time.deltaTime : new Vector2(xInput * maxRunSpeed, rb.velocity.y);
}
void Jump() {
// Checks whether the player is on the ground and if it is, replenishes coyote time, but if not, it starts to tick it down
coyoteTime = onGround ? 0.1f : coyoteTime - Time.deltaTime;
// Draws a box to check whether the player is touching objects on the ground layer
onGround = Physics2D.OverlapBox((Vector2)transform.position + bottomOffset, boxSize, 0f, groundLayer);
// Adds an upwards velocity to player when there is still valid coyote time and the jump button is pressed
if (Input.GetButtonDown("Jump") && coyoteTime > 0) {
rb.velocity = Vector2.up * jumpHeight;
}
// Increases gravity of player when falling down or when the jump button is let go mid-jump
if (rb.velocity.y < 0 ) {
rb.velocity += Vector2.up * Physics2D.gravity.y * (fallSpeed - 1) * Time.deltaTime;
} else if (rb.velocity.y > 0 && !Input.GetButton("Jump")) {
rb.velocity += Vector2.up * Physics2D.gravity.y * (lowJumpHeight - 1) * Time.deltaTime;
}
}
Sorry for there being a lot of unecessary code, it's just im not sure what's causing the issue so i don't want to remove anything. Hopefully my comments make some sense?
This is happening because you're setting the velocity of your rigidbody directly with rb.velocity = Vector2.up * jumpHeight. So that will wipe all existing velocity.
If you want to just add a force to the velocity rather than replacing it entirely, you can do that with methods like Rigidbody2D.AddForce.
While in all other cases you keep your velocity values and only slightly modify them you are hard overwriting the absolute velocity in
rb.velocity = Vector2.up * jumpHeight;
erasing any velocity on X.
You could simply keep whatever you have on the other axis and only overwrite Y like
var velocity = rb.velocity;
velocity.y = jumpHeight;
rb.velocity = velocity;
or
rb.velocity = new Vector2(rb.velocity.x, jumpHeight);
basically the same way you do it also in FixedUpdate for the horizontal direction.

Unity - Player movement problem, you can fly

If you dont collide with something you can fly! its really strange, please help me if you can.
i dont know how to fix it cause i am new in it.
Here is a script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player_Movement : MonoBehaviour
{
public float speed = 4.0f;
public float gravity = -9.8f;
private CharacterController _charCont;
// Use this for initialization
void Start()
{
_charCont = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
float deltaX = Input.GetAxis("Horizontal") * speed;
float deltaZ = Input.GetAxis("Vertical") * speed;
Vector3 movement = new Vector3(deltaX, 0, deltaZ);
movement = Vector3.ClampMagnitude(movement, speed); //Limits the max speed of the player
// movement.y = gravity;
movement *= Time.deltaTime; //Ensures the speed the player moves does not change based on frame rate
movement = transform.TransformDirection(movement);
_charCont.Move(movement);
}
}
I don't know that CharacterController but it sounds like it takes the global movement vector.
After
movement = transform.TransformDirection(movement);
you should erase the Y component
movement.y = 0;

i have a problem with player movment while jumping

the only problem that i face that the player only jump when they build momentum and i dont want that i want player jump by pressing space while standing or moving i tried velocity.y=jumphight which doesnt work too
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovment : MonoBehaviour
{
public CharacterController controller;
public float speed = 12f;
public float gravity = -9.81f;
Vector3 velocity;
public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;
bool isGrounded;
public float JumpHight = 3f;
void Update()
{
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
if(isGrounded && velocity.y<0)
{
controller.slopeLimit = 45.0f;
velocity.y = -2f;//when player is grounded it just put some gravity to him all the time
}
float x = Input.GetAxis("Horizontal");//moves left and right
float z = Input.GetAxis("Vertical");//moves up and down
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move*speed*Time.deltaTime);
if(Input.GetButtonDown("Jump") && controller.isGrounded)
{
velocity.y = Mathf.Sqrt(JumpHight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
you could use an addforce on the rigidbody with a ForceMode force , and if you don't want your physic depending on the fps use FixedUpdate instead of update
GetComponent<Rigidbody>().AddForce(Vector3.up,ForceMode.Force);
Vector3 velocity;
public float gravity = -9.82f;
public float JumpHeight = 3f;
if(Input.GetButtonDown("Jump")
{
velocity.y = Matf.Sqrt(JumpHeight * -2f * gravity);
}
You could also do what the other person said, the reason this person's line of code might not have worked it due to how weak it is. Here is an updated version of said code.
GetComponent<Rigidbody>().AddForce(Vector3.up * 10f ,ForceMode.Impulse);
The reason I am using the * is to increase the "up" variable since it means Vector3(0f, 1f, 0f); and using the ForceMode.Impulse to make it more volatile and stronger.
Hope this code helps you in your game making,
Kind Regards. SB

I have followed a tutorial on making controls for a fps game on unity. the controls work but if I leave the controls then I keep moving to the left

enter image description hereI have made controls for my character to move along the X axis. They seem to be working fine but my character keeps moving left and I'm not sure why or what I have missed.I have posted code from the two separate scripts
I have rechecked his code several times.I have checked to see if my arrow keys, numpad keys and WASD are sticking or any other.
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class PlayerMotor : MonoBehaviour
{
private Vector3 velocity = Vector3.zero;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
//gets a movement vector
public void Move (Vector3 _velocity)
{
velocity = _velocity;
}
//run every physics iteration
void FixedUpdate()
{
PerformMovement();
}
//perform movement based on velocity variable
void PerformMovement ()
{
if (velocity != Vector3.zero)
{
rb.MovePosition(rb.position + velocity * Time.fixedDeltaTime);
}
}
}
And the controller:
using UnityEngine;
[RequireComponent(typeof(PlayerMotor))]
public class PlayerController : MonoBehaviour
{
[SerializeField] //makes speed show up in inspector even if set to private
private float speed = 5f;
private PlayerMotor motor;
void Start ()
{
motor = GetComponent<PlayerMotor>();
}
void Update()
{
//Calculate movement velocity as a 3D vector
float _xMov = Input.GetAxisRaw("Horizontal");
float _zMov = Input.GetAxisRaw("Vertical");
Vector3 _movHorizontal = transform.right * _xMov;
Vector3 _movVertical = transform.forward * _zMov;
//final movement vector
Vector3 _velocity = (_movHorizontal + _movVertical).normalized * speed;
//apply movement
motor.Move(_velocity);
}
}
I expect 0 output when not pressing buttons but it seems to make me move to the left at speed of 5
You have a controller connected and reporting a slight movement in one direction. Use Input.GetAxis instead of Input.GetAxisRaw to let Unity handle deadzone detection. This way, nearly neutral inputs will be treated as neutral inputs.
void Update()
{
//Calculate movement velocity as a 3D vector
float _xMov = Input.GetAxis("Horizontal");
float _zMov = Input.GetAxis("Vertical");
Vector3 _movHorizontal = transform.right * _xMov;
Vector3 _movVertical = transform.forward * _zMov;
//final movement vector
Vector3 _velocity = (_movHorizontal + _movVertical).normalized * speed;
//apply movement
motor.Move(_velocity);
}

Problem with Jumping with Translate function [Unity 2D]

Soo, I'm trying to code a simple Platformer as a work for class, and I'm having problems with the jumping, the character actually jumps but it seems as a teleport since it instantly reaches the peak of the jump and then gradually falls, I'd like to make it smoother.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerMovement : MonoBehaviour {
public float speed;
public float jumpForce;
public bool grounded;
public Transform groundCheck;
private Rigidbody2D rb2d;
// Use this for initialization
void Start () {
rb2d = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update () {
}
private void FixedUpdate()
{
float moveVertical = 0;
float moveHorizontal = Input.GetAxis("Horizontal") * speed;
moveHorizontal *= Time.deltaTime;
grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));
if (grounded && Input.GetKeyDown("space"))
{
moveVertical = Input.GetAxis("Jump") * jumpForce;
moveVertical *= Time.deltaTime;
}
Vector2 move = new Vector2(moveHorizontal, moveVertical);
transform.Translate(move);
}
}
The answer to the question is below, however, for future questions related to Unity ask on the Unity forum. You will get a better answer quicker as more people are focused on Unity itself.
To fix your jump, rather split your vertical and horizontal movement in two parts and use your rigidbody you assigned in in your Start() function to handle jumping. Use ForceMode.Impulse to get an instant burst of speed/acceleration.
private void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal") * speed;
moveHorizontal *= Time.deltaTime;
grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground"));
if (grounded && Input.GetKeyDown("space"))
{
rb2d.AddForce(transform.up * jumpForce, ForceMode.Impulse);
}
Vector2 move = new Vector2(moveHorizontal, 0);
transform.Translate(move);
}
Instead of setting the position when you jump, add a vertical impulse to the character's rigidbody with:
if (grounded && Input.GetKeyDown("space"))
{
moveVertical = Input.GetAxis("Jump") * jumpForce;
moveVertical *= Time.fixedDeltaTime;
rb2d.AddForce(moveVertical, ForceMode.Impulse);
}
Vector2 move = new Vector2(moveHorizontal, 0f);
This will let Rigidbody2D handle the work of altering the vertical velocity on each frame.
Also, since you are doing all of these calculations in FixedUpdate, instead of Update, there is no sense in using Time.deltaTime. You should be using Time.fixedDeltaTime instead.

Categories

Resources