簡體   English   中英

Unity - 如何讓我的跳躍動畫循環起作用?

[英]Unity - how do I get my jump animation cycle to work?

我是團結和C#的新手所以非常感謝任何幫助。

我已經使我的精靈跳躍工作得很好,但是,唯一會播放的動畫是着陸動畫。 起飛動畫將不會播放並且精靈停留在空閑位置,同時跳躍直到速度低於0然后着陸動畫播放。

我究竟做錯了什么? 我希望在玩家跳起來然后直接進入落地動畫時播放起飛動畫。

這是我的代碼:

using UnityEngine;

public class Player : MonoBehaviour
{
    private Rigidbody2D myRigidbody;

    private Animator myAnimator;

    [SerializeField]
    private float movementSpeed;

    private bool facingRight;

    private bool attack;

    private bool slide;

    [SerializeField]
    private Transform[] groundPoints;

    [SerializeField]
    private float groundRadius;

    [SerializeField]
    private LayerMask whatIsGround;

    private bool isGrounded;

    private bool jump;

    private bool airControl;

    [SerializeField]
    private float jumpForce;

    // Use this for initialization
    void Start()
    {
        facingRight = true;
        myRigidbody = GetComponent<Rigidbody2D>();
        myAnimator = GetComponent<Animator>();
    }

    void Update()
    {
        HandleInput();
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        float horizontal = Input.GetAxis("Horizontal");

        HandleMovement(horizontal);

        isGrounded = IsGrounded();

        Flip(horizontal);

        HandleAttacks();

        HandleLayers();

        ResetValues();
    }

    private void HandleMovement(float horizontal)
    {
        if (myRigidbody.velocity.y < 0)
        {
            myAnimator.SetBool("land", true);
        }

        if (!myAnimator.GetBool("slide") && !this.myAnimator.GetCurrentAnimatorStateInfo(0).IsTag("Attack")&&(isGrounded || airControl))
        {
            myRigidbody.velocity = new Vector2(horizontal * movementSpeed, myRigidbody.velocity.y);

        }
        if (isGrounded && jump)
        {
            isGrounded = false;
            myRigidbody.AddForce(new Vector2(0, jumpForce));
            myAnimator.SetTrigger("jump");

        }
        if (slide && !this.myAnimator.GetCurrentAnimatorStateInfo(0).IsName("Slide"))
        {
            myAnimator.SetBool("slide", true);
        }
        else if (!this.myAnimator.GetCurrentAnimatorStateInfo(0).IsName("Slide"))
        {
            myAnimator.SetBool("slide", false);
        }
        myAnimator.SetFloat("speed", Mathf.Abs(horizontal));
    }

    private void HandleAttacks()
    {
        if (attack && !this.myAnimator.GetCurrentAnimatorStateInfo(0).IsTag("Attack"))
        {
            myAnimator.SetTrigger("attack");
            myRigidbody.velocity = Vector2.zero;
        }

    }

    private void HandleInput()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            jump = true;
        }
        if (Input.GetKeyDown(KeyCode.LeftShift))
        {
            attack = true;
        }

        if (Input.GetKeyDown(KeyCode.LeftControl))
        {
            slide = true;
        }
    }

    private void Flip(float horizontal)
    {
        if (horizontal > 0 && !facingRight || horizontal < 0 && facingRight)
        {
            facingRight = !facingRight;

            Vector3 theScale = transform.localScale;

            theScale.x *= -1;

            transform.localScale = theScale;
        }
    }

    private void ResetValues()
    {
        attack = false;
        slide = false;
        jump = false;
    }

    private bool IsGrounded()
    {
        if (myRigidbody.velocity.y <= 0)
        {
            foreach (Transform point in groundPoints)
            {
                Collider2D[] colliders = Physics2D.OverlapCircleAll(point.position, groundRadius, whatIsGround);

                for (int i = 0; i < colliders.Length; i++)
                {
                    if (colliders[i].gameObject != gameObject)
                    {
                        myAnimator.ResetTrigger("jump");
                        myAnimator.SetBool("land", false);
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private void HandleLayers()
    {
        if (!isGrounded)
        {
            myAnimator.SetLayerWeight(1, 1);
        }
        else 
        {
            myAnimator.SetLayerWeight(1, 0);
        }
    }
}

我認為你設置動畫的方式使得這比必要的更具挑戰性。 讓我們改變一些有希望使你的角色更容易動畫的東西。

首先,我認為在腳本跳躍動畫時使用動畫trigger是不可靠的。 更好的方法是在你的動畫師中創建一個float ,我稱之為velocityY ,代表玩家的Rigidbody2D.velocity.y 我還創建了一個名為isGrounded的新bool ,因為我認為這更加清晰,更適用於許多“跳轉”場景。

創建這些變量后,您可以通過以下方式鏈接三個動畫 - 空閑,跳躍和着陸 -

  1. 將默認動畫設置為“空閑”。
  2. 從“空閑”轉換到“跳轉”,條件是:

    • velocityY > 0
    • isGrounded = false
  3. 根據以下條件從“跳躍”過渡到“陸地”:

    • velocityY < 0
    • isGrounded = false
  4. isGrounded = true時,從“land”轉換為“idle”。

  5. 最后,要在角色落下時為其制作動畫(不先跳躍),您可以選擇從“空閑”過渡到“陸地”,其中:

    • velocityY < 0
    • isGrounded = false

現在到代碼。 這是我在項目中測試的一個工作示例,以實現您期望的結果。 請注意,我沒有在腳本中包含所有內容,只包括讓角色移動並正確設置其跳轉動畫的部分。 嘗試使用此腳本並使用移動值以及播放器的Rigidbody2D組件上的重力倍增器; 默認值和重力乘數3.5對我來說很有趣!

using UnityEngine;

public class Player : MonoBehaviour
{
    //Components on Player GameObject
    private Rigidbody2D myRigidbody;
    private Animator myAnimator;

    //Movement variables
    [SerializeField]
    private float movementSpeed = 9; //Set default values so you don't always
    [SerializeField]                //have to remember to set them in the inspector
    private float jumpForce = 15;

    //Ground checking
    [SerializeField]
    private Transform groundPoint;
    [SerializeField]
    private float groundRadius = 0.1f;
    [SerializeField]
    private LayerMask whatIsGround;

    private float velocityX;
    private bool isGrounded;
    private bool facingRight;

    // Use this for initialization
    private void Start()
    {
        facingRight = true;
        myRigidbody = GetComponent<Rigidbody2D>();
        myAnimator = GetComponent<Animator>();
    }

    private void Update()
    {
        Flip();
        HandleInput();
        HandleAnimations();
    }

    private void FixedUpdate()
    {                       
        HandleMovement();  //It's generally considered good practice to 
                           //call physics-related methods in FixedUpdate
    }

    private void HandleAnimations()
    {
        if (!isGrounded)
        {
            myAnimator.SetBool("isGrounded", false);

            //Set the animator velocity equal to 1 * the vertical direction in which the player is moving 
            myAnimator.SetFloat("velocityY", 1 * Mathf.Sign(myRigidbody.velocity.y));
        }

        if (isGrounded)
        {
            myAnimator.SetBool("isGrounded", true);
            myAnimator.SetFloat("velocityY", 0);
        }
    }

    private void HandleMovement()
    {
        isGrounded = Physics2D.OverlapCircle(groundPoint.position, groundRadius, whatIsGround);

        velocityX = Input.GetAxis("Horizontal");

        myRigidbody.velocity = new Vector2(velocityX * movementSpeed , myRigidbody.velocity.y);
    }

    private void HandleInput()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Jump();
        }
    }

    private void Jump()
    {
        if (isGrounded)
        {   //ForceMode2D.Impulse is useful if Jump() is called using GetKeyDown
            myRigidbody.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
        }

        else 
        {
            return;
        }       
    }

    private void Flip()
    {
        if (velocityX > 0 && !facingRight || velocityX < 0 && facingRight)
        {
            facingRight = !facingRight;

            Vector3 theScale = transform.localScale;
            theScale.x *= -1;

            transform.localScale = theScale;
        }
    }
}

我還花了一些時間來重新組織你的代碼。 你現在不一定需要關注太多組織,但我認為你可能會感興趣,因為你還在學習。

如您所見,腳本中的每個方法都處理一個具體的任務。 例如,有一種方法專門用於處理動畫,另一種方法可以讓玩家跳躍。 以這種方式設置代碼是個好主意,這樣如果你以后必須改變一個方面,比如玩家移動,那么所有相關代碼都在同一個地方。 我認為創建處理玩家“行動”(如跳躍或攻擊)的方法尤其如此; 如果你有足夠的,你甚至可以創建一個完整的Actions class

最后要提到的是這行代碼:

isGrounded = Physics2D.OverlapCircle(groundPoint.position, groundRadius, whatIsGround);

我發現這是一種更容易確定玩家何時接地的方法。 我通過向玩家添加一個兒童GameObject來實現這一點,添加了一個彩色圖標以便於放置(您可以通過單擊GameObject名稱附近的彩色框來完成此操作),並將其放置在玩家的腳之間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM