角色有时不跳-Unity

问题描述

我是Unity新手,我使用以下 CharacterController 作为我的角色。一切都运行良好,除了有时当我按下空格键时角色会跳跃而有时却不会。我使用Raycast使用Debog.Log来检查我的角色是否接地,并且结果为True。那么,是什么阻止了我的角色在我按下按键时跳动?

using UnityEngine;
using System.Collections;
 
[RequireComponent(typeof(CharacterController))]
public class Rpgmovement : MonoBehavIoUr
{
    public float ForwardSpeed = 8f;
    public float BackwardSpeed = 4f;
    public float StrafeSpeed = 5f;
    public float RotateSpeed = 110f;
 
    CharacterController m_CharacterController;
    Vector3 m_LastPosition;
    Animator m_Animator;
    PhotonView m_PhotonView;
    PhotonTransformView m_TransformView;
 
    float m_AnimatorSpeed;
    Vector3 m_CurrentMovement;
    float m_CurrentTurnSpeed;
 
    Vector3 playerVeLocity;
    private bool groundedplayer;
    private float jumpHeight = 0.9f;
    private float gravityValue = -20.81f;
 
    void Start()
    {
        m_CharacterController = GetComponent<CharacterController>();
        m_Animator = GetComponent<Animator>();
        m_PhotonView = GetComponent<PhotonView>();
        m_TransformView = GetComponent<PhotonTransformView>();
    }
 
    void Update()
    {
        if (m_PhotonView.ismine == true)
        {
            ResetSpeedValues();
            UpdateRotateMovement();
            UpdateForwardMovement();
            UpdateBackwardMovement();
            UpdateStrafeMovement();          
            MoveCharacterController();
            UpdateJump();
            ApplySynchronizedValues();
        }
        UpdateAnimation();
    }
 
    void UpdateAnimation()
    {
        Vector3 movementVector = transform.position - m_LastPosition;
 
        float speed = Vector3.Dot(movementVector.normalized,transform.forward);
        float direction = Vector3.Dot(movementVector.normalized,transform.right);
 
        if (Mathf.Abs(speed) < 0.2f)
        {
            speed = 0f;
        }
 
        if (speed > 0.6f)
        {
            speed = 1f;
            direction = 0f;
        }
 
        if (speed >= 0f)
        {
            if (Mathf.Abs(direction) > 0.7f)
            {
                speed = 1f;
            }
        }
 
        m_AnimatorSpeed = Mathf.Movetowards(m_AnimatorSpeed,speed,Time.deltaTime * 5f);
 
        m_Animator.SetFloat("Speed",m_AnimatorSpeed);
        m_Animator.SetFloat("Direction",direction);
 
        m_LastPosition = transform.position;
    }
 
    void ResetSpeedValues()
    {
        m_CurrentMovement = Vector3.zero;
        m_CurrentTurnSpeed = 0;
    }
 
    void ApplySynchronizedValues()
    {
        m_TransformView.SetSynchronizedValues(m_CurrentMovement,m_CurrentTurnSpeed);
    }
 
    void MoveCharacterController()
    {
        m_CharacterController.Move(m_CurrentMovement * Time.deltaTime);
    }
 
    void UpdateForwardMovement()
    {
        if (Input.GetKey(KeyCode.W) || Input.GetAxisRaw("Vertical") > 0.1f)
        {
            m_CurrentMovement = transform.forward * ForwardSpeed;
        }
    }
 
    void UpdateBackwardMovement()
    {
        if (Input.GetKey(KeyCode.S) || Input.GetAxisRaw("Vertical") < -0.1f)
        {
            m_CurrentMovement = -transform.forward * BackwardSpeed;
        }
    }
 
    void UpdateStrafeMovement()
    {
        if (Input.GetKey(KeyCode.Q) == true)
        {
            m_CurrentMovement = -transform.right * StrafeSpeed;
        }
 
        if (Input.GetKey(KeyCode.E) == true)
        {
            m_CurrentMovement = transform.right * StrafeSpeed;
        }
    }
 
    void UpdateRotateMovement()
    {
        if (Input.GetKey(KeyCode.A) || Input.GetAxisRaw("Horizontal") < -0.1f)
        {
            m_CurrentTurnSpeed = -RotateSpeed;
            transform.Rotate(0.0f,-RotateSpeed * Time.deltaTime,0.0f);
        }
 
        if (Input.GetKey(KeyCode.D) || Input.GetAxisRaw("Horizontal") > 0.1f)
        {
            m_CurrentTurnSpeed = RotateSpeed;
            transform.Rotate(0.0f,RotateSpeed * Time.deltaTime,0.0f);
        }
    }
 
    void UpdateJump()
    {
      groundedplayer = m_CharacterController.isGrounded;
        if (groundedplayer && playerVeLocity.y < 0)
        {
            playerVeLocity.y = 0f;
        }
 
        if (Input.GetButtonDown("Jump") && groundedplayer)
        {
            playerVeLocity.y += Mathf.Sqrt(jumpHeight * -3.0f * gravityValue);
            m_Animator.SetTrigger("Jump");
            print("Jumping Now");
        }
 
        playerVeLocity.y += gravityValue * Time.deltaTime;
        m_CharacterController.Move(playerVeLocity * Time.deltaTime);
    }
}

解决方法

最好的猜测是,“ m_PhotonView.isMine”在缺少输入的帧上没有返回true。它仅检查该帧的跳转输入,因此,如果您未按下最后一帧但未检查跳转的帧,则该输入将永远丢失。首先测试一下。将更新代码更改为此:

void Update()
{
    if (Input.GetButtonDown("Jump")) { Debug.Log("Jump was pressed at {Time.time}"); }
    if (m_PhotonView.isMine == true)
    {
        if (Input.GetButtonDown("Jump")) { Debug.Log("Attempting Jump at {Time.time}"); }
        ResetSpeedValues();
        UpdateRotateMovement();
        UpdateForwardMovement();
        UpdateBackwardMovement();
        UpdateStrafeMovement();          
        MoveCharacterController();
        UpdateJump();
        ApplySynchronizedValues();
    }
    UpdateAnimation();
}

然后玩游戏并跳一堆。无论什么时候,每次单击空格键都应发生第一条调试日志行。仅当在该帧上计算出物理量时,才会发生第二条调试行。两者都有时间。继续跳跃直到跳跃不起作用。如果该跳转仅产生第一个调试日志,而不是第二个,那么我是正确的,那是您的问题。

如果是这样,那么这很容易解决。添加一个名为“ jumpInput”的新布尔变量。每当您检查是否按下了跳转时,而是检查“ jumpInput”是否为true。然后,将更新更改为此:

void Update()
{
    if (Input.GetButtonDown("Jump")) { jumpInput = true; }
    if (m_PhotonView.isMine == true)
    {
        ResetSpeedValues();
        UpdateRotateMovement();
        UpdateForwardMovement();
        UpdateBackwardMovement();
        UpdateStrafeMovement();          
        MoveCharacterController();
        UpdateJump();
        ApplySynchronizedValues();
        jumpInput = false;
    }
    UpdateAnimation();
}

通过这种方式,如果您按下跳转,则将其设置为true ...,但是仅在完成物理操作后才将其设置为false。因此,如果您在第20帧上按下跳转,并且直到第25帧才以某种方式计算物理量,它仍然会知道您在某个点上按下了跳转并执行了它。如果使用网络,则可能还需要另一个变量,即按下了帧跳转。这样一来,您就可以算出自输入以来已经过了几帧,并在必要时补偿跳跃中错过的时间。