首页 > 解决方案 > Unity 2D - 跳转功能无法正常工作

问题描述

我是编码和 Unity2D 的新手,所以请多多包涵。

我创建了一个角色控制器,它通过针对 UI 按钮对象设置的 EventTriggers 调用。控制器工作正常(虽然可能是矫枉过正),但以下是我遇到的跳跃功能的挑战。对此的任何帮助都非常感谢。

非常感谢!

挑战

这是脚本:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class GameController : MonoBehaviour
    {
        Rigidbody2D rb2d;
        SpriteRenderer spriteRenderer;
        Animator animator;
        public Transform groundCheck;
        private LayerMask groundLayer = 1 << LayerMask.NameToLayer ("groundLayer");
        private bool moveLeft;
        private bool moveRight;
        private bool moveJump;
        private bool isGrounded;
        private float horizontalMove;
        private float verticalMove;
        public float playerSpeed = 0f;
        public float jumpForce = 0f;
        public float groundCheckRadius;
    
        public void Start()
        {
            rb2d = GetComponent<Rigidbody2D>();
            spriteRenderer = GetComponent<SpriteRenderer>();
            animator = GetComponent<Animator>();
    
            moveLeft = false;
            moveRight = false;
            moveJump = false;
        }
    
        //Function - Left button pressed
        public void MoveLeft()
        {
            moveLeft = true;
            Debug.Log("Function - Move Left");
        }
    
        //Function - Right button pressed
        public void MoveRight()
        {
            moveRight = true;
            Debug.Log("Function - Move Right");
        }
    
        //Function - Jump button pressed
        public void MoveJump()
        {
            moveJump = true;
            Debug.Log("Function - Move Jump");
        }
    
        //Function - Stop player movement
        public void MoveStop()
        {
            rb2d.velocity = Vector3.zero;
            animator.Play("PlayerIdle");
            moveLeft = false;
            moveRight = false;
            moveJump = false;
        }
    
        //Function - Check if player 'GroundCheck' is touching the ground layer
        private void PlayerGrounded()
        {
            isGrounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer);
    
            if (isGrounded == true)
            {
                Debug.Log("Player is touching the ground!");
            }
    
            if (isGrounded == false)
            {
                Debug.Log("Player is not touching the ground!");
            }
    
        }
    
        //Function - Plays once every frame
        private void Update()
        {
            PlayerMovement();
    
            PlayerGrounded();
        }
    
        //Function - Move the player GameObject
        public void PlayerMovement()
        {
    
            //Set the player horizontal right axis
            if (moveRight)
            {
                horizontalMove = playerSpeed;
                Debug.Log("Function - PlayerMovement - Move Right!");
            }
    
            //Set the player horizontal left axis
            if (moveLeft)
            {
                horizontalMove = -playerSpeed;
                Debug.Log("Function - PlayerMovement - Move Left!");
            }
    
            //Set the player vertical axis
            if (moveJump)
            {
                verticalMove = jumpForce;
                Debug.Log("Function - PlayerMovement - Move Jump!");
            }
    
        }
    
        //Function - Plays once every loaded frame
        private void FixedUpdate()
        {
    
            //Move the player right, don't flip, play animation
            if (moveRight)
            {
                rb2d.velocity = new Vector2(horizontalMove, rb2d.velocity.y * playerSpeed * Time.deltaTime);
                spriteRenderer.flipX = false;
                animator.Play("PlayerRun");
                Debug.Log("Function - Player Moving Right!");
            }
    
            //Move the player left, don't flip, play animation
            if (moveLeft)
            {
                rb2d.velocity = new Vector2(horizontalMove, rb2d.velocity.y * playerSpeed * Time.deltaTime);
                spriteRenderer.flipX = true;
                animator.Play("PlayerRun");
                Debug.Log("Function - Player Moving Left!");
            }
    
            //Move the player into the air via a jump
            if (moveJump && (rb2d.velocity.y == 0))
            {
                rb2d.velocity = new Vector2(verticalMove, rb2d.velocity.x * jumpForce);
                animator.Play("PlayerJump");
                Debug.Log("Function - Player Moving Up!");
            }
    
        }
    
    }

标签: unity3d

解决方案


问题出在固定更新的末尾。这就是你所拥有的:

if (moveJump && (rb2d.velocity.y == 0))
{
    rb2d.velocity = new Vector2(verticalMove, rb2d.velocity.x * jumpForce);
    animator.Play("PlayerJump");
    Debug.Log("Function - Player Moving Up!");
}

让我们看看开头。它说if (moveJump && (rb2d.velocity.y == 0)。所以,(我假设你在他们按下跳跃按钮时设置 moveJump)如果你按下跳跃按钮并且y速度为0。但是,这与玩家是否在地面上无关。我们应该将其更改为if (moveJump && isGrounded). 这样,它会在跳转之前检查 isGrounded 是否为真。

当您将速度更改为跳跃时,我注意到几个问题。这就是它所说的:

rb2d.velocity = new Vector2(verticalMove, rb2d.velocity.x * jumpForce);

创建新的 Vector2 时,第一个参数是x,第二个参数是y。您正在以相反的顺序进行操作。你做了y,然后x。你应该像这样交换它们:

rb2d.velocity = new Vector2(rb2d.velocity.x, verticalMove * jumpForce);

由于此交换,您将跳转应用到 x 轴,并移动到 y 轴,但现在它已修复。

这是所有的变化:

if (moveJump && (rb2d.velocity.y == 0))
{
    rb2d.velocity = new Vector2(verticalMove, rb2d.velocity.x * jumpForce);
    animator.Play("PlayerJump");
    Debug.Log("Function - Player Moving Up!");
}

推荐阅读