Робот:
- Использует WheelColliders для движения и рулевого управления
- Использует датчики Raycast (спереди, слева, справа) для обнаружения приближения
- Использует Датчик EulerAngles для ориентации
- Правильно движется вперед и передает ожидаемый крутящий момент двигателя
- Колеса визуально вращаются и управляются правильно
1. Машина поворачивает неправильно
Хотя:
- применяется к коллайдерам передних колес.
Код: Выделить всё
steerAngle - Крутящий момент двигателя подается правильно.
- Значения датчиков действительны и обновляются правильно.
- едет в основном прямо и игнорирует повороты, либо
- очень слабо поворачивает и съезжает с трассы на поворотах
После улучшения поворотов автомобиль должен также:
- Надежно ездить в гору и на спуске
- Соответствующим образом регулировать мощность на уклонах
- Сохранять устойчивость и сцепление с дорогой на наклонных поверхностях
- терять скорость на подъеме
- слишком агрессивно ускоряться на спуске
- дрифтовать или не выдерживать намеченную траекторию
- логика рулевого управления и двигателя выполняется в методе FixUpdate()
- рукоятка передних колес рулевое управление; задние колеса обеспечивают движение
- Решения по рулевому управлению принимаются на основе расстояний raycast
- Я не могу изменить модель транспортного средства, физические материалы или настройки Unity — только скрипт контроллера
Ниже приведен фрагмент кода текущий RobotController.cs, над которым я работаю, где требуется управление рулевым управлением и управление наклоном улучшение.
Я также предоставил изображение макета дорожки для контекста.
Код: Выделить всё
// RobotController.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;
public class RobotController : MonoBehaviour
{
// wheel colliders
[SerializeField] private WheelCollider WheelColliderFrontLeft;
[SerializeField] private WheelCollider WheelColliderFrontRight;
[SerializeField] private WheelCollider WheelColliderBackLeft;
[SerializeField] private WheelCollider WheelColliderBackRight;
// transforms for the wheels
[SerializeField] private Transform TransformWheelFrontLeft;
[SerializeField] private Transform TransformWheelFrontRight;
[SerializeField] private Transform TransformWheelBackLeft;
[SerializeField] private Transform TransformWheelBackRight;
// transforms for the sensors
[SerializeField] private Transform RaycastSensorFront;
[SerializeField] private Transform RaycastSensorLeft;
[SerializeField] private Transform RaycastSensorRight;
[SerializeField] private Transform EulerAnglesSensor;
private Rigidbody rb;
[SerializeField] private float angle_x;
[SerializeField] private float angle_z;
[SerializeField] private float velocity;
private float steerAngle;
private float maxSteeringAngle;
private float motorForce =150f;
private float s1dist = 5;
private float s3dist = 4;
private void Start()
{
rb = GetComponent();
float s1x =0; float s1y=10; float s1z =0;
AdjustSensors(RaycastSensorFront, 20,0,0);
AdjustSensors(RaycastSensorLeft, s1x,-s1y,s1z);
AdjustSensors(RaycastSensorRight, s1x,s1y,s1z);
AdjustSensors(EulerAnglesSensor, 50,180,0);
}
private void FixedUpdate()
{
StayOnRoad();
AvoidObstacles();
AdjustSpeed();
HandleMotor();
UpdateWheels();
angle_x = EulerAnglesSensor.eulerAngles.x;
angle_z = EulerAnglesSensor.eulerAngles.z;
velocity = rb.linearVelocity.magnitude;
}
private void AdjustSensors(Transform sensor, float x_angle, float y_angle, float z_angle)
{
sensor.transform.Rotate(x_angle, y_angle, z_angle);
}
private void HandleMotor()
{
WheelColliderFrontLeft.motorTorque = motorForce;
WheelColliderFrontRight.motorTorque = motorForce;
WheelColliderBackLeft.motorTorque = motorForce;
WheelColliderBackRight.motorTorque = motorForce;
}
private void UpdateWheels()
{
UpdateWheelPos(WheelColliderFrontLeft, TransformWheelFrontLeft);
UpdateWheelPos(WheelColliderFrontRight, TransformWheelFrontRight);
UpdateWheelPos(WheelColliderBackLeft, TransformWheelBackLeft);
UpdateWheelPos(WheelColliderBackRight, TransformWheelBackRight);
}
private void UpdateWheelPos(WheelCollider wheelCollider, Transform trans)
{
Vector3 pos;
Quaternion rot;
wheelCollider.GetWorldPose(out pos, out rot);
trans.rotation = rot;
trans.position = pos;
}
private void HandleSteering(float direction)
{
steerAngle = maxSteeringAngle * direction;
WheelColliderFrontLeft.steerAngle = steerAngle;
WheelColliderFrontRight.steerAngle = steerAngle;
}
private bool sense (Transform sensor, float dist)
{
if(Physics.Raycast(sensor.position, sensor.TransformDirection(Vector3.forward), dist))
{
Debug.DrawRay(sensor.position, sensor.TransformDirection(Vector3.forward) * dist, Color.yellow);
return true;
}
else
{
Debug.DrawRay(sensor.position, sensor.TransformDirection(Vector3.forward) * dist, Color.white);
return false;
}
}
private void StayOnRoad()
{
if(!sense(RaycastSensorLeft, s3dist) || !sense(RaycastSensorRight, s3dist))
{
if(!sense(RaycastSensorLeft, s3dist))
{
HandleSteering(1);
}
if(!sense(RaycastSensorRight, s3dist))
{
HandleSteering(-1);
}
}
else
{
HandleSteering(0);
}
}
private void AdjustSpeed()
{
if(velocity < 2 & motorForce < 50)
{
motorForce = motorForce + 0.5f;
}
if(velocity > 4 & motorForce > 0)
{
motorForce = motorForce - 0.5f;
}
}
private void AvoidObstacles()
{
if(sense(RaycastSensorLeft, s1dist))
{
HandleSteering(1);
}
if(sense(RaycastSensorRight, s1dist))
{
HandleSteering(-1);
}
}
}
- Распространенные ошибки при использовании WheelCollider рулевого управления
- Как правильно сбалансировать крутящий момент двигателя, угол поворота и торможение
- Необходимо ли по-другому сглаживать или зажимать рулевое управление
- Лучшие практики для автономных систем на основе raycast рулевое управление
- Методы управления движением в гору/спуска с помощью WheelColliders
- Любая логика контроллера, которая может помешать правильному повороту или компенсации наклона
Спасибо!

Подробнее здесь: https://stackoverflow.com/questions/798 ... -on-slopes
Мобильная версия