我目前正在为我的第一人称控制器开发冲刺功能。
我的设置是一个“PlayerMovementController”、一个“PlayerStatusController”和一个可编写脚本的对象“PlayerStatusData”,StatusController 正在获取有关玩家耐力的信息。
玩家移动控制器:
private void Update()
{
HandleMovementInput();
ApplyMovement();
}
private void HandleMovementInput()
{
if (Input.GetKey(sprintKey) && !isSprinting) // SPRINTING
{
if (OnCheckStamina != null && OnCheckStamina())
{
StartSprint();
OnStaminaDrain?.Invoke();
}
}
else // NOT SPRINTING
{
StopSprint();
OnStaminaRegen?.Invoke();
}
/*** SPRINTING ENDE ***/
currentInput = new Vector2(movementSpeed * Input.GetAxis("Vertical"), movementSpeed * Input.GetAxis("Horizontal"));
float moveDirectionY = moveDirection.y;
moveDirection = (transform.TransformDirection(Vector3.forward) * currentInput.x) + (transform.TransformDirection(Vector3.right) * currentInput.y);
moveDirection.y = moveDirectionY;
}
private void ApplyMovement()
{
if (!characterController.isGrounded)
moveDirection.y -= gravity * Time.deltaTime;
characterController.Move(moveDirection * Time.deltaTime);
}
private void StartSprint()
{
isSprinting = true;
movementSpeed = sprintSpeed;
}
private void StopSprint()
{
isSprinting = false;
movementSpeed = walkSpeed;
}
Sprint 本身像这样工作得很好,但我在检查器上注意到 isSprinting 布尔值和运动速度在 true 和 false 以及 3f 到 1.8f 之间不断变化。 我不敢相信这是正常的,必须有一个适当的开关......对吧? 在游戏视图本身中,这似乎不是问题,但处理这些事件的耐力系统并没有真正发挥作用。他们不断地在“恢复体力”和“消耗体力”之间切换
玩家状态控制器:
public class PlayerStatusController : MonoBehaviour
{
[Header("Scriptable Object")]
public PlayerStatusData playerStatusData, pSD;
private void OnEnable()
{
PlayerMovementController.OnCheckStamina += HasStamina;
PlayerMovementController.OnStaminaDrain += DrainStamina;
PlayerMovementController.OnStaminaRegen += RegenerateStamina;
}
private void OnDisable()
{
PlayerMovementController.OnCheckStamina -= HasStamina;
PlayerMovementController.OnStaminaDrain -= DrainStamina;
PlayerMovementController.OnStaminaRegen -= RegenerateStamina;
}
private bool HasStamina()
{
return playerStatusData.currentStamina > 0;
}
private void DrainStamina()
{
if (playerStatusData.currentStamina != playerStatusData.minStamina)
{
playerStatusData.currentStamina -= playerStatusData.staminaDrain * Time.deltaTime;
playerStatusData.currentStamina = Mathf.Max(0, playerStatusData.currentStamina); // Ensure stamina doesn't go below 0
Debug.Log("DRAINING STAMINA");
}
}
private void RegenerateStamina()
{
if (playerStatusData.currentStamina < playerStatusData.maxStamina)
{
playerStatusData.currentStamina += playerStatusData.staminaRegen * Time.deltaTime;
playerStatusData.currentStamina = Mathf.Min(100, playerStatusData.currentStamina); // Ensure stamina doesn't go above 100
Debug.Log("REGENERATING STAMINA");
}
}
}
在我看来,事件系统应该工作得很好......但我认为冲刺脚本的开/关切换存在问题,这会导致耐力系统出现问题。有人能解决这个问题吗?
这是因为你的if语句逻辑:
if (Input.GetKey(sprintKey) && !isSprinting)
。一旦冲刺开始,!isSprinting
变为假,这意味着即使仍然按住该键,StopSprinting()将始终在下一帧被调用。
示例帧序列:
(Input.GetKey = false & !isSprinting = false) == false
,调用 StopSprint() (Input.GetKey = true & !isSprinting = false) == true
,调用 StartSprint() Input.GetKey = true & !isSprinting = true, == false
,调用 StopSprint()(即使仍按住)(Input.GetKey = true & !isSprinting = false) == true
,StartSprint() 再次被调用将
!isSprinting
检查更改为第一个 if 语句的 inside 以解决此问题
if (Input.GetKey(sprintKey)) // SPRINTING
{
if (!isSprinting && OnCheckStamina != null && OnCheckStamina())
{
StartSprint();
OnStaminaDrain?.Invoke();
}
}
else // NOT SPRINTING
{
StopSprint();
OnStaminaRegen?.Invoke();
}