How to make jump independent on FPS? - c#

I almost made a 3D horror game in which the Player can walk, run and jump, but I noticed that jump depends on FPS. The more FPS, the higher the jump. I want to Player jump doesn't depend on FPS. How to solve the problem?
Script Player (just Update):
void Update{
// Jump when Player is on the Ground
Ground = Physics.CheckSphere(GroundCheck.position, groundDistance, Groundmask);
if (Ground && velocity.y < 0) { velocity.y = -0.5f; }
posX = Input.GetAxis("Horizontal"); posZ = Input.GetAxis("Vertical");
Vector3 Move = transform.right * posX + transform.forward * posZ;
controller.Move(Move * speed * Time.deltaTime);
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity);
if ((Input.GetMouseButton(0) || Input.GetKey(KeyCode.Return)) && Ground)
{
{ velocity.y = Mathf.Sqrt(3 - gravity); }
}
}

Related

my character is falling through the floor

I'm not sure why my character is falling through the floor.
My Rigidbody: has use gravity, no kinematic and Continuous Detection is set to Continuous.
My character is in the sky but the isgrounded bool ticks to true when it touches the floor but falls through anyways
My cube which is my floor has a box collider
void Update()
{
Move();
isGrounded = Physics.CheckSphere(GroundCheck.position, groundRadius, (int)whatisGround);
if (isGrounded == true)
{
velocity.y = -1f;
if (Input.GetKeyDown(KeyCode.Space))
{
velocity.y = JumpForce;
}
}
else
{
velocity.y -= Gravity * -2f * Time.deltaTime;
}
}
void Move()
{
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
Vector3 direction = new Vector3(horizontal, 0f, vertical).normalized;
if (direction.magnitude >= 0.1f)
{
float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg + playerCamera.eulerAngles.y;
float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime);
transform.rotation = Quaternion.Euler(0f, angle, 0f);
Vector3 moveDir = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward;
controller.Move(moveDir.normalized * speed * Time.deltaTime);
}
}
}
Looks like your code tests for the isgrounded value, and if it is true, changes the vertical velocity to -1, which is down. Since you don't tell it to zero it's vertical speed, and I assume it has no collider, it keeps falling down.
You need to either use a collider or, if isgrounded is true, set the y velocity to 0.

Slowly decrease movement speed after releasing left shift

So, I am still developing a game in Unity, where my only problem now is that I can't figure out how to slowly decrease the speed of my character after releasing left shift. Slowly increasing speed while holding shift is the only one I had worked out because I used the incrementing technique, but the speed slowly decreasing after releasing left shift is not. Can someone help me? Here's the code, I apologize, I am literally a beginner at this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
//Codes for setting walk and sprint speed (You should put speed in "Default Speed". "Walk Speed" is public so I can see if my speed is increasing)
public float defaultSpeed = 8f;
public float walkSpeed = 8f;
public float sprintIncrease = 15f;
public float sprintLimit = 16f;
//Gravity force
public float gravity = -60f;
//Probably jump height?
public float jumpHeight = 2f;
//For checking if you're on the ground
public Transform groundCheck;
public float groundDistance = 0.5f;
public LayerMask groundMask;
//Code to check if you are on the ground
Vector3 velocity;
bool isGrounded;
// Update is called once per frame
void Update()
{
//For checking again if you're on the ground
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
//Code to slowly increase sprint FORWARD while holding left shift
if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Vertical") > 0)
{
walkSpeed += sprintIncrease * Time.deltaTime;
}
//Code to prevent sprinting while holding S and when combined with A or D
else if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Vertical") < 0)
{
walkSpeed = defaultSpeed;
}
//Code for allowing to slowly increase sprint LEFT sideways
else if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Horizontal") < 0)
{
walkSpeed += sprintIncrease * Time.deltaTime;
}
//Code for allowing to slowly increase sprint RIGHT sideways
else if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Horizontal") > 0)
{
walkSpeed += sprintIncrease * Time.deltaTime;
}
//To stop Sprint Speed while holding shift from exceeding Sprint Limit
if (walkSpeed > sprintLimit)
{
walkSpeed = sprintLimit;
}
//Executes when shift is released, to slowly go back to default speed(This is my problem)
if (Input.GetKeyUp(KeyCode.LeftShift))
{
walkSpeed = defaultSpeed;
}
//To check if you're grounded so velocity doesn't increase
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
//The basic horizontal and vertical axises
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
//The basic code for movement
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * walkSpeed * Time.deltaTime);
//The code for jumping
if (Input.GetButtonDown("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
I thank everyone in advance.
if (!Input.GetKey(KeyCode.LeftShift))
{
walkSpeed -= sprintIncrease * Time.deltaTime;
}
the above code will do what you asked for. Just a heads up, the way you're implementing stuff is beginner-friendly but not performance friendly.
Ok, I have figured this out myself. I rearrange my ifs and else statement to look more organized. I added the else statement where if you don't hold shift while walking, it continuously subtracts the walk speed with the sprint increase, but to stop it from being lower than the default speed, I added an if statement where if the walk speed becomes lower than the default speed, it becomes equal to the default speed. Note that I rearranged my statements to trigger an else statement.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController controller;
//Codes for setting walk and sprint speed (You should put speed in "Default Speed". "Walk Speed" is public so I can see if my speed is changing or not)
public float defaultSpeed = 8f;
public float walkSpeed = 8f;
public float sprintIncrease = 15f;
public float sprintLimit = 16f;
//Gravity force
public float gravity = -60f;
//Probably jump height?
public float jumpHeight = 2f;
//For checking if you're on the ground
public Transform groundCheck;
public float groundDistance = 0.5f;
public LayerMask groundMask;
//Code to check if you are on the ground
Vector3 velocity;
bool isGrounded;
// Update is called once per frame
void Update()
{
//For checking again if you're on the ground
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
//Code to prevent sprinting while holding S and when combined with A or D(New Code)
if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Vertical") < 0)
{
walkSpeed -= sprintIncrease * Time.deltaTime;
}
//Code to slowly increase sprint FORWARD while holding left shift
else if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Vertical") > 0)
{
walkSpeed += sprintIncrease * Time.deltaTime;
}
//Code for allowing to slowly increase sprint LEFT sideways
else if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Horizontal") < 0)
{
walkSpeed += sprintIncrease * Time.deltaTime;
}
//Code for allowing to slowly increase sprint RIGHT sideways
else if (Input.GetKey(KeyCode.LeftShift) && Input.GetAxis("Horizontal") > 0)
{
walkSpeed += sprintIncrease * Time.deltaTime;
}
//To make sure that your speed decrease smoothly if not holding left shift(New code)
else
{
walkSpeed -= sprintIncrease * Time.deltaTime;
}
//To stop Sprint Speed while holding shift from exceeding Sprint Limit
if (walkSpeed > sprintLimit)
{
walkSpeed = sprintLimit;
}
//To stop Walk Speed from getting lower than Default Speed(New Code)
if (walkSpeed < defaultSpeed)
{
walkSpeed = defaultSpeed;
}
//To check if you're grounded so velocity doesn't increase
if (isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
//The basic horizontal and vertical axises
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
//The basic code for movement
Vector3 move = transform.right * x + transform.forward * z;
controller.Move(move * walkSpeed * Time.deltaTime);
//The code for jumping
if (Input.GetButtonDown("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}

Unity 3D Jumping issue

I've been following along with a 3D shooter tutorial (pretty good so far) but I've hit a snag when it comes to my framerate and jumping. The framerate on my PC is just not consistent and consequently the jump height varies constantly and sometimes the character doesn't jump at all. I know handling jumping in Update (rather than FixedUpdate) can cause issues regarding framerates but the tutorial insists that using Time.deltaTime should resolve that. Any ideas on what I should do to try and keep my jumps consistent?
//Jumping
public float jumpHeight = 10f;
public Transform ground;
private bool readyToJump;
public LayerMask groundLayer;
public float groundDistance = 0.5f;
// Update is called once per frame
private void Update()
{
Jump();
PlayerMovement();
CameraMovement();
Shoot();
}
void PlayerMovement()
{
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
Vector3 movement = x * transform.right + z * transform.forward;
myController.Move(movement * speed * Time.deltaTime);
//9.8 meters/second^2
velocity.y += Physics.gravity.y * Mathf.Pow(Time.deltaTime, 2) * gravityModifier;
if (myController.isGrounded)
{
velocity.y = Physics.gravity.y * Time.deltaTime;
}
myController.Move(velocity);
}
private void CameraMovement()
{
float mouseX = Input.GetAxisRaw("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxisRaw("Mouse Y") * mouseSensitivity * Time.deltaTime;
cameraVerticalRotation -= mouseY;
cameraVerticalRotation = Mathf.Clamp(cameraVerticalRotation, minVertCameraAngle, maxVertCameraAngle);
transform.Rotate(Vector3.up * mouseX);
myHead.localRotation = Quaternion.Euler(cameraVerticalRotation, 0f, 0f);
}
void Jump()
{
readyToJump = Physics.OverlapSphere(ground.position, groundDistance, groundLayer).Length > 0;
if (Input.GetButtonDown("Jump") && readyToJump)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * Physics.gravity.y) * Time.deltaTime;
}
myController.Move(velocity);
}
Handling the acceleration yourself is a bad idea, especially in Update rather than FixedUpdate. You should know that, in real life, the velocity changes smoothly with the acceleration against time. If you draw a curve, it is a straight slope. However, in computer, if you just calculate the velocity frame by frame, the curve will be looked like stairs.
You may use the physics engine in Unity and add an instant velocity to the character when it jumps. Just let Unity handle the acceleration.
First, you need to add a Rigidbody component to it. Then, you may modify your code to:
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Jump()
{
readyToJump = Physics.OverlapSphere(ground.position, groundDistance, groundLayer).Length > 0;
if (Input.GetButtonDown("Jump") && readyToJump)
{
rb.velocity = Vector3.up * jumpHeight * 2f / -Physics.gravity.y * gravityModifier;
}
}
Don't forget to remove the code in PlayerMovement on handling falling after you have Use Gravity in the Rigidbody component.
Edit
If you are using CharacterController, you can only handle the acceleration yourself. You may just move the logic to FixedUpdate to solve the various height problem, or make a more accurate simulation. For example, use this to handle jumping:
velocity.y = jumpHeight * 2f / -Physics.gravity.y * gravityModifier;
and use this to handle falling:
myController.Move(velocity * Time.deltaTime + Physics.gravity * Mathf.Pow(Time.deltaTime, 2) / 2f * gravityModifier);
// Here you should check whether it will fall through the ground.
// If no, use this line to update the velocity.
velocity.y += Physics.gravity.y * gravityModifier * Time.deltaTime;
// Otherwise, update the position to make it on ground and set velocity.y to 0.

Why is unity not recognising my left shift key

So I have a simple empty object with a 3d character controller attached. This is the update function of my player movement script
// Do the ground check
isGrounded = Physics.CheckSphere(groundCheck.position, groundDist, groundMask);
if (isGrounded && yMovement.y < 0)
{
yMovement.y = -2; // reset the gravity velocity
}
// get the xz movement of the player
float xMovement = Input.GetAxis("Horizontal");
float zMovement = Input.GetAxis("Vertical");
Vector3 xzMovement = transform.right * xMovement + transform.forward * zMovement;
// Check for sprinting
if (Input.GetButtonDown("Sprint"))
{
xzMovement *= sprintMultiplier;
}
// Check if the player should jump
if (Input.GetButtonDown("Jump") && isGrounded)
{
yMovement.y = Mathf.Sqrt(jumpHeight * -2 * gravity);
}
// move the player on xz
controller.Move(xzMovement * speed * Time.deltaTime);
// move the player on y
yMovement.y += gravity * Time.deltaTime;
controller.Move(yMovement * Time.deltaTime);
And during the sprinting check, no matter if the button is pressed or not, "xzMovement *= sprintingMultiplier" never gets called. Why is this?
By the way, in the input sprint is set up with a positive button of "left shift."
Any help is greatly appreciated.
You want to use Input.GetButton instead of Input.GetButtonDown.
GetButtonDown only returns true for a single frame when the button is pushed down, whereas GetButton returns true every frame while that button stays pushed down.

Unity Player's Shoot Function Will Not Work

I am creating a game in Unity. I have so far been able to get my player to follow the mouse at a somewhat correct angle. I am also trying to implement a shooting function for the character that shoots from the correct angle (straight from the top of the player, toward the mouse at the time of shooting). When I click using this code, nothing happens. I have objects set up for player, bullet and fire Point.
public void Update()
{
if (FollowMouse || Input.GetMouseButton(0))
{
_target = Camera.ScreenToWorldPoint(Input.mousePosition);
_target.z = 0;
}
var delta = ShipSpeed * Time.deltaTime;
var bulletDelta = shootSpeed * Time.deltaTime;
bulletDelta *= Vector3.Distance(transform.position, _target);
if (ShipAccelerates)
{
delta *= Vector3.Distance(transform.position, _target);
}
angle = Mathf.Atan2(_target.y, _target.x) * Mathf.Rad2Deg;
transform.position = Vector3.MoveTowards(transform.position, _target, delta);
transform.rotation = Quaternion.Euler(0, 0, angle);
if (Input.GetMouseButtonDown(0) && Time.time > nextFire && numOfBullets > 0)
{
nextFire = Time.time + fireRate;
Instantiate(bullet, firePoint.position, firePoint.rotation);
numOfBullets--;
bullet.transform.position = Vector3.MoveTowards(bullet.transform.position, _target, bulletDelta);
}
}

Categories