Есть ли лучший способ написать этот сверху вниз автомобиль mdoel - PullRequest
0 голосов
/ 22 мая 2019

Я пишу дрифт-кар, где я хочу, чтобы машина двигалась по кругу, а пользователь управляет радиусом круга с помощью рулевого управления, в основном прямое рулевое управление - это прямая линия, а повернутый влево - маленький круг.слева от машины, по которой он будет следовать.по мере того, как автомобиль поворачивает все больше (с обеих сторон), я пытаюсь сделать так, чтобы передняя часть машины все больше и больше поворачивалась к центру, как будто она дрейфует.

  1. Это для мобильной игры.поэтому я написал контроллер рулевого управления для автомобиля, чтобы контролировать его левый и правый, скорость постоянна.

  2. Есть два твердых тела.

car_fig_0

Передняя коробка белого цвета и большая коробка серого цвета - это твердые тела.соединены шарнирным соединением.

Передняя часть каждой рамы поворачивается на определенное количество градусов относительно своей оси z и немного смещается вперед.Таким образом, следует форма круга.количество вращений определяется моим рулевым управлением.

Я могу сделать оба тела кинематическими и убедиться, что они повторяют форму круга и движутся в этом направлении, но я также хочу иметь соответствующее поведение во время столкновенийВ окончательном плане возможны всевозможные столкновения.Поэтому я сделал их кинематическими и добавил скорости, используя методы добавления силы.Сама по себе передняя коробка идеальна, она вращается по кругу, когда я меняю рулевое управление, круг становится больше, все в порядке, но когда я добавляю коробку шасси Other, все силы перепутались.центробежные силы, и инерция все портит.

В основном мне нужна машина, чтобы дрейфовать идеальные круги, и пользователь должен иметь возможность контролировать радиус круга.Как лучше всего это смоделировать.

Вот код для обоих твердых тел.

  1. код передней коробки.Это просто исправленный метод обновления.Пожалуйста, игнорируйте код, связанный с элементами управления.В этом нет необходимости, поэтому я пропустил это.

    {
    //-------------------------
    // I N I T.
    //-------------------------
    
    current_steering_angle = controls_i.ToSignedRotation(controls_i.getSteeringAngle());
    current_steering_angle = (current_steering_angle < 0) ? (current_steering_angle + 90): current_steering_angle;
    current_steering_angle -= 45;
    
    //-------------------------
    // S P E E D.
    //-------------------------
    
    current_speed = Utils.curve_map_linear(0, 45, min_speed, max_speed, Mathf.Abs(current_steering_angle), -1);
    _rigid_body.AddRelativeForce(acceleration * Vector3.up);
    velocity = transform.InverseTransformVector(_rigid_body.velocity);
    if(velocity.y > current_speed){
        velocity.y = current_speed;
    }
    // to prevent reverse movement due to centrifugal force.
    velocity.x = 0;
    
    //-------------------------
    // R O T A T I O N.
    //-------------------------
    
    current_radius = Mathf.Sign(current_steering_angle) * Utils.exp_range_3(0, 45, min_radius, max_radius, Mathf.Abs(current_steering_angle), steering_tension, -1);
    current_rot_rate = (velocity.y / (2 * Mathf.PI * current_radius)) * 360;
    Vector3 angle = transform.localEulerAngles;
    angle.z += (current_rot_rate * Time.fixedDeltaTime);
    transform.localEulerAngles = angle;
    
    //-------------------------
    // A P P L Y.
    //-------------------------
    _rigid_body.velocity = transform.TransformVector(velocity); 
    
    }
    

Функции Utils.exp_linear и exp_range - это всего лишь диапазон для определения диапазона с некоторым напряжением, для контроля чувствительности рулевого управления.элементы управления.

Код для шасси.

{

//-------------------------
// I N I T.
//-------------------------

current_steering_angle = controls_i.ToSignedRotation(controls_i.getSteeringAngle());
current_steering_angle = (current_steering_angle < 0) ? (current_steering_angle + 90): current_steering_angle;
current_steering_angle = current_steering_angle - 45;
current_steering_angle = ((float)((int)(current_steering_angle * Mathf.Pow(10, 5))))/Mathf.Pow(10,5);

//-------------------------
// R O T A T I O N.
//-------------------------

current_angle = front_transform.eulerAngles.z - _rigid_body.transform.eulerAngles.z;

current_angle = (Mathf.Abs(current_angle) > 180) ? ((Mathf.Abs(current_angle) - 360) * Mathf.Sign(current_angle)) : current_angle;

current_angle += Mathf.Sign(current_steering_angle) * Utils.curve_map_linear(0, 45, min_angle, max_angle, Mathf.Abs(current_steering_angle), 1);

_rigid_body.transform.RotateAround(front_transform.position, Vector3.forward, current_angle);

//-------------------------
// S P E E D.
//-------------------------

Vector3 velocity = _rigid_body.transform.InverseTransformVector(_rigid_body.velocity);
if (velocity.y < 0){
    velocity.y = 0;
}
_rigid_body.velocity = _rigid_body.transform.TransformVector(velocity);

}

Я хотел бы знать, как на самом деле реализовать нечто подобное в единстве.Я новичок в этом единстве вещи.Я осмотрелся повсюду, и было много вещей для 3d-автомобилей, но не слишком много сверху.Ценю любые отзывы.

1 Ответ

1 голос
/ 23 мая 2019

Сделайте его не кинематическим, снимите жесткий корпус передних шин и сделайте передние шины дочерними элементами шасси.

Положение обработки:

Создайте метод, который смотрит на текущее положение автомобиля, на какой угол поворота игрока, и возвращает тангенциальную скорость, по которой автомобиль должен двигаться, чтобы двигаться по соответствующему кругу:

Vector2 GetTangentialVelocity(...) { }

Затем найдите разницу между этой скоростью и текущей скоростью шасси:

Vector2 velDiff = GetTangentialVelocity(...) - chassis_rigidbody.velocity;

Затем примените эту разницу, используя AddForce с ForceType.VelocityChange:

chassis_rigidbody.AddForce(velDiff, ForceType.VelocityChange);

Обработка вращения:

Переместить центр масс вперед. Вы можете сделать это, сделав твердое тело длинным и поместив коллайдер сзади объекта или установив RigidBody.centerOfMass:

chassis_rigidbody.centerOfMass = Vector2.up * 0.5;

Создайте функцию, аналогичную GetTangentialVelocity, которая возвращает желаемую угловую скорость, найдите разницу с chassis_rigidbody.angularVelocity, затем используйте AddTorque с ForceType.VelocityChange:

Vector2 angVelDiff = GetAngularVelocity(...) - chassis_rigidbody.angularVelocity;
chassis_rigidbody.AddTorque(angVelDiff , ForceType.VelocityChange);
...