Answer the question
In order to leave comments, you need to log in
How to make correct isGrounded in Unity 3D?
When I just stand on the surface, everything is fine
. But when I just start to go to another surface, then for some reason isGrounded changes to false and I levitate.
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(PlayerMotor))]
public class PlayerController : MonoBehaviour
{
public Animator anim;
public Rigidbody rig;
public Transform mainCamera;
private PlayerMotor motor;
public float speedCharacter = 5f;
public float runningSpeed = 6f;
private float curVertSpeed;
public float currentSpeed;
public float jumpCount;
private bool isGrounded;
private readonly Vector3 jumpDirection = Vector3.up;
private float animationInterpolation = 1f;
private bool runTrue;
void Start()
{
motor = GetComponent<PlayerMotor>();
anim = GetComponent<Animator>();
this.rig = GetComponent<Rigidbody>();
// Прекрепляем курсор к середине экрана
Cursor.lockState = CursorLockMode.Locked;
// и делаем его невидимым
Cursor.visible = false;
}
void OnCollisionEnter(Collision other)
{
var ground = other.gameObject.GetComponentInParent<Ground>();
if (ground)
this.isGrounded = true;
anim.SetBool("InAir", false);
runTrue = true;
}
void OnCollisionExit(Collision other)
{
var ground = other.gameObject.GetComponentInParent<Ground>();
if (ground)
this.isGrounded = false;
anim.SetBool("InAir", true);
runTrue = false;
}
void Run()
{
if (runTrue)
{
animationInterpolation = Mathf.Lerp(animationInterpolation, 1.5f, Time.deltaTime * 3);
anim.SetFloat("x", Input.GetAxis("Horizontal") * animationInterpolation);
anim.SetFloat("y", Input.GetAxis("Vertical") * animationInterpolation);
currentSpeed = Mathf.Lerp(currentSpeed, runningSpeed, Time.deltaTime * 3);
}
}
void Walk()
{
// Mathf.Lerp - отвчает за то, чтобы каждый кадр число animationInterpolation(в данном случае) приближалось к числу 1 со скоростью Time.deltaTime * 3.
// Time.deltaTime - это время между этим кадром и предыдущим кадром. Это позволяет плавно переходить с одного числа до второго НЕЗАВИСИМО ОТ КАДРОВ В СЕКУНДУ (FPS)!!!
animationInterpolation = Mathf.Lerp(animationInterpolation, 1f, Time.deltaTime * 3);
anim.SetFloat("x", Input.GetAxis("Horizontal") * animationInterpolation);
anim.SetFloat("y", Input.GetAxis("Vertical") * animationInterpolation);
currentSpeed = Mathf.Lerp(currentSpeed, speedCharacter, Time.deltaTime * 3);
}
void Jump()
{
if (this.isGrounded)
{
this.rig.AddForce(this.jumpDirection * this.jumpCount, ForceMode.Impulse);
}
}
void FixedUpdate()
{
if (isGrounded)
{
if (Input.GetKeyDown(KeyCode.Space))
{
Jump();
}
}
// Устанавливаем поворот персонажа когда камера поворачивается
transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x, mainCamera.rotation.eulerAngles.y, transform.rotation.eulerAngles.z);
if (isGrounded)
// Зажаты ли кнопки W и Shift?
if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.LeftShift))
{
// Зажаты ли еще кнопки A S D?
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.D))
{
Run();
runTrue = true;
}
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.LeftShift))
{
Run();
runTrue = true;
}
// Если нет, то тогда бежим!
else
{
Run();
runTrue = true;
}
}
// Если W & Shift не зажаты, то мы просто идем пешком
else
{
Walk();
runTrue = false;
}
// Здесь мы задаем движение персонажа в зависимости от направления в которое смотрит камера
// Сохраняем направление вперед и вправо от камеры
Vector3 camF = mainCamera.forward;
Vector3 camR = mainCamera.right;
// Чтобы направления вперед и вправо не зависили от того смотрит ли камера вверх или вниз, иначе когда мы смотрим вперед, персонаж будет идти быстрее чем когда смотрит вверх или вниз
// Можете сами проверить что будет убрав camF.y = 0 и camR.y = 0 :)
camF.y = 0;
camR.y = 0;
Vector3 movingVector;
// Тут мы умножаем наше нажатие на кнопки W & S на направление камеры вперед и прибавляем к нажатиям на кнопки A & D и умножаем на направление камеры вправо
movingVector = Vector3.ClampMagnitude(camF.normalized * Input.GetAxis("Vertical") * currentSpeed + camR.normalized * Input.GetAxis("Horizontal") * currentSpeed, currentSpeed);
// Magnitude - это длинна вектора. я делю длинну на currentSpeed так как мы умножаем этот вектор на currentSpeed на 86 строке. Я хочу получить число максимум 1.
anim.SetFloat("magnitude", movingVector.magnitude / currentSpeed);
Debug.Log(movingVector.magnitude / currentSpeed);
// Здесь мы двигаем персонажа! Устанавливаем движение только по x & z потому что мы не хотим чтобы наш персонаж взлетал в воздух
rig.velocity = new Vector3(movingVector.x, rig.velocity.y, movingVector.z);
// У меня был баг, что персонаж крутился на месте и это исправил с помощью этой строки
rig.angularVelocity = Vector3.zero;
}
}
Answer the question
In order to leave comments, you need to log in
void OnCollisionEnter(Collision other)
{
var ground = other.gameObject.GetComponentInParent<Ground>();
if (ground)
this.isGrounded = true;
anim.SetBool("InAir", false);
runTrue = true;
}
void OnCollisionExit(Collision other)
{
var ground = other.gameObject.GetComponentInParent<Ground>();
if (ground)
this.isGrounded = false;
anim.SetBool("InAir", true);
runTrue = false;
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question