Можем ли мы обнаружить, когда твердое тело сталкивается, используя Physics.Simulate в единстве - PullRequest
0 голосов
/ 05 июня 2018
public void RunSimulation()
{
        Physics.autoSimulation = false;
        simulatedBodies = FindObjectsOfType<Rigidbody>().Select(rb => new SimulatedBody(rb)).ToArray();
        striker.GetComponent<Rigidbody> ().AddForce (new Vector3 (200.0f, 0.0f, 200.0f));

        for (int i = 0; i < maxIterations; i++)
        {
            Physics.Simulate(0.02f);
            //GET COLLISIONS HERE 
            if (simulatedBodies.All(body => body.rigidbody.IsSleeping()))
            {
                print(i);
                break;
            }
        }
        Physics.autoSimulation = true;
}

Я пытаюсь использовать физику. Имитация в единстве.В соответствии с документацией по единству « моделирование включает в себя все этапы обнаружения столкновений, интеграции твердого тела и соединений, а также регистрации обратных вызовов физики (контакт, триггер и соединения »).с другим игровым объектом. Если я использую автоматическое моделирование, OnCollisionEnter работает. Однако он не работает, когда я использую Physics.Simulate, он не регистрируется. Что я делаю неправильно или как я получаю, когда мой объект сталкивается с другими объектами.

1 Ответ

0 голосов
/ 05 июня 2018

Можем ли мы обнаружить, когда твердое тело сталкивается, используя физику. Симулировать в единицу

Да, это возможно.

Однажды я провел эксперимент на этом, и он сработал, я открыл ту же самую сцену, использованную для примера, и снова сделал тест, и он снова заработал.Вот заявление из документа, которое также находится в вашем вопросе:

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

Итак, он может обнаружить столкновение.

Если я использую автоматическое моделирование, OnCollisionEnter работает.Однако это не работает, когда я использую Physics.Simulate, он не регистрируется.

Вы не можете использовать IsSleeping(), чтобы получить столкновение.Если вы правильно настроили коллайдер и Rigidbody, то проблема в том, что значение maxIterations слишком мало , что приводит к тому, что симуляция не завершена и не достигает места назначения, где предполагается столкновение с другимобъект. Если это столкновение не выполнено, OnCollisionEnter не будет вызвано.

Увеличьте maxIterations, чтобы придать ему большее расстояние в симуляции, и следует вызвать OnCollisionEnter.Что касается определения того, какая итерация вашего GameObject сталкивается с другим GameObject, используйте логическую переменную в качестве флага и установите для нее значение true в функции OnCollisionEnter, затем break из цикла for, когда эта логическая переменная true.

const int maxIterations = 60;
int collideIteration = 0;
bool collided = false;

public void RunSimulation()
{
    //RESET OLD VALUES
    collided = false;
    collideIteration = 0;

    Physics.autoSimulation = false;

    Rigidbody rbdy = GetComponent<Rigidbody>();
    rbdy.AddForce(new Vector3(200.0f, 0.0f, 200.0f));


    for (int i = 0; i < maxIterations; i++)
    {
        Physics.Simulate(0.02f);

        //Check if collided then break out of the loop 
        if (collided)
        {
            collideIteration = i;

            print(i);
            break;
        }
    }
    Physics.autoSimulation = true;
}

public int GetCollideIteration()
{
    return collideIteration;
}

void OnCollisionEnter(Collision collision)
{
    collided = true;
    Debug.Log("Collision: " + collision.collider.name);
}

Если увеличение maxIterations не решило вашу проблему, то посмотрите моделирование на основе времени .Это сделает симуляцию за x секунд.В приведенном ниже коде используется 5 секунд, и изменяется только функция RunSimulation().Остальная часть кода выше все еще действительна:

public void RunSimulation()
{
    //RESET OLD VALUES
    collided = false;
    collideIteration = 0;

    Physics.autoSimulation = false;

    Rigidbody rbdy = GetComponent<Rigidbody>();
    rbdy.AddForce(new Vector3(200.0f, 0.0f, 200.0f));

    //Simulate where it will be in 5 seconds
    float timeInSec = 5f;
    int i = 0;

    while (timeInSec >= Time.fixedDeltaTime)
    {
        timeInSec -= Time.fixedDeltaTime;
        Physics.Simulate(Time.fixedDeltaTime);

        //Check if collided then break out of the loop 
        if (collided)
        {
            collideIteration = i;

            print(i);
            break;
        }
        i++;
    }
    Physics.autoSimulation = true;
}
...