下面是我的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;
}
}
我试图移动某些代码块并简化布尔值,认为这可能会使代码陷入困境。
1条答案
按热度按时间ddrv8njm1#
这将是有帮助的,以获得一个描述你的“小故障”看起来像什么。
无论如何,最奇怪的是运行大量的协程。每一帧
Update()
都会被调用。在攻击过程中的每一帧都会运行StopAttacking
协程。所以,在60 fps和0.5秒的攻击动画持续时间的情况下,你会得到30个例程。每一个例程都会在一段时间后将isAttacking
设置为false
。从我现在看到的,它肯定会导致bug,因为你的状态会随机切换。在将
isAttack
设置为true之后立即开始延迟,而不是其他地方。