Подтвердить что ты не робот

Как предотвратить коллайдеры от прохождения друг друга?

У меня возникают проблемы с сохранением игровых объектов внутри содержащегося пространства. Когда они достигают края, происходит мгновенное отталкивание назад, но затем они пройдут прямо через стену.

Я использую Box Player на игроком и Mesh Collider для уровня стены. У меня возникают проблемы с персонажем игрока (космическим кораблем), что движение контролируется игроком. И с снарядами, которые стреляют и забывают двигаться с постоянной скоростью.

Это мой код для моего игрока. Он запускается в функции FixedUpdate().

//Movement
    haxis = Input.GetAxis("Horizontal") * speed;
    vaxis = Input.GetAxis("Vertical") * speed;

    moveVector.x = haxis;
    moveVector.z = vaxis;

    if(moveVector.magnitude > 1)
    {
        moveVector.Normalize();
    }

    rigidbody.MovePosition(transform.position + moveVector * speed);

С пулями им дается скорость, и двигатель вычисляет их видеоролики. Они используют Box Collider, и он установлен как триггер, поэтому у них нет физики. Но я использую OnTriggerEnter для их уничтожения.

//Projectiles without physics collisiions
function OnTriggerEnter (other : Collider) {
    Destroy(gameObject);
}

Некоторые, но не все пули будут уничтожены при попадании на сетчатую стену коллайдера. Игрок иногда ударяет его и останавливается, но обычно может проталкивать его. Как я могу делать столкновения с работой коллайдера сетки каждый раз?

4b9b3361

Ответ 1

Столкновение с быстро движущимися объектами всегда является проблемой. Хороший способ обеспечить обнаружение всех столкновений - использовать Raycasting вместо того, чтобы полагаться на физическое моделирование. Это хорошо работает для пуль или небольших объектов, но не дает хороших результатов для больших объектов. http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html

Псевдокодиш (у меня нет завершения кода здесь и плохой памяти):

void FixedUpdate()
{
    Vector3 direction = new Vector3(transform.position - lastPosition);
    Ray ray = new Ray(lastPosition, direction);
    RaycastHit hit;
    if (Physics.Raycast(ray, hit, direction.magnitude))
    {
        // Do something if hit
    }

    this.lastPosition = transform.position;
}

Ответ 2

У меня есть прототип пинбола, который также дал мне много проблем в тех же областях. Это все шаги, которые я предпринял почти (но еще не полностью), чтобы решить эти проблемы:

Для быстро движущихся объектов:

  • Задайте для Interpolate жесткой формы Interpolate (это не влияет на фактическое физическое моделирование, но обновляет рендеринг объекта правильно - используйте это только для важных объектов с точки зрения рендеринга, например, игрока, или пинбол, но не для снарядов)

  • Установить обнаружение столкновений на непрерывный динамический

  • Подключите script DontGoThroughThings (https://www.auto.tuwien.ac.at/wordpress/?p=260) к вашему объекту. Этот script умело использует решение Raycasting, которое я опубликовал в своем другом ответе, чтобы отбросить объекты-нарушители до точек столкновения.

В Изменить → Настройки проекта → Физика:

  • Установите Min Penetration for Penalty на очень низкое значение. Я установил мой 0,001

  • Установите значение "Итерация счетчика" на большее значение. Я установил для меня 50, но вы, вероятно, можете делать нормально с гораздо меньшим.

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

Ответ 4

Поэтому мне не удалось заставить Mesh Colliders работать. Я создал составной коллайдер, используя простые полевые коллайдеры, и он работал точно так, как ожидалось.

Другие тесты с простыми коллайдерами Mesh выглядят одинаково.

Похоже, лучший ответ - собрать сложный коллайдер из простых коллайдеров box/sphere.

В моем конкретном случае я написал Мастер, который создает трубчатый составной коллайдер.

@script AddComponentMenu("Colliders/Pipe Collider");
class WizardCreatePipeCollider extends ScriptableWizard
{
    public var outterRadius : float = 200;
    public var innerRadius : float = 190;
    public var sections : int = 12;
    public var height : float = 20;

    @MenuItem("GameObject/Colliders/Create Pipe Collider")
    static function CreateWizard()
    {
        ScriptableWizard.DisplayWizard.<WizardCreatePipeCollider>("Create Pipe Collider");
    }

    public function OnWizardUpdate() {
        helpString = "Creates a Pipe Collider";
    }

    public function OnWizardCreate() {
        var theta : float = 360f / sections;
        var width : float = outterRadius - innerRadius;

        var sectionLength : float = 2 * outterRadius * Mathf.Sin((theta / 2) * Mathf.Deg2Rad);

        var container : GameObject = new GameObject("Pipe Collider");
        var section : GameObject;
        var sectionCollider : GameObject;
        var boxCollider : BoxCollider;

        for(var i = 0; i < sections; i++)
        {
            section = new GameObject("Section " + (i + 1));

            sectionCollider = new GameObject("SectionCollider " + (i + 1));
            section.transform.parent = container.transform;
            sectionCollider.transform.parent = section.transform;

            section.transform.localPosition = Vector3.zero;
            section.transform.localRotation.eulerAngles.y = i * theta;

            boxCollider = sectionCollider.AddComponent.<BoxCollider>();
            boxCollider.center = Vector3.zero;
            boxCollider.size = new Vector3(width, height, sectionLength);

            sectionCollider.transform.localPosition = new Vector3(innerRadius + (width / 2), 0, 0);
        }
    }
}

Ответ 5

  • Изменить --- > Настройки проекта --- > Время... decrese Значение фиксированной временной отметки. Это решит проблему, но может отрицательно сказаться на производительности.

  • Другим решением может быть вычисление координат (например, у вас есть мяч и стена, мяч попадает в стену, поэтому вычисляйте координаты стены и устанавливайте процесс удара по этим каналам)

Ответ 6

1.) Никогда не используйте MESH COLLIDER. Используйте комбинацию коллайдера с коробкой и капсулой.

2.) Проверьте ограничения в RigidBody. Если вы отметите позицию фиксации X, то она пройдет через объект по оси X. (То же самое для оси y).

Ответ 7

Старый вопрос, но, возможно, это помогает кому-то.

Перейдите к настройкам проектa > Время и попробуйте делить фиксированный временной интервал и максимально допустимый временной интервал на два или четыре.

У меня была проблема с тем, что мой игрок смог сжать отверстия, меньшие, чем игроки-коллайдеры, и это решило. Это также помогает остановить быстро движущиеся объекты.