Gabriel Silva
He logrado hacer que el bastón lance una bolita que hace daño, y solo cuando se tiene el bastón equipado
Ikal Esteban Fernández Galván
no se ve
Controla con precisión el cambio entre movimiento y ataque en Unity combinando el Animator y el PlayerController. Aquí verás cómo activar un estado booleado de attacking, usar un contador de tiempo para la duración del ataque y evitar que el personaje se mueva mientras ataca. Todo con C# claro, directo y fácil de depurar.
¿Cómo alternar entre ataque y movimiento con animator y controlador?
Para conmutar entre animaciones, se utiliza un parámetro booleano en el Animator llamado exactamente attacking. Este parámetro gobierna las transiciones desde movimiento e idle hacia la animación de ataque en el blend tree. La lógica se programa en Update para leer la entrada del ratón y actualizar el contador de ataque.
¿Qué variables y constantes necesitas?
Ejemplo en C#:
// Nombre exacto del parámetro en Animator private const string attackingState = "attacking"; // Control del ataque public float attackTime = 0.5f; // ajustable en el Inspector private bool attacking = false; // estado actual private float attackTimeCounter; // contador interno
¿Cómo gestionar el ciclo de ataque en update?
La clave es decrementar el contador mientras se ataca y apagar el estado cuando llegue a cero. Así evitas mezclar movimiento y ataque.
void Update() { // Mientras se ataca, cuenta hacia atrás y bloquea el movimiento. if (attacking) { attackTimeCounter -= Time.deltaTime; if (attackTimeCounter < 0f) { attacking = false; animator.SetBool(attackingState, false); } } else { // Aquí iría la lógica de movimiento horizontal/vertical. // Ejemplo: animator.SetFloat("moveX", inputX); animator.SetFloat("moveY", inputY); // El cálculo de walking es común. } // Resto de Update... }
¿Cómo detectar la entrada del ratón para iniciar el ataque?
Se usa el clic izquierdo con Input.GetMouseButtonDown(0). Al iniciar, se reinicia el contador, se pone la velocidad a cero y se activa el parámetro del Animator.
if (Input.GetMouseButtonDown(0)) { attacking = true; attackTimeCounter = attackTime; // copia desde la pública playerRigidBody.velocity = Vector2.zero; // detener por completo animator.SetBool(attackingState, true); // activar animación de ataque }
¿Qué errores comunes debes evitar?
Un fallo típico es un desajuste de nombres entre código y Animator. El parámetro debe llamarse exactamente "attacking". Otro error frecuente es invertir los modificadores: hacer pública la variable del contador y privada la duración. El comportamiento que revela este error es claro: el parámetro nunca pasa a true en el Animator y no aparece ningún error en la consola. La corrección consiste en dejar attackTime pública (se edita en el Inspector) y attackTimeCounter privada (uso interno), y asignar correctamente el valor del contador desde la pública al iniciar el ataque.
Consejos rápidos:
¿Cómo ajustar la experiencia de ataque?
El ajuste fino mejora la sensación del combate y evita inconsistencias entre animación y lógica.
¿Tienes dudas sobre la configuración del Animator o el manejo del contador? Comparte tu caso y comenta qué resultado buscas, así se puede afinar el flujo de ataque y movimiento.
Gabriel Silva
He logrado hacer que el bastón lance una bolita que hace daño, y solo cuando se tiene el bastón equipado
Ikal Esteban Fernández Galván
no se ve
Luis José Leopardi Velásquez
Ricardo Rito Anguiano
Por lo que comentas, parece que tu animación es la que esta dando el problema, si es asi, esta debe tener algun parametro en el cual modifique el transform del personaje, o eso es lo que por ahora podria pensar.
No se si esto te ayude, Igual tu pregunta tiene 3 meses, espero lo hayas podido solucionar :D
Leonardo Gutierrez
Genial
IVÁN ROMERO RODRÍGUEZ
Líam Ayelén Acosta Muñoz
Hola tengo un bug y es que cuando intento de atacar hacia la izquierda ataca hacia la derecha alguien sabe como corregir esto?
Tengo un problema que no he podido resolver, al agregar el blend tree de la animación de ataque, mi jugador deja de moverse, solo ataca y hace la animación de movimiento, pero no se desplaza.
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerController : MonoBehaviour { public float speed = 120.0f; private bool walking = false; public Vector2 lastMovement = Vector2.zero; private const string horizontal = "Horizontal"; private const string vertical = "Vertical"; private const string lastVertical = "LastVertical"; private const string lastHorizontal = "LastHorizontal"; private const string walkingState = "Walking"; private const string attackingState = "Attacking"; private Animator animator; private Rigidbody2D playerRigidbody; public static bool playerCreated; public string nextPlaceName; private bool attacking = false; public float attackTime; private float attackTimeCounter; // Start is called before the first frame update void Start() { animator = GetComponent<Animator>(); playerRigidbody = GetComponent<Rigidbody2D>(); if(!playerCreated) { playerCreated = true; DontDestroyOnLoad(this.transform.gameObject); } else { Destroy(gameObject); } } // Update is called once per frame void Update() { walking = false; if (Input.GetMouseButtonDown(0)) { attacking = true; attackTimeCounter = attackTime; playerRigidbody.velocity = Vector2.zero; animator.SetBool(attackingState, true); } if (attacking) { attackTimeCounter -= Time.deltaTime; if (attackTimeCounter < 0) { attacking = false; animator.SetBool(attackingState, false); } } else { if (Mathf.Abs(Input.GetAxisRaw(horizontal)) > 0.5f) { //this.transform.Translate(new Vector3(Input.GetAxisRaw(horizontal) // * speed // * Time.deltaTime, 0, 0)); playerRigidbody.velocity = new Vector2(Input.GetAxisRaw(horizontal) * speed * Time.deltaTime, playerRigidbody.velocity.y); lastMovement = new Vector2(Input.GetAxisRaw(horizontal), 0); walking = true; Debug.Log(playerRigidbody.velocity.x); } if (Mathf.Abs(Input.GetAxisRaw(vertical)) > 0.5f) { //this.transform.Translate(new Vector3(0, Input.GetAxisRaw(vertical) * speed * Time.deltaTime, 0)); playerRigidbody.velocity = new Vector2(playerRigidbody.velocity.x, Input.GetAxisRaw(vertical) * speed * Time.deltaTime); lastMovement = new Vector2(0, Input.GetAxisRaw(vertical)); walking = true; } } if (!walking) { playerRigidbody.velocity = Vector2.zero; } animator.SetFloat(horizontal, Input.GetAxisRaw(horizontal)); animator.SetFloat(vertical, Input.GetAxisRaw(vertical)); animator.SetFloat(lastHorizontal, lastMovement.x); animator.SetFloat(lastVertical, lastMovement.y); animator.SetBool(walkingState, walking); } }
Yo puse las funciones después de invocar la función de caminar para poder moverme después de atacar y quite el playerRigidbody.velocity.zero, para que no se frene y la verdad es que es muy útil.
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerMovement : MonoBehaviour { public float speed = 2.5f; private bool IsWalking = false; public Vector2 lastMovement = Vector2.zero; private const string horizontal = "Horizontal"; private const string vertical = "Vertical"; private const string lastHorizontal = "LastHorizontal"; private const string lastVertical = "LastVertical"; private const string isWalkingState = "IsWalking"; private const string attackingState = "Attacking"; private Animator animator; private Rigidbody2D playerRb; public static bool playerCreated; public string nextPlaceName; private bool attacking = false; public float attackTime; private float attackTimeCounter; // Start is called before the first frame update void Start() { animator = GetComponent<Animator>(); playerRb = GetComponent<Rigidbody2D>(); if (!playerCreated) { playerCreated = true; DontDestroyOnLoad(this.transform.gameObject); }else { Destroy(gameObject); } } // Update is called once per frame void Update() { // s = v*t; IsWalking = false; if (Mathf.Abs(Input.GetAxisRaw(horizontal)) > 0.5f) { /* this.transform.Translate(new Vector3(Input.GetAxisRaw(horizontal) * speed * Time.deltaTime, 0, 0)); */ playerRb.velocity = new Vector2(Input.GetAxisRaw(horizontal) * speed * Time.deltaTime, playerRb.velocity.y); IsWalking = true; lastMovement = new Vector2(Input.GetAxisRaw(horizontal), 0); } else { playerRb.velocity = new Vector2(0f, playerRb.velocity.y); } if (Mathf.Abs(Input.GetAxisRaw(vertical)) > 0.5f) { /* this.transform.Translate(new Vector3( 0, Input.GetAxisRaw(vertical) * speed * Time.deltaTime, 0)); */ playerRb.velocity = new Vector2(playerRb.velocity.x, Input.GetAxisRaw(vertical) * speed * Time.deltaTime); IsWalking = true; lastMovement = new Vector2(0, Input.GetAxisRaw(vertical)); } else { playerRb.velocity = new Vector2(playerRb.velocity.x, 0f); } if (!IsWalking) { playerRb.velocity = Vector2.zero; } if (Input.GetKey(KeyCode.Z)) { attacking = true; attackTimeCounter = attackTime; animator.SetBool(attackingState, true); } if (attacking) { attackTimeCounter -= Time.deltaTime; if (attackTimeCounter < 0) { attacking = false; animator.SetBool(attackingState, false); } } animator.SetFloat(horizontal, Input.GetAxisRaw(horizontal)); animator.SetFloat(vertical, Input.GetAxisRaw(vertical)); animator.SetBool(isWalkingState, IsWalking); animator.SetFloat(lastHorizontal, lastMovement.x); animator.SetFloat(lastVertical, lastMovement.y); } }