Unity中的2D角色跳不起来问题

时间:2018-12-30 10:31:25

标签: c# visual-studio unity3d

我是Unity和C#的新手,正尝试制作2D游戏。 附加了所有过渡的动画师控制器屏幕截图,从空闲到跳转的{isGrounded)布尔值为false,从跳转到空闲的布尔值为true,从运行到跳转的布尔值为false,但是在这种情况下,角色没有不会跳跃,它会摇晃,从怠速过渡到非常快的跳跃。当我删除跳跃动画时,角色会正常移动,但当然不会跳跃。这可能是什么问题?

enter image description here

这也是CharacterController2D脚本:

    public float jumpForce = 600f;

    // player health
    public int playerHealth = 1;

    // LayerMask to determine what is considered ground for the player
    public LayerMask whatIsGround;

    internal void EnemyBounce(CharacterController2D characterController2D)
    {
        throw new NotImplementedException();
    }
    // Transform just below feet for checking if player is grounded
    public Transform groundCheck;

    // player can move?
    // we want this public so other scripts can access it but we don't want to show in editor as it might confuse designer
    [HideInInspector]
    public bool playerCanMove = true;

    // SFXs
    public AudioClip coinSFX;
    public AudioClip deathSFX;
    public AudioClip fallSFX;
    public AudioClip jumpSFX;
    public AudioClip victorySFX;

    // private variables below

    // store references to components on the gameObject
    Transform _transform;
    Rigidbody2D _rigidbody;
    Animator _animator;
    AudioSource _audio;
    // hold player motion in this timestep
    float _vx;
    float _vy;

    // player tracking
    bool _facingRight = true;
    bool _isGrounded = false;
    bool _isRunning = false;
    bool _canDoubleJump = false;

    // store the layer the player is on (setup in Awake)
    int _playerLayer;

    // number of layer that Platforms are on (setup in Awake)
    int _platformLayer;

    void Awake()
    {
        // get a reference to the components we are going to be changing and store a reference for efficiency purposes
        _transform = GetComponent<Transform>();

        _rigidbody = GetComponent<Rigidbody2D>();
        if (_rigidbody == null) // if Rigidbody is missing
            Debug.LogError("Rigidbody2D component missing from this gameobject");

        _animator = GetComponent<Animator>();
        if (_animator == null) // if Animator is missing
            Debug.LogError("Animator component missing from this gameobject");

        _audio = GetComponent<AudioSource>();
        if (_audio == null)
        { // if AudioSource is missing
            Debug.LogWarning("AudioSource component missing from this gameobject. Adding one.");
            // let's just add the AudioSource component dynamically
            _audio = gameObject.AddComponent<AudioSource>();
        }

        // determine the player's specified layer
        _playerLayer = this.gameObject.layer;

        // determine the platform's specified layer
        _platformLayer = LayerMask.NameToLayer("Platform");
    }

    // this is where most of the player controller magic happens each game event loop
    void Update()
    {
        // exit update if player cannot move or game is paused
        if (!playerCanMove || (Time.timeScale == 0f))
            return;

        // determine horizontal velocity change based on the horizontal input
        _vx = CrossPlatformInputManager.GetAxisRaw("Horizontal");

        // Determine if running based on the horizontal movement
        if (_vx != 0)
        {
            _isRunning = true;
        }
        else
        {
            _isRunning = false;
        }

        // set the running animation state
        _animator.SetBool("Running", _isRunning);

        // get the current vertical velocity from the rigidbody component
        _vy = _rigidbody.velocity.y;

        // Check to see if character is grounded by raycasting from the middle of the player
        // down to the groundCheck position and see if collected with gameobjects on the
        // whatIsGround layer
        _isGrounded = Physics2D.Linecast(_transform.position, groundCheck.position, whatIsGround);
        // allow double jump after grounded
        if (_isGrounded)
        {
            _canDoubleJump = true;
        }
        // Set the grounded animation states
        _animator.SetBool("Grounded", _isGrounded);

        if (_isGrounded && CrossPlatformInputManager.GetButtonDown("Jump")) // If grounded AND jump button pressed, then allow the player to jump
        {

            DoJump();
        }
        else if (_canDoubleJump && CrossPlatformInputManager.GetButtonDown("Jump")) // If candoublejump and jump button pressed, then allow player to double jump
        {
            DoJump();
            // disable double hump after double jumping since you can only really do it once
            _canDoubleJump = false;
        }

        // If the player stops jumping mid jump and player is not yet falling
        // then set the vertical velocity to 0 (he will start to fall from gravity)
        if (CrossPlatformInputManager.GetButtonUp("Jump") && _vy > 0f)
        {
            _vy = 0f;
        }

        // Change the actual velocity on the rigidbody
        _rigidbody.velocity = new Vector2(_vx * moveSpeed, _vy);

        // if moving up then don't collide with platform layer
        // this allows the player to jump up through things on the platform layer
        // NOTE: requires the platforms to be on a layer named "Platform"
        Physics2D.IgnoreLayerCollision(_playerLayer, _platformLayer, (_vy > 0.0f));
    }

    // Checking to see if the sprite should be flipped
    // this is done in LateUpdate since the Animator may override the localScale
    // this code will flip the player even if the animator is controlling scale
    void LateUpdate()
    {
        // get the current scale
        Vector3 localScale = _transform.localScale;

        if (_vx > 0) // moving right so face right
        {
            _facingRight = true;
        }
        else if (_vx < 0)
        { // moving left so face left
            _facingRight = false;
        }

        // check to see if scale x is right for the player
        // if not, multiple by -1 which is an easy way to flip a sprite
        if (((_facingRight) && (localScale.x < 0)) || ((!_facingRight) && (localScale.x > 0)))
        {
            localScale.x *= -1;
        }

        // update the scale
        _transform.localScale = localScale;
    }

    // if the player collides with a MovingPlatform, then make it a child of that platform
    // so it will go for a ride on the MovingPlatform
    void OnCollisionEnter2D(Collision2D other)
    {
        if (other.gameObject.tag == "MovingPlatform")
        {
            this.transform.parent = other.transform;
        }
    }

    // if the player exits a collision with a moving platform, then unchild it
    void OnCollisionExit2D(Collision2D other)
    {
        if (other.gameObject.tag == "MovingPlatform")
        {
            this.transform.parent = null;
        }
    }

    //make the player jump
    void DoJump()
    {
        // reset current vertical motion to 0 prior to jump
        _vy = 0f;
        // add a force in the up direction
        _rigidbody.AddForce(new Vector2(4, jumpForce));
        // play the jump sound
        PlaySound(jumpSFX);
    }
    // do what needs to be done to freeze the player
    void FreezeMotion()
    {
        playerCanMove = false;
        _rigidbody.velocity = new Vector2(0, 0);
        _rigidbody.isKinematic = true;
    }

    // do what needs to be done to unfreeze the player
    void UnFreezeMotion()
    {
        playerCanMove = true;
        _rigidbody.isKinematic = false;
    }

    // play sound through the audiosource on the gameobject
    void PlaySound(AudioClip clip)
    {
        _audio.PlayOneShot(clip);
    }

    // public function to apply damage to the player
    public void ApplyDamage(int damage)
    {
        if (playerCanMove)
        {
            playerHealth -= damage;

            if (playerHealth <= 0)
            { // player is now dead, so start dying
                PlaySound(deathSFX);
                StartCoroutine(KillPlayer());
            }
        }
    }

    // public function to kill the player when they have a fall death
    public void FallDeath()
    {
        if (playerCanMove)
        {
            playerHealth = 0;
            PlaySound(fallSFX);
            StartCoroutine(KillPlayer());
        }
    }

    // coroutine to kill the player
    IEnumerator KillPlayer()
    {
        if (playerCanMove)
        {
            // freeze the player
            FreezeMotion();

            // play the death animation
            _animator.SetTrigger("Death");

            // After waiting tell the GameManager to reset the game
            yield return new WaitForSeconds(2.0f);

            if (GameManager.gm) // if the gameManager is available, tell it to reset the game
                GameManager.gm.ResetGame();
            else // otherwise, just reload the current level
                SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        }
    }

    public void CollectCoin(int amount)
    {
        PlaySound(coinSFX);

        if (GameManager.gm) // add the points through the game manager, if it is available
            GameManager.gm.AddPoints(amount);
    }

    // public function on victory over the level
    public void Victory()
    {
        PlaySound(victorySFX);
        FreezeMotion();
        _animator.SetTrigger("Victory");

        if (GameManager.gm) // do the game manager level compete stuff, if it is available
            GameManager.gm.LevelCompete();
    }

    // public function to respawn the player at the appropriate location
    public void Respawn(Vector3 spawnloc)
    {
        UnFreezeMotion();
        playerHealth = 1;
        _transform.parent = null;
        _transform.position = spawnloc;
        _animator.SetTrigger("Respawn");
    }
    public void EnemyBounce()
    {
        DoJump();
    }
}

我还尝试添加一个单独的Jump脚本,它不起作用。

1 个答案:

答案 0 :(得分:0)

在阅读代码的同时做些笔记...

此:

// Determine if running based on the horizontal movement
if (_vx != 0)
{
    _isRunning = true;
}
else
{
    _isRunning = false;
}

// set the running animation state
_animator.SetBool("Running", _isRunning);

可以替换为

_isRunning = _vx != 0;
_animator.SetBool("Running", _isRunning);

甚至只是创建属性访问器

bool _isRunning { 
    get {
        return _vx != 0;
    }
}

关于您的实际问题;我看不到您的转换,但我假设它们有问题,请继续尝试通过删除SetBools进行调试,并检查Animator触发了什么。任何状态->空闲状态都很可疑。