You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 18:54:53