Character Controller isGrounded value flickers on and off
So I am trying to make a 3D platformer game similar to the Mario games. I want my character to be able to run around, jump, and dive. After a dive, the player should slide on the ground while still in the diving animation for a little bit. When the character runs around, isGrounded is always true; I have no problems with this. However, when my character is sliding on the ground after diving, the isGrounded value keeps flickering on and off. I also noticed that the y position of my character will alternate between 0.2049 and 0.204899 when this happens. I've tried different things to try and get it to work but I'm out of ideas. I think it could be the way I set the y velocity to be -4 when I'm grounded to keep my character grounded, or it could be because I changed the size and skinwidth of my character controller for different animations.
This is my code if it helps (sorry if it it messy):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public float jumpForce;
public float doubleJumpForceScalar;
public CharacterController controller;
public float gravityScale;
public int jumpBuffer;
public Animator anim;
public Transform pivot;
public float rotateSpeed;
public GameObject playerModel;
public float speed;
public float diveSpeed;
public float diveForceScalar;
public int diveCountMax;
public float ccHeightGrounded;
public float ccHeightDive;
public float ccHeightDoubleJump;
public Vector3 ccCenterGrounded;
public Vector3 ccCenterDive;
public Vector3 ccCenterDoubleJump;
public float ccSkinWidth;
public float ccSkinWidthDive;
public float ccRadius;
public float ccRadiusDive;
public float diveFlipScalar;
public float diveSlow;
public bool divedGroundJump;
public bool bonk;
public float bonkSpeed;
public bool grounded;
public bool dived;
private bool hasDoubleJump;
private Vector3 moveDirection;
private bool jumped;
private int jumpBufferCount = 0;
private bool divedOutOfJump;
private int diveCount;
private bool firstAirFrame;
private int diveCCCount;
public bool divedGround;
public float bonkJumpScalar;
// Start is called before the first frame update
void Start()
{
controller = GetComponent<CharacterController>();
grounded = controller.isGrounded;
hasDoubleJump = true;
}
// Update is called once per frame
void Update()
{
float yStore = moveDirection.y; //Stores the value of the y velocity from last frame
moveDirection = (transform.forward * Input.GetAxisRaw("Vertical")) + (transform.right * Input.GetAxisRaw("Horizontal"));
moveDirection = moveDirection.normalized * moveSpeed;
moveDirection.y = yStore;
grounded = controller.isGrounded;
if (controller.isGrounded)
{
jumped = false;
hasDoubleJump = true;
if (dived)
{
moveDirection.y = -4f; // <--- I think this might be the problem
divedGround = true;
divedGroundJump = false;
}
else if(bonk) //bonk checks if you hit a wall while diving
{
dived = false;
divedGround = false;
moveDirection.y = jumpForce * bonkJumpScalar;
jumped = true;
bonk = false;
}
else if(!divedGround) //divedGround is when the character is sliding on the ground after a dive
{
GetComponent<CharacterController>().height = ccHeightGrounded;
GetComponent<CharacterController>().center = ccCenterGrounded;
GetComponent<CharacterController>().skinWidth = ccSkinWidth;
GetComponent<CharacterController>().radius = ccRadius;
dived = false;
divedGround = false;
diveCount = 0;
diveCCCount = 0;
divedOutOfJump = false;
firstAirFrame = true;
divedGroundJump = false;
bonk = false;
if (jumpBufferCount < jumpBuffer && jumpBufferCount > 0)
{
moveDirection.y = jumpForce;
jumped = true;
}
jumpBufferCount = 0;
moveDirection.y = -4f;
if (Input.GetButtonDown("Jump"))
{
moveDirection.y = jumpForce;
jumped = true;
}
if (Input.GetMouseButtonDown(0) || Input.GetButtonDown("Dive"))
{
dived = true;
}
}
}
else //if isGrounded is false (character in the air)
{
if (bonk)
{
moveDirection.x = 0.0f;
moveDirection.z = 0.0f;
moveDirection.y += (Physics.gravity.y * gravityScale * Time.deltaTime);
controller.Move(moveDirection * Time.deltaTime);
controller.Move(-playerModel.transform.forward * bonkSpeed * Time.deltaTime);
GetComponent<CharacterController>().height = ccHeightGrounded;
GetComponent<CharacterController>().center = ccCenterGrounded;
//GetComponent<CharacterController>().skinWidth = ccSkinWidth;
GetComponent<CharacterController>().radius = ccRadius;
}
else
{
if (moveDirection.y < -0.5f && firstAirFrame)
{
moveDirection.y = -0.5f;
firstAirFrame = false;
}
if (jumpBufferCount > 0 && jumpBufferCount < jumpBuffer)
{
jumpBufferCount++;
}
if (hasDoubleJump == false)
{
anim.SetBool("doubleJumped", hasDoubleJump);
}
if (Input.GetButtonDown("Jump") && hasDoubleJump == true)
{
moveDirection.y = jumpForce * doubleJumpForceScalar;
hasDoubleJump = false;
anim.SetBool("doubleJumped", !hasDoubleJump);
dived = false;
GetComponent<CharacterController>().height = ccHeightDoubleJump;
GetComponent<CharacterController>().center = ccCenterDoubleJump;
}
else if (Input.GetButtonDown("Jump") && jumpBufferCount == 0 && hasDoubleJump == false)
{
jumpBufferCount++;
}
if ((Input.GetMouseButtonDown(0) || Input.GetButtonDown("Dive")) && !dived && !divedOutOfJump)
{
dived = true;
divedOutOfJump = true;
}
moveDirection.y += (Physics.gravity.y * gravityScale * Time.deltaTime);
}
}
if(divedGround)
{
if (Input.GetButtonDown("Jump"))
{
dived = false;
divedGround = false;
moveDirection.y = jumpForce * diveFlipScalar;
jumped = true;
//divedGroundJump = true;
}
if(diveSlow > diveSpeed)
{
dived = false;
divedGround = false;
moveDirection.y = jumpForce * diveFlipScalar;
jumped = true;
//divedGroundJump = true;
}
}
if (!dived && !bonk && !divedGroundJump)
{
GetComponent<CharacterController>().skinWidth = ccSkinWidth;
//Move the player in different directions based on the camera look direction
if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0)
{
transform.rotation = Quaternion.Euler(0f, pivot.rotation.eulerAngles.y, 0f);
Quaternion newRotation = Quaternion.LookRotation(new Vector3(moveDirection.x, 0f, moveDirection.z));
playerModel.transform.rotation = Quaternion.Slerp(playerModel.transform.rotation, newRotation, rotateSpeed * Time.deltaTime);
}
controller.Move(moveDirection * Time.deltaTime);
}
else if(dived)
{
GetComponent<CharacterController>().skinWidth = ccSkinWidthDive;
GetComponent<CharacterController>().radius = ccRadiusDive;
if (diveCCCount < 10)
{
GetComponent<CharacterController>().height = ccHeightGrounded;
GetComponent<CharacterController>().center = ccCenterGrounded;
diveCCCount++;
}
else
{
GetComponent<CharacterController>().height = ccHeightDive;
GetComponent<CharacterController>().center = ccCenterDive;
}
if (diveCount < diveCountMax)
{
if (!grounded)
{
diveCount++;
}
else
{
moveDirection.y = -0.5f;
}
moveDirection.y += jumpForce * diveForceScalar;
}
moveDirection.x = 0f;
moveDirection.z = 0f;
controller.Move(moveDirection * Time.deltaTime);
if (!divedGround)
{
diveSlow = 0.1f;
controller.Move(playerModel.transform.forward * diveSpeed * Time.deltaTime);
}
else
{
if (diveSlow < diveSpeed)
{
controller.Move(playerModel.transform.forward * (diveSpeed - diveSlow) * Time.deltaTime);
diveSlow += 0.025f;
}
}
}
speed = Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal"));
anim.SetBool("isGrounded", controller.isGrounded);
anim.SetFloat("Speed", speed);
anim.SetBool("jumped", jumped);
anim.SetBool("dived", dived);
anim.SetBool("divedGround", divedGround);
anim.SetBool("bonk", bonk);
}
void OnTriggerEnter(Collider other)
{
if(other.tag == "Ceiling")
{
moveDirection.y = 0.75f;
controller.Move(moveDirection * Time.deltaTime);
}
}
void OnControllerColliderHit(ControllerColliderHit hit)
{
if(hit.gameObject.tag == "Level" && dived)
{
dived = false;
bonk = true;
}
if(hit.gameObject.tag == "Respawn")
{
transform.position = new Vector3(0f, 2f, 0f);
}
if (hit.gameObject.tag == "Ceiling")
{
moveDirection.y = 1f;
controller.Move(moveDirection * Time.deltaTime);
}
}
}
Answer by parag1111 · Aug 02, 2020 at 06:08 PM
At line number 70, You may want to try adding constant push to negative direction of y. E.G. moveDirection.y =- gravityScale * Time.deltaTime;
Your answer
Follow this Question
Related Questions
Jumping with slight air control while retaining velocity 1 Answer
IsGrounded flickers when hitting a wall 0 Answers
Hold the jump button to jump higher with CharacterController 1 Answer
Help! Collision will not work, but all others will 0 Answers
Can someone help me with why my jump wont work properly 0 Answers