统一代码不工作和动画故障时,攻击点击迅速



这是我的playerMovement脚本代码,它应该直接调用某些动画。我正在尝试执行不同的攻击动画,并在玩家再次攻击之前设置与动画相同的延迟。我已经尝试了许多不同的延迟类型,协程,调用方法,甚至一个外部的等待函数传递给lambda函数,但无论如何,当你按下攻击太快时,这个愚蠢的东西就会出故障。

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.AdaptivePerformance.Provider;
using UnityEngine.EventSystems;
public class PlayerMovement : MonoBehaviour
{
// Initialize variables
// Private variables
private float moveHorizontal = 0;
private float moveVertical = 0;
private float attackDelay;
// Public variables
public float moveSpeed = 1.0f;
public float movePenalty = 0.7f;
// Initialize boolean variables for various action events
private bool isAttacking = false;
// Initialize Components
public MobileJoystick mobileJoystick;
private Rigidbody2D rb;
private Animator animator;
// Animation States
private string currentState;
const string IDLE = "HeroIdle";
const string WALK_X = "WalkHoriz";
const string WALK_Y = "WalkVertical";
const string WALK_DIAG = "WalkDiagonal";
const string ATTACK = "MeleeAttack";
const string BLOCK = "ShieldBlock";
const string THRUST = "Thrust";
const string UPSLASH = "UpSlash";
const string DOWNSLASH = "DownSlash";
void Start()
{
// Get the players rigidbody
rb = GetComponent<Rigidbody2D>();
// Get the animator
animator = GetComponent<Animator>();
// Set the animation state
ChangeAnimationState(IDLE);
}
void Update()
{
// Update movement to current moveHorizontal and moveVertical
Vector2 movement = new Vector2(moveHorizontal, moveVertical);
// Update Movement based on whether moving or attacking
if (isAttacking)
{
// Input Movement Vectors
moveHorizontal = Input.GetAxis("Horizontal") + mobileJoystick.InputDirection.x;
moveVertical = Input.GetAxis("Vertical") + mobileJoystick.InputDirection.y;
rb.velocity = movement * movePenalty;
// Wait until animation completely finishes (gets the length of animation)
attackDelay = animator.GetCurrentAnimatorStateInfo(0).length;
// After the waited amount of time, allow the player to move again.
StartCoroutine(StopAttacking(attackDelay));
}
else
{
// Input Movement Vectors
moveHorizontal = Input.GetAxis("Horizontal") + mobileJoystick.InputDirection.x;
moveVertical = Input.GetAxis("Vertical") + mobileJoystick.InputDirection.y;
rb.velocity = movement * moveSpeed;
// Animate Walking for character based on direction (up/down or left/right)
// Note these are important checks because of future mobile implementation
// Check left / right movement is non-zero and more than vertical movement
if (moveHorizontal != 0 && Mathf.Abs(moveHorizontal) > Mathf.Abs(moveVertical))
{
ChangeAnimationState(WALK_X);
}
// Check up / down movement is non-zero and vertical more than horizontal
else if (moveVertical != 0 && Mathf.Abs(moveVertical) > Mathf.Abs(moveHorizontal))
{
ChangeAnimationState(WALK_Y);
}
// Check perfect diagonal movement
else if (moveVertical != 0 && Mathf.Abs(moveVertical) == Mathf.Abs(moveHorizontal))
{
ChangeAnimationState(WALK_DIAG);
}
// Else, IDLE
else
{
ChangeAnimationState(IDLE);
}
}

// Flip the Character Left or Right based on their direction
// If the player is moving left and the character is not flipped, flip the character
if (moveHorizontal < 0 && transform.localScale.x > 0)
{
Vector3 flippedScale = transform.localScale;
flippedScale.x = -0.05f;
transform.localScale = flippedScale;
}
// If the player is moving right and the character is flipped, unflip the character
else if (moveHorizontal > 0 && transform.localScale.x < 0)
{
Vector3 unflippedScale = transform.localScale;
unflippedScale.x = 0.05f;
transform.localScale = unflippedScale;
}

// Check Action animations
// Combat and Attacking (and taking damage)
// Get attack input
if (!isAttacking && Input.GetButtonDown("Fire1"))
{
// Set the isAttacking bool to true to prevent movement / other actions
isAttacking = true;
// Animate the attack
// Check which type of attack based on player input directions
if(moveHorizontal != 0 && Mathf.Abs(moveHorizontal) > Mathf.Abs(moveVertical))
{
ChangeAnimationState(THRUST);
}
else if(moveVertical > 0 && Mathf.Abs(moveHorizontal) < Mathf.Abs(moveVertical))
{
ChangeAnimationState(UPSLASH);
}
else if(moveVertical < 0 && Mathf.Abs(moveHorizontal) < Mathf.Abs(moveVertical))
{
ChangeAnimationState(DOWNSLASH);
}
else
{
ChangeAnimationState(ATTACK);
}
}
// Debugging 
Debug.Log("IsAttacking: " + isAttacking);
Debug.Log("currentState: " + currentState);
Debug.Log("attackDelay: " + attackDelay);

}
void ChangeAnimationState(string newState)
{
//stop the same animation from interrupting itself
if (currentState == newState) return;
//play the animation
animator.Play(newState);
//reassign the current state
currentState = newState;

}
//void StopAttacking()
//{
//    isAttacking = false;
//}
IEnumerator StopAttacking(float waitTime)
{
yield return new WaitForSeconds(waitTime);
isAttacking = false;
}
}

我试图移动某些代码块并简化布尔值,认为这可能会使代码陷入困境。

如果你能得到"故障"的描述将会很有帮助。样子。

不管怎样,最奇怪的是要运行大量的协程。每一帧Update()都会被调用。攻击过程中的每一帧都将运行StopAttacking协程。所以,在60 fps和0.5秒攻击动画持续时间的情况下,你将获得30个例程。经过一段时间后,它们各自将isAttacking设置为false

从我现在看到的,这肯定会导致bug,因为你的状态会随机切换。在将isAttack设置为true后立即启动延迟,其他任何地方都不能启动。