Всем привет! Сегодня мы сделаем так, чтобы наш автомобиль мог ездить, начнем!
Колеса
Делаем 4 Whell Collider — создаем пустой объект — вешаем туда компонент Whell Collider, и подгоняем под колесо, и так 4 раза. Но, для начало добавьте к машине Box Collider и Rigidbody, Box Collider настройте под размеры автомобиля.
Вот так у вас должно получится, обязательно обратите внимание на Hierarchy. У Rigidbody измените массу, к примеру на 2 тонны.
Скрипт CarController
Создайте новый скрипт под названием CarController, и откройте скрипт, удалите там все методы. И впишите данный код:
[SerializeField] private Transform _transformFL;
[SerializeField] private Transform _transformFR;
[SerializeField] private Transform _transformBL;
[SerializeField] private Transform _transformBR;
[SerializeField] private WheelCollider _colliderFL;
[SerializeField] private WheelCollider _colliderFR;
[SerializeField] private WheelCollider _colliderBL;
[SerializeField] private WheelCollider _colliderBR;
[SerializeField] private float _force;
[SerializeField] private float _maxAngle;
// Start is called before the first frame update
private void FixedUpdate()
{
_colliderFL.motorTorque = Input.GetAxis("Vertical") * _force;
_colliderFR.motorTorque = Input.GetAxis("Vertical") * _force;
if (Input.GetKey(KeyCode.Space))
{
_colliderFL.brakeTorque = 3000f;
_colliderFR.brakeTorque = 3000f;
_colliderBL.brakeTorque = 3000f;
_colliderBR.brakeTorque = 3000f;
}
else
{
_colliderFL.brakeTorque = 0f;
_colliderFR.brakeTorque = 0f;
_colliderBL.brakeTorque = 0f;
_colliderBR.brakeTorque = 0f;
}
_colliderFL.steerAngle = _maxAngle * Input.GetAxis("Horizontal");
_colliderFR.steerAngle = _maxAngle * Input.GetAxis("Horizontal");
RotateWheel(_colliderFL, _transformFL);
RotateWheel(_colliderFR, _transformFR);
RotateWheel(_colliderBL, _transformBL);
RotateWheel(_colliderBR, _transformBR);
}
private void RotateWheel(WheelCollider collider, Transform transform)
{
Vector3 position;
Quaternion rotation;
collider.GetWorldPose(out position, out rotation);
transform.rotation = rotation;
transform.position = position;
}
Разбор:
- Создали 4 переменных типа Transform для каждого колеса.
- Еще 4 переменные типа WheelCollider для каждого коллайдера колеса.
- Дополнительные 2 переменные — мощность и максимальный угол поворота колеса.
- Говорим, что _colliderFL.motorTorque и _colliderFR.motorTorque это ввод клавиш W и S умноженное на мощность.
- Если нажимаем на пробел, то к каждому коллайдеру применяем тормозную силу 3000.
- Если мы не нажимаем на пробел, то к каждому коллайдеру применяем тормозную силу 0.
- Говорим, что _colliderFL.steerAngle и _colliderFR.steerAngle это максимальный угол поворота колеса умноженный на ввод клавиш A и D.
- Поворачиваем колеса
- Метод для поворота колес.
Сохраняем скрипт, и в юнити. Заполняем пункты. FL — Переднее — левое колесо. FR — переднее — правое колесо. BL — заднее — левое колесо. BR — заднее — правое колесо. Ставим force на 2500, а maxAngle на 60. Запускаем! Но только при повороте, у нас машина заваливается. Погнали, исправлять.
Фикс багов
Измените код, на этот:
[SerializeField] private Transform _transformFL;
[SerializeField] private Transform _transformFR;
[SerializeField] private Transform _transformBL;
[SerializeField] private Transform _transformBR;
[SerializeField] private WheelCollider _colliderFL;
[SerializeField] private WheelCollider _colliderFR;
[SerializeField] private WheelCollider _colliderBL;
[SerializeField] private WheelCollider _colliderBR;
[SerializeField] private float _force;
[SerializeField] private float _maxAngle;
private Rigidbody _rigidbody;
// Start is called before the first frame update
private void Start()
{
_rigidbody = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
_colliderFL.motorTorque = Input.GetAxis("Vertical") * _force;
_colliderFR.motorTorque = Input.GetAxis("Vertical") * _force;
if (Input.GetKey(KeyCode.Space))
{
_colliderFL.brakeTorque = 3000f;
_colliderFR.brakeTorque = 3000f;
_colliderBL.brakeTorque = 3000f;
_colliderBR.brakeTorque = 3000f;
}
else
{
_colliderFL.brakeTorque = 0f;
_colliderFR.brakeTorque = 0f;
_colliderBL.brakeTorque = 0f;
_colliderBR.brakeTorque = 0f;
}
_colliderFL.steerAngle = _maxAngle * Input.GetAxis("Horizontal");
_colliderFR.steerAngle = _maxAngle * Input.GetAxis("Horizontal");
RotateWheel(_colliderFL, _transformFL);
RotateWheel(_colliderFR, _transformFR);
RotateWheel(_colliderBL, _transformBL);
RotateWheel(_colliderBR, _transformBR);
_rigidbody.centerOfMass = new Vector3(0f, -0.3f, 0f); // Adjust the Y value as needed
}
private void RotateWheel(WheelCollider collider, Transform transform)
{
Vector3 position;
Quaternion rotation;
collider.GetWorldPose(out position, out rotation);
transform.rotation = rotation;
transform.position = position;
}
Устанавливая значение Y для центра масс отрицательным, вы понижаете центр масс. После чего наш автомобиль не должен заваливаться, но вы можете сделать поменьше значение.
Фикс багов 2
У нас есть еще один баг, если мы отпустим камеру вниз, то мы увидим дно автомобиля. А plane не видно. Для этого заходим в камеру, и ищем — Blocking Layers, создаем новый слой Ground. Для этого — объект — Layer (в правом верхнем углу) — AddLayer — в свободной строчке пишем Ground и все.
Теперь устанавливаем наш слой Ground на Plane и в камере — Blocking Layers выбираем наш слой Ground. И все! Blocking Layers это настройка, указывающая через какие слои не может пройти камера.