包含此页的版本:
不含此页的版本:
本教程将引导您完成使用 PhysX 创建基本功能四轮汽车的过程车轮对撞机 用于停飞车辆的专用对撞机。它具有内置的碰撞检测、车轮物理和基于打滑的轮胎摩擦模型。它可用于车轮以外的物体,但它是专门为带轮子的车辆设计的。更多信息
请参阅术语表.
这些步骤包括:
要遵循这些说明,您需要:
要创建地面曲面:
Ground. 这个平面是汽车行驶的地面。首先,将汽车模型放在场景场景包含游戏的环境和菜单。将每个唯一的场景文件视为一个独特的关卡。在每个场景中,你放置你的环境、障碍物和装饰品,基本上是将你的游戏设计和构建成碎片。更多信息
请参阅术语表:
Assets文件夹(项目选项卡)更多信息Car资产。Assets文件夹(默认位置)。在“层次结构”窗口中查看汽车游戏对象的层次结构。有一个名为Car,以及车身模型和每个车轮模型的子游戏对象。
配置车身碰撞当物理引擎检测到两个游戏对象的碰撞器接触或重叠时,当至少一个游戏对象具有刚体组件并且处于运动状态时,就会发生碰撞。更多信息
请参阅术语表:
Carroot GameObject,添加一个刚体允许游戏对象受到模拟重力和其他力影响的组件。更多信息Car BodyGameObject,添加一个网格碰撞体自由形式的碰撞器组件,它接受网格参考来定义其碰撞表面形状。更多信息若要将 Wheel 碰撞器添加到 Wheel 模型,需要在与 Wheel 模型相同的位置创建四个新的单独游戏对象(但不能作为 Wheel 的子游戏对象)。
在大致相同的位置设置此设置的一种快速方法是复制滚轮游戏对象,然后配置新的游戏对象:
Wheel Back Left (1).为清楚起见,请改为将单词“Collider”添加到游戏对象名称中;例如Wheel Back Left collider.汽车游戏对象层次结构现在应如下所示:
接下来,您需要调整车轮碰撞器的位置和大小以匹配车轮模型。
选择 Wheel 碰撞器时,将场景视图:您正在创建的世界的交互式视图。您可以使用场景视图来选择和定位场景、角色、摄像机、灯光和所有其他类型的游戏对象。更多信息
请参阅术语表显示一个小工具与场景中的游戏对象关联的图形叠加层,并显示在场景视图中。移动工具等内置场景工具是 Gizmo,您可以使用纹理或脚本创建自定义 Gizmo。某些 Gizmo 仅在选择游戏对象时绘制,而其他 Gizmo 则由编辑器绘制,而不管选择了哪个游戏对象。更多信息
请参阅术语表它提供了 Wheel 碰撞器设置的可视化效果(请参阅 Wheel 碰撞体可视化)。你可以使用小工具根据车轮模型的位置和大小检查车轮碰撞体的位置和大小。
要更清楚地看到滚轮方向和小工具,请将场景的 绘制(Draw) 模式设置为 线框(Wireframe) ,并将 场景方向(Scene orientation) 设置为 等距(Isometric)。
首次使用添加车轮碰撞器中所述的工作流程添加车轮碰撞器时,它们太低(在场景视图中,车轮碰撞体圆圈显示在车轮模型网格下方)。这是因为“挂起距离”从这些游戏对象的位置开始,向下延伸“挂起距离”设置中指定的距离。场景视图可视化将 悬挂距离(Suspension Distance) 显示为沿车轮碰撞器小工具的 Y 轴向下的橙色线。
绿色圆圈轮廓显示车轮位于悬架距离范围的中间点,当汽车在其悬架上没有被压扁或抬起时,应将其视为车轮的正常位置。因此,每个车轮碰撞器的绿色轮廓需要在其相应的车轮网格体上居中。
若要更正此问题,需要将 WheelCollider 游戏对象向上移动(在 Y 轴上)Wheel 碰撞器的“悬挂距离”值的一半。在此示例项目中,“悬挂距离”为 0.3(默认值),因此需要将 Wheel 碰撞器游戏对象向上移动 0.15 个单位。
Unity 允许您在数字字段中输入简单的数学计算。您可以使用它添加到 Y 轴值。
+0.15到值的末尾(例如,如果值为 0.5,则该值现在应为0.5+0.15).Unity 将 +0.15 应用于上一个值,这将 Wheel 碰撞器游戏对象沿 Y 轴向上移动 0.15 个单位。
车轮碰撞器小工具现在应该完全位于车轮网格体的中心:
首次使用添加车轮碰撞器中描述的工作流程添加车轮碰撞器时,它们太大(在“场景”视图中,车轮碰撞器小工具大于车轮模型网格体)。
要准确纠正此问题,您需要知道车轮模型的确切半径。此信息应可从您的 3D 建模软件或创作模型的技术美术师处获得。
在此示例项目中,车轮模型的半径为 0.44。
0.44.如果车轮模型的确切半径未知或不可用,你可以使用 车轮碰撞器小工具将其半径与模型近似匹配。或者,您可以使用球体碰撞器球体形状的碰撞器组件,用于处理游戏对象(如球或其他出于物理目的可以粗略近似为球体)的碰撞。更多信息
请参阅术语表以获取半径,因为球体碰撞器会自动调整大小以包含其关联模型的网格。
要使用球体碰撞器获取半径:
车轮碰撞器现在应该与车轮模型的位置和大小完全匹配。
要控制汽车,您需要添加脚本一段代码,允许您创建自己的组件、触发游戏事件、随时间修改组件属性以及以您喜欢的任何方式响应用户输入。更多信息
请参阅术语表到执行以下作的项目:
在此示例中,我们使用两个脚本来执行此作:CarControl.cs和WheelControl.cs.
创建一个名为CarControl.cs,然后粘贴到下面的代码中:
using UnityEngine;
public class CarControl : MonoBehaviour
{
[Header("Car Properties")]
public float motorTorque = 2000f;
public float brakeTorque = 2000f;
public float maxSpeed = 20f;
public float steeringRange = 30f;
public float steeringRangeAtMaxSpeed = 10f;
public float centreOfGravityOffset = -1f;
private WheelControl[] wheels;
private Rigidbody rigidBody;
// Start is called before the first frame update
void Start()
{
rigidBody = GetComponent<Rigidbody>();
// Adjust center of mass to improve stability and prevent rolling
Vector3 centerOfMass = rigidBody.centerOfMass;
centerOfMass.y += centreOfGravityOffset;
rigidBody.centerOfMass = centerOfMass;
// Get all wheel components attached to the car
wheels = GetComponentsInChildren<WheelControl>();
}
// FixedUpdate is called at a fixed time interval
void FixedUpdate()
{
// Get player input for acceleration and steering
float vInput = Input.GetAxis("Vertical"); // Forward/backward input
float hInput = Input.GetAxis("Horizontal"); // Steering input
// Calculate current speed along the car's forward axis
float forwardSpeed = Vector3.Dot(transform.forward, rigidBody.linearVelocity);
float speedFactor = Mathf.InverseLerp(0, maxSpeed, Mathf.Abs(forwardSpeed)); // Normalized speed factor
// Reduce motor torque and steering at high speeds for better handling
float currentMotorTorque = Mathf.Lerp(motorTorque, 0, speedFactor);
float currentSteerRange = Mathf.Lerp(steeringRange, steeringRangeAtMaxSpeed, speedFactor);
// Determine if the player is accelerating or trying to reverse
bool isAccelerating = Mathf.Sign(vInput) == Mathf.Sign(forwardSpeed);
foreach (var wheel in wheels)
{
// Apply steering to wheels that support steering
if (wheel.steerable)
{
wheel.WheelCollider.steerAngle = hInput * currentSteerRange;
}
if (isAccelerating)
{
// Apply torque to motorized wheels
if (wheel.motorized)
{
wheel.WheelCollider.motorTorque = vInput * currentMotorTorque;
}
// Release brakes when accelerating
wheel.WheelCollider.brakeTorque = 0f;
}
else
{
// Apply brakes when reversing direction
wheel.WheelCollider.motorTorque = 0f;
wheel.WheelCollider.brakeTorque = Mathf.Abs(vInput) * brakeTorque;
}
}
}
}
如果使用的是输入系统包,请改用以下指南。首先,您需要在 Unity 的输入系统包中创建和配置输入作:
CarInputActions.Car(或您喜欢的任何名称)。在Car作映射,添加以下作:
最后,保存配置并从 actions 资产生成 C# 类:
CarInputActions资产。创建一个名为CarControl.cs,然后粘贴到下面的代码中:
using UnityEngine;
public class CarControl : MonoBehaviour
{
[Header("Car Properties")]
public float motorTorque = 2000f;
public float brakeTorque = 2000f;
public float maxSpeed = 20f;
public float steeringRange = 30f;
public float steeringRangeAtMaxSpeed = 10f;
public float centreOfGravityOffset = -1f;
private WheelControl[] wheels;
private Rigidbody rigidBody;
private CarInputActions carControls; // Reference to the new input system
void Awake()
{
carControls = new CarInputActions(); // Initialize Input Actions
}
void OnEnable()
{
carControls.Enable();
}
void OnDisable()
{
carControls.Disable();
}
// Start is called before the first frame update
void Start()
{
rigidBody = GetComponent<Rigidbody>();
// Adjust center of mass to improve stability and prevent rolling
Vector3 centerOfMass = rigidBody.centerOfMass;
centerOfMass.y += centreOfGravityOffset;
rigidBody.centerOfMass = centerOfMass;
// Get all wheel components attached to the car
wheels = GetComponentsInChildren<WheelControl>();
}
// FixedUpdate is called at a fixed time interval
void FixedUpdate()
{
// Read the Vector2 input from the new Input System
Vector2 inputVector = carControls.Car.Movement.ReadValue<Vector2>();
// Get player input for acceleration and steering
float vInput = inputVector.y; // Forward/backward input
float hInput = inputVector.x; // Steering input
// Calculate current speed along the car's forward axis
float forwardSpeed = Vector3.Dot(transform.forward, rigidBody.linearVelocity);
float speedFactor = Mathf.InverseLerp(0, maxSpeed, Mathf.Abs(forwardSpeed)); // Normalized speed factor
// Reduce motor torque and steering at high speeds for better handling
float currentMotorTorque = Mathf.Lerp(motorTorque, 0, speedFactor);
float currentSteerRange = Mathf.Lerp(steeringRange, steeringRangeAtMaxSpeed, speedFactor);
// Determine if the player is accelerating or trying to reverse
bool isAccelerating = Mathf.Sign(vInput) == Mathf.Sign(forwardSpeed);
foreach (var wheel in wheels)
{
// Apply steering to wheels that support steering
if (wheel.steerable)
{
wheel.WheelCollider.steerAngle = hInput * currentSteerRange;
}
if (isAccelerating)
{
// Apply torque to motorized wheels
if (wheel.motorized)
{
wheel.WheelCollider.motorTorque = vInput * currentMotorTorque;
}
// Release brakes when accelerating
wheel.WheelCollider.brakeTorque = 0f;
}
else
{
// Apply brakes when reversing direction
wheel.WheelCollider.motorTorque = 0f;
wheel.WheelCollider.brakeTorque = Mathf.Abs(vInput) * brakeTorque;
}
}
}
}
添加此CarControl.cs脚本添加到Carroot GameObject。
这CarControl.cs脚本根据用户输入处理汽车行为,例如加速、扭矩和制动。有关详细信息,请参阅代码注释。
的一些元素CarControl.cs脚本引用WheelControl.cs下一节中创建的脚本。
创建一个名为WheelControl.cs,然后粘贴到下面的代码中:
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;
}
}
将此脚本添加到每个 Wheel 碰撞器游戏对象。
这WheelControl.cs脚本使用WheelCollider.GetWorldPose以获取 Wheel 碰撞体在场景中的位置。然后,该脚本将该位置信息分配给指定的车轮模型 GameObject。有关详细信息,请参阅代码注释。
每个实例WheelControl.cs脚本必须具有对其相应的车轮模型 GameObject 的引用。
若要将正确的车轮模型游戏对象分配给每个车轮碰撞器,请执行以下作:
您还需要选择哪些车轮从 CarControl 脚本接收电机输入和转向输入。要通过车轮控制属性模拟四轮驱动汽车:
要测试汽车,请进入播放模式并使用箭头或 WASD 键移动和转向。请注意,输入控件仅在游戏视图具有焦点时才有效。
要更好地查看在场景中移动的汽车:
Carroot GameObject,然后按 Shift + F。现在您已经有了基本设置,您可以尝试更改不同的设置以观察它们如何影响汽车的运动。您还可以按照这些说明对不同的车型进行作,并观察其设置的异同。