我们可以统一使用 Physics.Simulate 来检测刚体何时发生碰撞吗

Can we detect when a rigid body collides using Physics.Simulate in unity

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

我正在尝试统一使用 physics.simulate。根据统一文档“模拟包括碰撞检测、刚体和关节集成的所有阶段,以及物理回调的归档(接触、触发器和关节” 我需要了解我的前锋游戏对象在哪个迭代中与其他游戏对象发生碰撞。如果我使用自动模拟,OnCollisionEnter 会起作用。但是,当我使用 Physics.Simulate 它不注册时它不起作用。当我的对象与其他对象发生碰撞时,我做错了什么或如何得到。

Can we detect when a rigid body collides using Physics.Simulate in unity

是的,可以。

我曾经对此做过一个实验,它成功了,我打开使用过的相同示例场景再次进行测试,它又成功了。这是文档中的声明,也在您的问题中:

Simulation includes all the stages of collision detection, rigidbody and joints integration, and filing of the physics callbacks (contact, trigger and joints).

因此,它可以检测碰撞。

If I user auto simulation, OnCollisionEnter works. However it doesn't work when I use Physics.Simulate it doesn't register.

你不能使用IsSleeping()来获得碰撞。假设您正确设置了对撞机和刚体,那么 问题是 maxIterations 太小 导致模拟未完成且未到达目的地它应该与另一个对象发生碰撞的地方。 如果没有发生碰撞,将不会调用 OnCollisionEnter

增加你的 maxIterations 以使其在模拟中移动更远的距离,并且应该调用 OnCollisionEnter。至于检测你的游戏对象与其他游戏对象发生碰撞的迭代,使用布尔变量作为标志并在 OnCollisionEnter 函数中将其设置为 true 然后在 for 循环中将其设置为 break当这个布尔变量是 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;
}