Can't stop Multi Jumping in mid air

Hey so I cannot find a way to make my character stop jumping in mid-air infinitely without rigidbody and I need help to make him jump only once when off the ground. Here is my script.

using System.Collections;

using System.Collections.Generic;
using System.Collections.Specialized;
using System.Security.Cryptography;
using System.Threading;
using UnityEngine;

public class ThirdPersonMovement : MonoBehaviour
{
public CharacterController controller;
public Transform cam;

public float speed = 6;
public float gravity = -9.81f;
public float jumpHeight = 3;
Vector3 velocity;
public bool isGrounded = true;

public Transform groundCheck;
public float groundDistance = 0.4f;
public LayerMask groundMask;

float turnSmoothVelocity;
public float turnSmoothTime = 0.1f;

// Update is called once per frame
void Update()
{
//jump
isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);

if (isGrounded == false && velocity.y < 0)
{
velocity.y = -10;
}

if (Input.GetButtonDown(“Jump”) && isGrounded == true)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2 * gravity);
isGrounded = false;
}
//gravity
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
//walk
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 + cam.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);
}
}

private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.name == “Ground”)
{
isGrounded = true;
}
}
}

CharacterController CharMover broken:

I wrote about this before: the Unity example code in the API no longer jumps reliably. I have reported it. Here is a work-around:

1 Like

Oh wow thanks for this!

Just a quick question but how would I edit the character controller to fit the proportions of my character? It is always defaulted to be 2 for height, 5 for radius and 0,0,0 for coords.

Do you see the entries in the inspector? I believe you just edit them and save it.

Make sure you unfold the character controller if it is folded… here’s what mine looks like:

6488745--729378--Screen Shot 2020-11-03 at 6.06.53 PM.png

Alright thanks

Do you know how to save it?

you save it with the scene, or else in a prefab, like any setting.

You could probably set the properties yourself in the Start() method but that might confuse you in the future.

ah ok

Hey Kurt-Dekker so I used that script you gave me and I decided to combine it with my original script so that my player would follow the direction he is going and the direction my camera is looking.

However, whenever I add in {controller.Move(moveDir.normalized * playerSpeed * Time.deltaTime);} and remove {controller.Move(moving * Time.deltaTime);}, I cannot jump, but my player would follow the direction he is going and would follow the direction my camera is looking.

However, whenever I add in {controller.Move(moving * Time.deltaTime);} and remove {controller.Move(moveDir.normalized * playerSpeed * Time.deltaTime);}, I can jump and my player would follow the direction he is going, but he won’t follow the direction my camera is looking.

I bolded the locations of these two lines so I need help

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// Originally from Unity examples at:
// Unity - Scripting API: CharacterController.Move
//
// 3:55 PM 10/3/2020
//
// Reworked by @kurtdekker so that it jumps reliably in modern Unity versions.
//
// To use:
// - make your player shape about 1x2x1 in size
// - put this script on the root of it
//
// That’s it.

public class ThirdPersonMovement : MonoBehaviour
{
private CharacterController controller;
private float verticalVelocity;
private float groundedTimer; // to allow jumping when going down ramps
public float playerSpeed = 2.0f;
public float jumpHeight = 1.0f;
public float gravityValue = 9.81f;
public Transform cam;
float turnSmoothVelocity;
public float turnSmoothTime = 0.1f;

private void Start()
{
// always add a controller
controller = GetComponent();
}

void Update()
{
bool groundedPlayer = controller.isGrounded;
if (groundedPlayer)
{
// cooldown interval to allow reliable jumping even whem coming down ramps
groundedTimer = 0.2f;
}
if (groundedTimer > 0)
{
groundedTimer -= Time.deltaTime;
}

// slam into the ground
if (groundedPlayer && verticalVelocity < 0)
{
// hit ground
verticalVelocity = 0f;
}

// apply gravity always, to let us track down ramps properly
verticalVelocity -= gravityValue * Time.deltaTime;

// gather lateral input control
float horizontal = Input.GetAxisRaw(“Horizontal”);
float vertical = Input.GetAxisRaw(“Vertical”);
Vector3 move = new Vector3(horizontal, 0f, vertical).normalized;
Vector3 moving = new Vector3(Input.GetAxis(“Horizontal”), 0, Input.GetAxis(“Vertical”));

// scale by speed
moving *= playerSpeed;

// only align to motion if we are providing enough input
if (move.magnitude >= 0.1f)
{
float targetAngle = Mathf.Atan2(move.x, move.z) * Mathf.Rad2Deg + cam.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 * playerSpeed * Time.deltaTime);

}

// allow jump as long as the player is on the ground
if (Input.GetButtonDown(“Jump”))
{
// must have been grounded recently to allow jump
if (groundedTimer > 0)
{
// no more until we recontact ground
groundedTimer = 0;

// Physics dynamics formula for calculating jump up velocity based on height and gravity
verticalVelocity += Mathf.Sqrt(jumpHeight * 2 * gravityValue);
}
}

// inject Y velocity before we use it
moving.y = verticalVelocity;

// call .Move() once only
controller.Move(moving * Time.deltaTime);
}
}

This is going to be highly-dependent not only on the code running properly but on the setup being correct.

I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run?
  • what are the values of the variables involved? Are they initialized?

Knowing this information will help you reason about the behavior you are seeing.

Cool i’ll do that