Можем ли мы обнаружить, когда твердое тело сталкивается, используя физику. Симулировать в единицу
Да, это возможно.
Однажды я провел эксперимент на этом, и он сработал, я открыл ту же самую сцену, использованную для примера, и снова сделал тест, и он снова заработал.Вот заявление из документа, которое также находится в вашем вопросе:
Симуляция включает в себя все этапы обнаружения столкновений, интеграции твердого тела и соединений, а также регистрацию физических обратных вызовов (контакт, триггер и соединения).
Итак, он может обнаружить столкновение.
Если я использую автоматическое моделирование, 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;
}