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

у меня возникли проблемы с хранением игровых объектов внутри замкнутого пространства. Когда они достигают края, происходит какое-то мгновенное отталкивание, но затем они проходят прямо сквозь стену.

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

это мой код движения для моего игрока. Он работает в

7 ответов


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

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

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;
}

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

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

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

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

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

на Правка - > Настройки Проекта - > Физика:

  • установите минимальное проникновение для штрафа до очень низкого значения. Я установил свой 0.001

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

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


Как насчет установки обнаружения столкновения rigidbody в непрерывно или Непрерывный Динамический?

http://unity3d.com/support/documentation/Components/class-Rigidbody.html


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

другие тесты с простыми коллайдерами сетки вышли то же самое.

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

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

@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);
        }
    }
}

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

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


1.) Никогда не используйте сетчатый коллайдер. Используйте комбинацию box и capsule collider.

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


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

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

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