问题描述
我是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帧才以某种方式计算物理量,它仍然会知道您在某个点上按下了跳转并执行了它。如果使用网络,则可能还需要另一个变量,即按下了帧跳转。这样一来,您就可以算出自输入以来已经过了几帧,并在必要时补偿跳跃中错过的时间。