My player should always do the following animation sequence: idle/run → jump → fall → idle/run, but when he falls while moving to the right, the fall animation will remain even after he’s touched the ground, fading out only when I stop his movement.
I’ve already checked the state machine for my player as well as his script, but everything seems alright.
Player’s bug.
Player’s state machine.
Player’s script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//Todas as informações do jogador se encontram aqui.
public class Player : Character
{
//Booleano que determina se o jogador pode pular novamente.
private bool resetjump = false;
//Booleano que determina se o jogador está no chão.
private bool grounded = false;
//Float para o tempo de espera do jogador após atirar.
private float nextFireTime = 0;
//Float para o tempo de recarga da arma do jogador.
[SerializeField] private float gunCooldown;
//Float para a altura do pulo do jogador.
[SerializeField] private float jumpForce;
//Função de inicialização do jogador:
protected override void Init()
{
//Obtém os comandos de inicialização da classe pai,
base.Init();
//Determina que o jogador está virado para a direita,
facingRight = true;
//Determina a altura do pulo,
jumpForce = 14f;
//A velocidade do movimento e
moveSpeed = 8f;
//O tempo de recarga da arma do jogador.
gunCooldown = 0.35f;
}
//Aplica a função de inicialização no primeiro frame do jogo.
void Start()
{
Init();
}
//Aguarda os comandos de tiro e movimento do jogador a cada frame.
void Update()
{
Shoot();
Movement();
}
//Função de tiro do jogador:
public override void Shoot()
{
//Se chegar o tempo onde o jogador pode atirar novamente e
if (Time.time > nextFireTime)
{
//Se o botão de tiro for apertado,
if (Input.GetKeyDown(KeyCode.L))
{
//Reproduz a animação de tiro do jogador,
anim.SetTrigger("shoot");
//Instancia a bala do jogador e
Instantiate(shotPrefab, firePoint.position, firePoint.rotation);
//Acrescenta o tempo de recarga da arma ao float de espera.
nextFireTime = Time.time + gunCooldown;
}
}
}
//Função de movimento do jogador:
void Movement()
{
//Obtém o registro horizontal do jogador, que vai de -1 a 1.
//Valor negativo = movimento para a esquerda.
//Valor positivo = movimento para a direita.
float move = Input.GetAxisRaw("Horizontal");
//Verifica se o jogador está no chão.
grounded = IsGrounded();
//Se o registro for positivo e o jogador estiver virado à esquerda,
if (move > 0 && !facingRight)
{
//O jogador dá meia-volta.
Flip();
}//Se o registro for negativo e o jogador estiver virado à direita,
else if (move < 0 && facingRight)
{
//O jogador dá meia-volta.
Flip();
}
//Se o botão de pulo for apertado e o jogador estiver no chão,
if (Input.GetKeyDown(KeyCode.W) && IsGrounded())
{
//Aplica no jogador a força vertical do pulo,
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
//Inicia a corrotina de reabilitação de pulo e
StartCoroutine(resetJumpRoutine());
//Reproduz a animação de pulo do jogador.
anim.SetBool("jump", true);
}
if (rb.velocity.y < 0)
{
anim.SetBool("fall", true);
anim.SetBool("jump", false);
}
//
//tentar aplicar GetKeyUp com mudança na gravidade para mudar intensidade do pulo
//
//Por fim, aplica no jogador a força horizontal do movimento e
rb.velocity = new Vector2(move * moveSpeed, rb.velocity.y);
//Se o valor do registro não for 0, reproduz a animação de corrida do jogador.
anim.SetFloat("speed", Mathf.Abs(move));
}
//Função que verifica se o jogador está no chão:
bool IsGrounded()
{
//Desenha na cena uma linha de debug partindo do jogador até o chão e
Debug.DrawRay(transform.position, Vector2.down * 1.4f, Color.green);
//Gera uma linha de colisão invisível correspondente à linha de debug.
RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, 1.4f, 1 << 9);
//Se a linha colidir com algo (implicando que o jogador pousou em algo sólido) e
if (hit.collider != null)
{
//Se atualmente o jogador não puder pular,
if (resetjump == false)
{
//Para a reprodução da animação de pulo do jogador e
anim.SetBool("fall", false);
//Confirma que o jogador está no chão.
return true;
}
}//Senão, confirma que o jogador não está no chão.
return false;
}
//Corrotina de reabilitação do pulo do jogador:
IEnumerator resetJumpRoutine()
{
//Reabilita o pulo do jogador,
resetjump = true;
//Espera um determinado tempo e
yield return new WaitForSeconds(0.1f);
//O desabilita novamente.
resetjump = false;
}
private void OnCollisionEnter2D(Collision2D other)
{
Debug.Log("Trigger called");
if (other.gameObject.CompareTag("Moving Platform") && !IsGrounded())
{
grounded = true;
transform.parent = other.gameObject.transform;
}
if (other.gameObject.CompareTag("Enemy"))
{
anim.SetTrigger("damage");
}
}
private void OnCollisionExit2D(Collision2D other)
{
if (other.gameObject.CompareTag("Moving Platform"))
{
transform.parent = null;
}
}
public override void TakeDamage()
{
//HP--;
}
}