Unity挂载玩家控制脚本后物体下落减速百倍,重力异常求助
卡丁车游戏下落速度异常缓慢问题排查
我正在使用Unity开发一款卡丁车竞速游戏,编写了玩家控制脚本。但将该脚本挂载到游戏对象后,对象的下落速度比正常情况慢了约100倍,始终无法找到原因。脚本代码如下,我并未在脚本中找到任何会影响物体重力作用的逻辑:
using UnityEngine; using System.Collections; public class PlayerController : MonoBehaviour { public float moveSpeed = 10f; // Movement speed of the player public float rotationSpeed = 100f; // Rotation speed of the player public float maxSpeed = 20f; // Maximum speed the player can move public float acceleration = 5f; // Acceleration of the player public float braking = 10f; // Braking force applied to slow down the player public float reverseSpeed = 5f; // Speed of reverse movement private Rigidbody rb; // Reference to the player's Rigidbody component private float currentSpeed = 0f; // Current speed of the player private float moveInput; private float rotationInput; // New variables for drifting public float driftTraction = 0.5f; public float driftForce = 10f; private bool isDrifting = false; private bool isTurningLeft = false; private bool isTurningRight = false; private bool leftTrueRightFalse; private float lockedRotationInput; void Start() { rb = GetComponent<Rigidbody>(); } void Update() { // Get input for movement and rotation moveInput = Input.GetAxis("Vertical"); rotationInput = Input.GetAxis("Horizontal"); isTurningLeft = rotationInput < 0f; isTurningRight = rotationInput > 0f; if (Input.GetKeyDown(KeyCode.LeftShift)) { StartDrift(); } else if (Input.GetKeyUp(KeyCode.LeftShift)) { EndDrift(); } } void FixedUpdate() { // Calculate movement float moveAmount = 0f; // Accelerate if moving forward, reverse if moving backward, or brake if not moving if (moveInput > 0 && currentSpeed >= 0) { moveAmount = acceleration * Time.deltaTime; } else if (moveInput > 0 && currentSpeed <= 0) { moveAmount = braking * Time.deltaTime; } else if (moveInput < 0 && currentSpeed >= 0) { moveAmount = -braking * Time.deltaTime; } else if (moveInput < 0 && currentSpeed < 0) { moveAmount = -acceleration * Time.deltaTime; } else if (moveInput < 0 && currentSpeed == 0) { moveAmount = -reverseSpeed * Time.deltaTime; } else if (currentSpeed < 0.01 && currentSpeed > -0.01){ moveAmount = 0; } else if (currentSpeed > 0) { moveAmount = 0.5f * -braking * Time.deltaTime; } else if (currentSpeed < 0) { moveAmount = 0.5f * braking * Time.deltaTime; } if (isDrifting){ if ((isTurningLeft && !leftTrueRightFalse) || (isTurningRight && leftTrueRightFalse)){ // Apply rotation only if drift direction matches float targetRotation = rotationInput * rotationSpeed * 0.8f * Time.deltaTime; Quaternion targetRotationQuaternion = Quaternion.Euler(0f, targetRotation, 0f); transform.rotation = Quaternion.Lerp(transform.rotation, transform.rotation * targetRotationQuaternion, Time.deltaTime * rotationSpeed); } else { // Slight rotation float targetRotation = rotationInput * rotationSpeed * 0.4f * Time.deltaTime; Quaternion targetRotationQuaternion = Quaternion.Euler(0f, targetRotation, 0f); transform.rotation = Quaternion.Lerp(transform.rotation, transform.rotation * targetRotationQuaternion, Time.deltaTime * rotationSpeed); } } else { // Apply rotation float targetRotation = rotationInput * rotationSpeed * Time.deltaTime; Quaternion targetRotationQuaternion = Quaternion.Euler(0f, targetRotation, 0f); transform.rotation = Quaternion.Lerp(transform.rotation, transform.rotation * targetRotationQuaternion, Time.deltaTime * rotationSpeed); } // Apply acceleration or braking to change speed currentSpeed += moveAmount; currentSpeed = Mathf.Clamp(currentSpeed, -reverseSpeed, maxSpeed); // Apply forward or reverse movement based on speed rb.velocity = transform.forward * currentSpeed; // Apply drifting physics if drifting if (isDrifting) { ApplyDriftPhysics(); } } private void StartDrift() { if (!isDrifting){ if (isTurningLeft){ leftTrueRightFalse = false; isDrifting = true; // Add visual and audio feedback for starting a drift lockedRotationInput = rotationInput; } else if (isTurningRight){ leftTrueRightFalse = true; isDrifting = true; // Add visual and audio feedback for starting a drift lockedRotationInput = rotationInput; } else { // Nothing } } } private void EndDrift() { isDrifting = false; // Reset kart physics to normal rb.drag = 0f; } private void ApplyDriftPhysics() { // Reduce traction to simulate drifting rb.drag = driftTraction; // Apply sideways force to induce drift if (!leftTrueRightFalse){ Vector3 driftForceDirection = transform.right; rb.AddForce(driftForceDirection * driftForce, ForceMode.Acceleration); } else { Vector3 driftForceDirection = -transform.right; rb.AddForce(driftForceDirection * driftForce, ForceMode.Acceleration); } // Apply rotation float targetRotation = lockedRotationInput * rotationSpeed * 0.6f * Time.deltaTime; Quaternion targetRotationQuaternion = Quaternion.Euler(0f, targetRotation, 0f); transform.rotation = Quaternion.Lerp(transform.rotation, transform.rotation * targetRotationQuaternion, Time.deltaTime * rotationSpeed); } public void ResetSpeedAndAcceleration() { currentSpeed = 0f; // Reset current speed to 0 moveInput = 0f; // Reset move input rotationInput = 0f; // Reset rotation input } public int getCurrentSpeed(){ if (currentSpeed >= 0) { return 1; } else { return 0; } } }
问题原因
核心问题在FixedUpdate中的这行代码:
rb.velocity = transform.forward * currentSpeed;
这行代码直接完全覆盖了Rigidbody的velocity属性,包括竖直方向(Y轴)的速度。Unity的重力是通过持续给Rigidbody的Y轴velocity施加向下的力来实现的,但你每次FixedUpdate都将velocity重置为仅包含水平向前的分量,等于把重力带来的下落速度强制清零了,导致物体下落速度几乎停滞,看起来比正常慢100倍。
修复方案
只修改velocity的水平分量(X、Z轴),保留竖直方向的速度以维持重力效果:
// 替换原有的rb.velocity = transform.forward * currentSpeed; 这一行 Vector3 newVelocity = transform.forward * currentSpeed; newVelocity.y = rb.velocity.y; // 保留重力带来的竖直方向速度 rb.velocity = newVelocity;
额外检查点:
- 确认游戏对象的Rigidbody组件Use Gravity选项处于勾选状态
- 检查Rigidbody的Mass值是否合理(不要设置过小,比如0.01会导致重力影响不明显)
- 确保Drag和Angular Drag没有设置过大,否则会抵消部分重力效果
内容的提问来源于stack exchange,提问作者CottonReyler
相关产品推荐
相关产品推荐

