Проблема с физикой в местах соединения коллайдеров (отскоки на ровной поверхности)

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

При старте сцены у Rigidbody задается velocity для старта движения, в моменты отскоков на мяч кроме физики ничего не действует.

введите сюда описание изображения

Как убрать эти прыжки, почему так происходит? Пробовал удлинять коллайдеры у платформ, это не помогло, ставил разные collision detection у Rigidbody мяча - не помогает.

using UnityEngine;

public class SimpleX : MonoBehaviour
{
    public GameObject player;
    public GameObject cam;


    void Start()
    {
        if (!player){
            player = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            player.AddComponent<Rigidbody>();
        }
        player.transform.position = new Vector3(0, 2, 0);
        player.GetComponent<Rigidbody>().velocity = Vector3.forward * 200;

        if (!cam){
            cam = GameObject.Find("Main Camera");
        }
    }


    void Update()
    {
        cam.transform.position = player.transform.position - (Vector3.forward * 5);
    }


    int roadSectorCount = 0;
    int roadSectorLength = 10;
    private void FixedUpdate()
    {
        while(player.transform.position.z+100 > roadSectorCount * roadSectorLength) {
            var roadSector = GameObject.CreatePrimitive(PrimitiveType.Cube);
            roadSector.transform.position = new Vector3(0, 0, roadSectorCount * roadSectorLength);
            roadSector.transform.localScale = new Vector3(20, 1, roadSectorLength);
            roadSector.GetComponent<MeshRenderer>().material.color = new Color(Random.value, Random.value, Random.value, 0);
            roadSectorCount++;
        }
    }
}

Демонстрация проблемного поведения: https://www.youtube.com/watch?v=4A1W0eDaXnA

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

UPD

Переопределил у платформ методы OnCollision.

  • Отскок начинается до срабатывания OnCollisionEnter(первая фиксирует изменения) следующей платформы.

  • OnCollisionExit предыдущей платформы отрабатывает только спустя
    несколько итераций физики.

  • Получается, шар в моменте стоит на 2 коллайдерах одновременно, хотя и не должен.

Это поведение наблюдается при всех collision detection кроме continuous speculative (при нем прыжки будут почти на каждом переходе и может начаться до OnCollisionEnter, причем unity не может корректно обработать возврат на другой детект без перезапуска)

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


Ответы (2 шт):

Автор решения: Alemkhan Utepkaliev

Во-первых убедитесь что реальных зазоров нет, для заметки подскажу тем кто может с этим столкнуться, что можно использовать стыковки обьектов путём зажатия клавиши V и выбрав один из углов и протянуть его к другому необходимому углу.

Также возможно вам поможет решение с Contact Offset у физики, данный глобальный параметр указывает какое значение будет являтся дистанцией касания, попробуйте установить значение равное 0, или поиграть с значением методом пробы:

скрин

Во-вторых используйте физическое движение вместо "телепортаций" путём transform если в методе Update() указано движение игрока. Вам поможет движение по нормалям поверхности, для удобства есть наглядный видео урок по данной теме: https://www.youtube.com/watch?v=puPjNRJMmOc (если видео будет доступно к тому времени как Вы это откроете, если нет используйте информацию выше про движение по нормалям поверхности)

(Данный вариант исключает любую возможность падать персонажу внутрь потому что он будет идти строго по поверхности)

→ Ссылка
Автор решения: Kopkan

В общем, к каким выводам я пришел. По всей видимости, решить данную проблему в каком-то общем виде не выйдет, сама проблема находится в PhysX, то есть, будет актуальна для unity, unreal engine и прочих.

Есть несколько способов ухода от этой проблемы:

  1. Не использовать некинематический Rigidbody для персонажа.

    Тут все просто, если чего-то нет, то с этим и нет проблем. Используем для своих персонажей Character Controller, либо делаем полностью все сами через kinematic Rigidbody. Есть только проблемы с фактически полной реализацией свой физики для персонажа, но из плюсов полный контроль.

  2. Попробовать скрыть, уменьшить случаи проблемного поведение

    Можно переопределить OnCollisionEnter и при обнаружении незапланированного начала отскока возвращать Rigidbody на землю (костыль адовый, но кто-то использует).

    Простым вариантом является уменьшение contactOffset у проблемных коллайдеров и персонажа (myGameObject.GetComponent<SomeCollider>().contactOffset), либо уменьшение Default Contact Offset в настройках проекта (Edit -> Project Settings -> Physics -> Default Contact Offset)

    Стоит заметить, что при слишком низком значении, Rigidbody может начать трястись на ровной поверхность, поэтому с этим параметром придется экспериментировать, также это не защитит от отскоков от скрытых стен при частичных провалах внутрь коллайдера (при падении с высоты), поэтому придется это как-то дополнительно обрабатывать и исключать (Raycast, SphereCast).

    Даже при изменении Contact Offset, при обнаружении коллизий методом continuous speculative отскоки будут наблюдаться.

  3. Генерация общего коллайдер меша для дороги

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

Для большинства случаев наиболее верным решением будет использовать первый вариант.

→ Ссылка