版本:Unity 6 (6000.0)
语言:English
轮碰撞器悬架
轮碰撞器组件参考

使用轮碰撞器创建汽车

本教程将引导您完成使用 PhysX 轮碰撞器一种用于地面车辆的特殊碰撞器。它具有内置的碰撞检测、车轮物理和基于滑移的轮胎摩擦模型。它可以用于轮子以外的物体,但它是专门为带轮子的车辆设计的。 更多信息
参见 词汇表
创建一个基本的功能齐全的四轮汽车的过程。

步骤包括

  1. 准备项目
  2. 准备汽车模型
  3. 添加轮碰撞器,并设置它们的位置和半径
  4. 添加脚本以控制汽车行为,包括汽车移动和车轮旋转
  5. 测试汽车

准备项目

要遵循这些说明,您需要

  • 一个新的空场景
  • 演示汽车模型(下载:car.fbx),导入到打开的项目中
  • 汽车行驶的地面。

要创建地面

  1. 创建一个平面游戏对象Unity 场景中的基本对象,可以表示角色、道具、场景、摄像机、路径点等等。游戏对象的功能由附加在其上的组件定义。 更多信息
    参见 词汇表
    并将其重命名为 Ground。此平面是汽车行驶的地面。
  2. 将其位置设置为 (0,0,0),比例设置为 (100,1,100)。

准备汽车模型

首先,将汽车模型放置在场景场景包含游戏环境和菜单。可以将每个唯一的场景文件视为一个唯一的关卡。在每个场景中,放置环境、障碍物和装饰物,从本质上讲,将游戏分段设计和构建。 更多信息
参见 词汇表

  1. 项目窗口一个窗口,显示您的 Assets 文件夹(项目选项卡)的内容 更多信息
    参见 词汇表
    中,选择导入的 Car 资源。
  2. 提取汽车模型的纹理,以便 Unity 可以在场景中显示它们。为此,请导航到检查器一个 Unity 窗口,显示当前选定游戏对象、资源或项目设置的信息,允许检查和编辑值。 更多信息
    参见 词汇表
    窗口中的导入设置,并执行以下操作
    1. 选择材质
    2. 选择纹理 > 提取纹理。在打开的文件浏览器中,将它们保存在 Assets 文件夹(默认位置)中。
    3. 选择应用
  3. 将汽车资源放置到场景中,在地面平面上或其正上方。

查看层次结构窗口中汽车游戏对象的层次结构。有一个名为 Car 的根游戏对象,以及汽车车身模型和每个车轮模型的子游戏对象。

配置汽车车身以进行碰撞当物理引擎检测到两个游戏对象的碰撞器发生接触或重叠时,就会发生碰撞,前提是至少有一个具有刚体组件并且处于运动状态。 更多信息
参见 词汇表

  1. Car 根游戏对象上,添加一个刚体一个组件,允许游戏对象受到模拟重力和其它力的影响。 更多信息
    参见 词汇表
    组件。
  2. 将刚体的质量设置为 1500。此值定义汽车的重量(以千克为单位)。对于轮碰撞器的默认悬架设置,这是一个合适的重量。有关更多信息,请参见轮碰撞器悬架:质量和悬架值
  3. Car Body 游戏对象上,添加一个网格碰撞器一个自由形式的碰撞器组件,它接受网格引用来定义其碰撞表面形状。 更多信息
    参见 词汇表
    组件。
  4. 在新网格Unity 的主要图形基元。网格构成了 3D 世界的大部分。Unity 支持三角形或四边形多边形网格。Nurbs、Nurms、细分曲面必须转换为多边形。 更多信息
    参见 词汇表
    碰撞器一种用于处理对象物理碰撞的不可见形状。碰撞器不需要与对象的网格完全相同形状 - 粗略的近似值通常更有效,并且在游戏玩法中无法区分。 更多信息
    参见 词汇表
    组件上,启用凸面

添加轮碰撞器

要向车轮模型添加轮碰撞器,需要在与车轮模型相同的位置创建四个新的独立游戏对象(但不是作为车轮的子游戏对象)。

一种快速设置此操作以使其大致位于相同位置的方法是复制车轮游戏对象,然后配置新游戏对象

  1. 选择所有四个车轮游戏对象。
  2. 复制游戏对象(Ctrl/Cmd+D)。
  3. 选择所有四个副本,然后执行以下操作
    1. 删除网格渲染器一个网格组件,它获取来自网格过滤器的几何体,并根据对象的变换组件定义的位置对其进行渲染。 更多信息
      参见 词汇表
      网格过滤器一个网格组件,它获取来自资源的网格,并将其传递给网格渲染器以在屏幕上进行渲染。 更多信息
      参见 词汇表
      组件
    2. 添加一个轮碰撞器组件
  4. 重命名新的轮碰撞器游戏对象。默认情况下,Unity 会为重复的游戏对象提供相同的名称,并在括号中添加一个数字;例如,Wheel Back Left (1)。为清楚起见,改为在游戏对象名称中添加“Collider”一词;例如,Wheel Back Left collider

汽车游戏对象的层次结构现在应如下所示

The root Car GameObject and all child GameObjects, including the Car Body, four wheel model GameObjects, and four Wheel collider GameObjects.
根汽车游戏对象和所有子游戏对象,包括汽车车身、四个车轮模型游戏对象和四个轮碰撞器游戏对象。

接下来,需要调整轮碰撞器的位置和大小以匹配车轮模型。

选择轮碰撞器时,场景视图对正在创建的世界进行交互式查看。使用场景视图选择和放置场景、角色、摄像机、灯光和所有其他类型的游戏对象。 更多信息
参见 词汇表
将显示一个Gizmo与场景中游戏对象关联的图形叠加层,并在场景视图中显示。内置场景工具(如移动工具)是 Gizmo,并且可以使用纹理或脚本创建自定义 Gizmo。某些 Gizmo 仅在选择游戏对象时绘制,而其他 Gizmo 无论选择哪些游戏对象,都会由编辑器绘制。 更多信息
参见 词汇表
,它提供了轮碰撞器设置的可视化效果(请参阅轮碰撞器可视化)。可以使用 Gizmo 检查轮碰撞器的位置和大小与车轮模型的位置和大小是否匹配。

要更清楚地查看车轮方向和 Gizmo,请将场景的绘制模式设置为线框,并将场景方向设置为等轴测

设置轮碰撞器位置

当使用添加轮碰撞器中描述的工作流首次添加轮碰撞器时,它们太低了(在场景视图中,轮碰撞器圆圈出现在车轮模型网格下方)。这是因为悬架距离从这些游戏对象的位置开始,并向下延伸由悬架距离设置中指定的值指定的距离。场景视图可视化效果将悬架距离显示为沿轮碰撞器 Gizmo 的 Y 轴向下延伸的橙色线条。

绿色圆圈轮廓显示车轮位于悬架距离范围的中点,应将其视为车轮的正常位置,此时汽车没有被压低或抬起。因此,每个轮碰撞器的绿色轮廓需要以其对应的车轮网格为中心。

The Wheel collider gizmo indicates the position of the Wheel collider in relation to the wheel model. In this image, the Wheel collider is too large and too low.
轮碰撞器 Gizmo 指示轮碰撞器相对于车轮模型的位置。在此图像中,轮碰撞器太大且太低。

要更正此问题,需要将 WheelCollider 游戏对象向上(在 Y 轴上)移动轮碰撞器悬架距离值的一半。在此示例项目中,悬架距离为 0.3(默认值),因此需要将 WheelCollider 游戏对象向上移动 0.15 个单位。

Unity 允许您在数字字段中输入简单的数学计算。您可以使用它来添加到 Y 轴值。

  1. 选择所有四个轮碰撞器游戏对象。
  2. 在检查器中,导航到变换的位置属性。
  3. Y轴值中,将光标置于值的末尾。在值的末尾添加 +0.15(例如,如果值为 0.5,则该值现在应显示为 0.5+0.15)。
  4. 按回车键。

Unity 将 +0.15 应用于先前的值,这会将 WheelCollider 游戏对象在 Y 轴上向上移动 0.15 个单位。

轮碰撞器 Gizmo 现在应完美地以车轮网格为中心

The Wheel collider gizmo indicates the position of the Wheel collider in relation to the wheel model. In this image, the Wheel collider is centered correctly in the wheel model.
轮碰撞器 Gizmo 指示轮碰撞器相对于车轮模型的位置。在此图像中,轮碰撞器已正确以车轮模型为中心。

设置轮碰撞器半径

当使用添加轮碰撞器中描述的工作流首次添加轮碰撞器时,它们太大(在场景视图中,轮碰撞器 Gizmo 大于车轮模型网格)。

要准确更正此问题,需要知道车轮模型的确切半径。此信息应可从您的 3D 建模软件或创建模型的技术美术师那里获得。

在此示例项目中,车轮模型的半径为 0.44。

  1. 选择所有四个轮碰撞器游戏对象
  2. 在检查器中,导航到轮碰撞器组件的半径属性
  3. 半径设置为 0.44

如果车轮模型的精确半径未知或不可用,您可以使用轮碰撞体 Gizmo 将其半径近似匹配到模型。或者,您可以使用一个球形碰撞体一种球形碰撞体组件,用于处理游戏对象的碰撞,例如球体或其他可以粗略地近似为球体以用于物理目的的事物。 更多信息
参见 术语表
来获取半径,因为球形碰撞体自动调整大小以包含其关联模型的网格。

如何使用球形碰撞体获取半径

  1. 选择任意车轮模型游戏对象。
  2. 添加一个球形碰撞体。
  3. 记下球形碰撞体的**半径**属性值。
  4. 移除球形碰撞体。
  5. 选择所有四个轮碰撞器游戏对象。
  6. 在检查器中,导航到轮碰撞体组件的**半径**属性。
  7. 将轮碰撞体的**半径**设置为您记下的球形碰撞体的**半径**值。

轮碰撞体现在应该与车轮模型的位置和大小完全匹配。

Two Wheel collider gizmos indicate the position of the Wheel colliders in relation to the wheel models. In this image, the Wheel colliders are centered correctly in the wheel model, and their radius correctly matches the radius of the wheel model.
两个轮碰撞体 Gizmo 指示轮碰撞体相对于车轮模型的位置。在此图像中,轮碰撞体在车轮模型中正确居中,并且它们的半径与车轮模型的半径正确匹配。

添加脚本以控制汽车行为

要控制汽车,您需要向项目中添加脚本一段代码,允许您创建自己的组件、触发游戏事件、随时间修改组件属性并以任何您喜欢的方式响应用户输入。 更多信息
参见 术语表
来执行以下操作

  • 控制汽车移动:根据用户输入向轮碰撞体发送转向、扭矩和制动值。
  • 控制车轮移动:根据每个轮碰撞体状态移动和旋转车轮网格。

在此示例中,我们使用两个脚本执行此操作:CarControl.csWheelControl.cs

添加汽车移动控制

创建一个名为 CarControl.cs 的 C# 文件,并将下面的代码粘贴到其中

using UnityEngine;

public class CarControl : MonoBehaviour
{
    public float motorTorque = 2000;
    public float brakeTorque = 2000;
    public float maxSpeed = 20;
    public float steeringRange = 30;
    public float steeringRangeAtMaxSpeed = 10;
    public float centreOfGravityOffset = -1f;

    WheelControl[] wheels;
    Rigidbody rigidBody;

    // Start is called before the first frame update
    void Start()
    {
        rigidBody = GetComponent<Rigidbody>();

        // Adjust center of mass vertically, to help prevent the car from rolling
        rigidBody.centerOfMass += Vector3.up * centreOfGravityOffset;

        // Find all child GameObjects that have the WheelControl script attached
        wheels = GetComponentsInChildren<WheelControl>();
    }

    // Update is called once per frame
    void Update()
    {

        float vInput = Input.GetAxis("Vertical");
        float hInput = Input.GetAxis("Horizontal");

        // Calculate current speed in relation to the forward direction of the car
        // (this returns a negative number when traveling backwards)
        float forwardSpeed = Vector3.Dot(transform.forward, rigidBody.velocity);


        // Calculate how close the car is to top speed
        // as a number from zero to one
        float speedFactor = Mathf.InverseLerp(0, maxSpeed, forwardSpeed);

        // Use that to calculate how much torque is available 
        // (zero torque at top speed)
        float currentMotorTorque = Mathf.Lerp(motorTorque, 0, speedFactor);

        // …and to calculate how much to steer 
        // (the car steers more gently at top speed)
        float currentSteerRange = Mathf.Lerp(steeringRange, steeringRangeAtMaxSpeed, speedFactor);

        // Check whether the user input is in the same direction 
        // as the car's velocity
        bool isAccelerating = Mathf.Sign(vInput) == Mathf.Sign(forwardSpeed);

        foreach (var wheel in wheels)
        {
            // Apply steering to Wheel colliders that have "Steerable" enabled
            if (wheel.steerable)
            {
                wheel.WheelCollider.steerAngle = hInput * currentSteerRange;
            }
            
            if (isAccelerating)
            {
                // Apply torque to Wheel colliders that have "Motorized" enabled
                if (wheel.motorized)
                {
                    wheel.WheelCollider.motorTorque = vInput * currentMotorTorque;
                }
                wheel.WheelCollider.brakeTorque = 0;
            }
            else
            {
                // If the user is trying to go in the opposite direction
                // apply brakes to all wheels
                wheel.WheelCollider.brakeTorque = Mathf.Abs(vInput) * brakeTorque;
                wheel.WheelCollider.motorTorque = 0;
            }
        }
    }
}

将此 CarControl.cs 脚本添加到 Car 根游戏对象。

CarControl.cs 脚本根据用户输入处理汽车行为,例如加速、扭矩和制动。有关详细信息,请参阅代码注释。

CarControl.cs 脚本的某些元素引用了下一节中创建的 WheelControl.cs 脚本。

添加车轮移动控制

创建一个名为 WheelControl.cs 的 C# 文件,并将下面的代码粘贴到其中

using UnityEngine;

public class WheelControl : MonoBehaviour
{
    public Transform wheelModel;

    [HideInInspector] public WheelCollider WheelCollider;

    // Create properties for the CarControl script
    // (You should enable/disable these via the 
    // Editor Inspector window)
    public bool steerable;
    public bool motorized;

    Vector3 position;
    Quaternion rotation;

    // Start is called before the first frame update
    private void Start()
    {
        WheelCollider = GetComponent<WheelCollider>();
    }

    // Update is called once per frame
    void Update()
    {
        // Get the Wheel collider's world pose values and
        // use them to set the wheel model's position and rotation
        WheelCollider.GetWorldPose(out position, out rotation);
        wheelModel.transform.position = position;
        wheelModel.transform.rotation = rotation;
    }
}

将此脚本添加到每个轮碰撞体游戏对象。

WheelControl.cs 脚本使用 WheelCollider.GetWorldPose 获取轮碰撞体在场景中的位置。然后,脚本将该位置信息分配给指定的轮模型游戏对象。有关详细信息,请参阅代码注释。

WheelControl.cs 脚本的每个实例都必须引用其对应的轮模型游戏对象。

为每个轮碰撞体分配正确的轮模型游戏对象

  1. 选择一个轮碰撞体游戏对象
  2. 在检查器窗口中,导航到脚本创建的**轮控制**组件
  3. 将**轮模型**设置为对应的轮模型游戏对象(例如,在“Wheel Rear Left collider”游戏对象上,分配“Wheel Rear Left”轮模型游戏对象)
  4. 对每个轮碰撞体重复此操作。

您还需要选择哪些车轮接收来自 CarControl 脚本的电机输入和转向输入。要通过轮控制属性模拟四轮驱动汽车

  1. 在所有四个轮碰撞体游戏对象上,启用**电机驱动**。
  2. 在两个前轮碰撞体游戏对象上,启用**可转向**。

测试汽车

要测试汽车,请进入播放模式并使用箭头键或 WASD 键移动和转向。请注意,输入控件仅在游戏视图具有焦点时有效。

要更好地查看汽车在场景中移动

  1. 排列编辑器窗口,以便同时显示场景视图和游戏视图。
  2. 将场景视图的焦点锁定到汽车。为此,在场景视图中选择Car根游戏对象,然后按 Shift + F。

现在您已经有了基本的设置,您可以尝试更改不同的设置以观察它们如何影响汽车的移动。您也可以使用不同的汽车模型遵循这些说明,并观察其设置的异同。

轮碰撞器悬架
轮碰撞器组件参考