简体   繁体   English

第一次重新加载后Unity 2D跳跃高度不同

[英]Unity 2D Jump Height different after first reloading

Recently I got into Unity and I have a weird bug that my character's jump height is only higher after the first reload(respawn) on the first scene I am running.最近我进入了 Unity,我有一个奇怪的错误,我的角色的跳跃高度只有在我运行的第一个场景中第一次重新加载(重生)后才会更高。

Scenario 1:场景一:

  • Scene 1 is being loaded.正在加载场景 1。 Character is jumping at the correct height.角色以正确的高度跳跃。
  • Character dies.人物死亡。 Scene 1 is reloaded and character is respawned.场景 1 重新加载,角色重生。 Character now jumps much higher than intended.角色现在跳得比预期高得多。
  • Clear Scene 1, moves to Scene 2. Character now behaves normally (even after respawning).清除场景 1,移动到场景 2。角色现在行为正常(即使在重生后)。

Scenario 2:场景2:

  • Scene 2 is being loaded.正在加载场景 2。 The exact problem in Scenario 1 occur in Scene 2. (because it is the first scene I run)场景1中的确切问题发生在场景2中。(因为它是我运行的第一个场景)
  • Clear Scene 2, moves to Scene 3. Character now behaves normally (even after respawning).清除场景 2,移动到场景 3。角色现在行为正常(即使在重生之后)。

I have been on this for hours and I still could not figure out where is the bug.我已经研究了几个小时,但我仍然无法弄清楚错误在哪里。

CharacterController Script角色控制器脚本

using UnityEngine;
using UnityEngine.Events;

public class CharacterController2D : MonoBehaviour
{
    [SerializeField] private float m_JumpForce = 200f;                          // Amount of force added when the player jumps.
    [Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f;  // How much to smooth out the movement
    [SerializeField] private bool m_AirControl = false;                         // Whether or not a player can steer while jumping;
    [SerializeField] private LayerMask m_WhatIsGround;                          // A mask determining what is ground to the character
    [SerializeField] private Transform m_GroundCheck;                           // A position marking where to check if the player is grounded.
    [SerializeField] private Transform m_CeilingCheck;                          // A position marking where to check for ceilings
    [SerializeField] private Collider2D m_CrouchDisableCollider;                // A collider that will be disabled when crouching

    private System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
    const float k_GroundedRadius = .2f; // Radius of the overlap circle to determine if grounded
    private bool m_Grounded;            // Whether or not the player is grounded.
    const float k_CeilingRadius = .2f; // Radius of the overlap circle to determine if the player can stand up
    private Rigidbody2D m_Rigidbody2D;
    private bool m_FacingRight = true;  // For determining which way the player is currently facing.
    private Vector3 m_Velocity = Vector3.zero;

    [Header("Events")]
    [Space]

    public UnityEvent OnLandEvent;

    [System.Serializable]
    public class BoolEvent : UnityEvent<bool> { }

    private void Awake()
    {
        m_Rigidbody2D = GetComponent<Rigidbody2D>();

        if (OnLandEvent == null)
            OnLandEvent = new UnityEvent();
    }
    
    private void FixedUpdate()
    {

        if (!m_Grounded)
        { 
            sw.Start();
        }

        m_Grounded = false;


        // The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
        // This can be done using layers instead but Sample Assets will not overwrite your project settings.
        Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
        for (int i = 0; i < colliders.Length; i++)
        {
            if (colliders[i].gameObject != gameObject)
            {
                //sw.Stop();
                m_Grounded = true;
               if (sw.ElapsedMilliseconds > (long)60)
                    OnLandEvent.Invoke(); 
                sw.Reset();
            }
        }
    }


    public void Move(float move, bool jump)
    {

        //only control the player if grounded or airControl is turned on
        if (m_Grounded || m_AirControl)
        {

            // Move the character by finding the target velocity
            Vector3 targetVelocity = new Vector2(move * 10f, m_Rigidbody2D.velocity.y);
            // And then smoothing it out and applying it to the character
            m_Rigidbody2D.velocity = Vector3.SmoothDamp(m_Rigidbody2D.velocity, targetVelocity, ref m_Velocity, m_MovementSmoothing);

            // If the input is moving the player right and the player is facing left...
            if (move > 0 && !m_FacingRight)
            {
                // ... flip the player.
                Flip();
            }
            // Otherwise if the input is moving the player left and the player is facing right...
            else if (move < 0 && m_FacingRight)
            {
                // ... flip the player.
                Flip();
            }
        }
        // If the player should jump...
        if (m_Grounded && jump)
        {
            // Add a vertical force to the player.
            m_Grounded = false;
            m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));
        }
    }

    
    private void Flip()
    {
        // Switch the way the player is labelled as facing.
        m_FacingRight = !m_FacingRight;

        // Multiply the player's x local scale by -1.
        Vector3 theScale = transform.localScale;
        theScale.x *= -1;
        transform.localScale = theScale;
    }
}

CharacterMovement Script角色移动脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CharacterMovement : MonoBehaviour
{

    public CharacterController2D controller;
    public Animator animator;
    public Joystick joystick;
    public float horizontalMove = 0;
    public float runSpeed = 40f;
    public bool jump = false;
    
    // Update is called once per frame
    void Update()
    {
        
        if(joystick.Horizontal >= .2f){

            horizontalMove = runSpeed;

        }else if(joystick.Horizontal <= -.2f){

            horizontalMove = -runSpeed;

        }else{

            horizontalMove = 0;

        }

        animator.SetFloat("Speed", Mathf.Abs(horizontalMove));
        
        float verticalMove = joystick.Vertical;

        if(verticalMove >= .5f){

            jump = true;
            animator.SetBool("IsJumping", true);

        }

    }

    public void OnLanding() {

        animator.SetBool("IsJumping", false);

    }
    void FixedUpdate() {

        controller.Move(horizontalMove * Time.fixedDeltaTime, jump);
        jump = false;

    }

}

CharacterDeath Script角色死亡脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CharacterDeath : MonoBehaviour
{   
    [SerializeField] GameObject DustCloud;
    //To avoid multiple water splash sound playing
    private bool splashed = false;
    public void OnCollisionEnter2D(Collision2D other){

        if(other.gameObject.CompareTag("Enemy")){

            gameObject.SetActive(false);
            Instantiate(DustCloud, transform.position, DustCloud.transform.rotation);
            Invoke("LMRespawn", 2.5f);
            
        }
    }

    public void OnTriggerEnter2D(Collider2D other) {

       if(other.CompareTag("Water") && !splashed){

                AudioManager.instance.PlaySound("WaterSplashSFX");
                splashed = true;

        } 
    }

    //Adds delay before respawning
    void LMRespawn(){

        LevelManager.instance.Respawn();
        splashed = false;

    }
}

LevelManager Script关卡管理器脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelManager : MonoBehaviour
{
    public static LevelManager instance;
    public Transform respawnPoint;
    public GameObject characterPrefab;
    private void Awake(){

        instance = this;
    }

    public void Respawn(){

        //Instantiate(characterPrefab, respawnPoint.position, Quaternion.identity);
        Scene CS = SceneManager.GetActiveScene();
        SceneManager.LoadScene(CS.name);

    }

}

Please let me know if any more information is needed.如果需要更多信息,请告诉我。

Multiply the jump force with Time.DeltaTime.用 Time.DeltaTime 乘以跳跃力。

Time.DeltaTime is the represents the completion time in seconds since the last frame, so multiplying or jumpForce with it will make sure that we jump the same height no matter of the frame rate we get on different devices, or when the frame rate drops. Time.DeltaTime 表示自上一帧以来的完成时间(以秒为单位),因此乘以或 jumpForce 将确保我们跳跃相同的高度,无论我们在不同设备上获得的帧速率如何,或者帧速率何时下降。

Notice that you're also applying force in the CharacterController class inside the Move function: m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));请注意,您还在Move函数内的 CharacterController 类中施加了力: m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM