unity3d Unity代码不工作,当攻击快速点击时动画出现故障

wpx232ag  于 2023-03-30  发布在  其他
关注(0)|答案(1)|浏览(162)

下面是我的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;
    }

}

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

ddrv8njm

ddrv8njm1#

这将是有帮助的,以获得一个描述你的“小故障”看起来像什么。
无论如何,最奇怪的是运行大量的协程。每一帧Update()都会被调用。在攻击过程中的每一帧都会运行StopAttacking协程。所以,在60 fps和0.5秒的攻击动画持续时间的情况下,你会得到30个例程。每一个例程都会在一段时间后将isAttacking设置为false
从我现在看到的,它肯定会导致bug,因为你的状态会随机切换。在将isAttack设置为true之后立即开始延迟,而不是其他地方。

相关问题