Unity FPS控制器重力失效求助:ApplyGravity函数不生效
FPS控制器重力失效问题排查与修复
我正在制作一款FPS控制器,无法为角色施加重力。已编写ApplyGravity()函数,调试发现角色的y方向数值在减小,但角色本身并未移动。移动和相机旋转功能均正常,需要解决重力失效问题。
问题代码
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class FirstPersonController : MonoBehaviour { [Header("Dependencies")] [SerializeField] private GameInput gameInput; [Header("Movement Parameters")] [SerializeField] private float moveSpeed; [SerializeField] private float sprintSpeed; [Header("Look Parameters")] [SerializeField] private Transform cameraFollowTransform; [SerializeField] private float lookSensitivity; [SerializeField] private float topClamp = 90.0f; [SerializeField] private float bottomClamp = -90.0f; [Header("Jumping Parameters")] [SerializeField] private float jumpForce; [Header("Gravity Parameters")] [SerializeField] private float gravityMultiplier = 3f; // player private CharacterController characterController; private float rotationVelocity; private bool isSprinting; // input private Vector2 inputVector; private Vector3 moveDirection; // gravity private float gravityForce = -9.81f; private float velocity; // cinemachine private float cinemachineTargetPitch; private void Awake() { characterController = GetComponent<CharacterController>(); Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; } private void Update() { ApplyGravity(); HandleMovement(); } private void LateUpdate() { HandleCameraRotation(); } private void HandleMovement() { inputVector = gameInput.GetMovementVectorNormalized(); moveDirection = new Vector3(inputVector.x, 0f, inputVector.y); moveDirection = transform.right * inputVector.x + transform.forward * inputVector.y; float targetSpeed = CheckSprint() ? sprintSpeed : moveSpeed; float moveDistance = targetSpeed * Time.deltaTime; characterController.Move(moveDirection * moveDistance); } private void HandleCameraRotation() { Vector2 inputVector = gameInput.GetLookVector(); cinemachineTargetPitch += inputVector.y * lookSensitivity * Time.deltaTime; rotationVelocity = inputVector.x * lookSensitivity * Time.deltaTime; cinemachineTargetPitch = ClampAngle(cinemachineTargetPitch, bottomClamp, topClamp); cameraFollowTransform.transform.localRotation = Quaternion.Euler(cinemachineTargetPitch, 0f, 0f); transform.Rotate(Vector3.up * rotationVelocity); } private void ApplyGravity() { velocity += gravityForce * gravityMultiplier * Time.deltaTime; moveDirection.y = velocity; Debug.Log(moveDirection); } private bool CheckSprint() { if (gameInput.GetPLayerInputActions().Player.Sprint.inProgress) { isSprinting = true; } else { isSprinting = false; } return isSprinting; } private static float ClampAngle(float lfAngle, float lfMin, float lfMax) { if (lfAngle < -360f) lfAngle += 360f; if (lfAngle > 360f) lfAngle -= 360f; return Mathf.Clamp(lfAngle, lfMin, lfMax); } }
问题原因
HandleMovement()重置了y轴分量:每次调用该方法时,都会执行moveDirection = new Vector3(inputVector.x, 0f, inputVector.y),将y轴设为0,覆盖了ApplyGravity()中设置的y轴重力值。- 未将重力分量传入
CharacterController.Move():当前代码仅将水平方向的移动量传给了Move()方法,没有包含重力的y轴位移。
修复方案
1. 修改HandleMovement(),保留重力y轴分量
将重置moveDirection的代码改为仅更新水平方向,保留y轴的重力值:
private void HandleMovement() { inputVector = gameInput.GetMovementVectorNormalized(); // 只更新水平方向,保留y轴的重力值 moveDirection.x = inputVector.x; moveDirection.z = inputVector.y; moveDirection = transform.right * inputVector.x + transform.forward * inputVector.y; float targetSpeed = CheckSprint() ? sprintSpeed : moveSpeed; // 分离水平移动和重力移动 Vector3 horizontalMove = moveDirection.normalized * targetSpeed * Time.deltaTime; Vector3 gravityMove = new Vector3(0f, velocity, 0f) * Time.deltaTime; // 合并后应用移动 characterController.Move(horizontalMove + gravityMove); }
2. 完善ApplyGravity(),添加地面检测
当角色接触地面时重置重力速度,避免无限累加导致速度过大,同时防止角色悬空:
private void ApplyGravity() { // 角色在地面时,重置速度为小负数,确保贴合地面 if (characterController.isGrounded && velocity < 0) { velocity = -1f; } else { velocity += gravityForce * gravityMultiplier * Time.deltaTime; } // 无需再给moveDirection.y赋值,直接在Move中使用velocity }
修复后补充说明
- 地面检测使用
CharacterController.isGrounded,确保角色站在地面时不会持续受到重力加速度影响。 - 分离水平移动和重力移动,避免移动速度影响重力的加速度效果。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

