Search Unity

Inconsistent results when using ForceMode.VelocityChange to apply a collision reaction force

Discussion in 'Physics' started by trzy, Aug 19, 2017.

  1. trzy

    trzy

    Joined:
    Jul 2, 2016
    Posts:
    128
    Hi,

    I'm trying to detect collisions between a collider and other objects, and then apply a reaction impulse that rapidly pushes the object away from the collision point. To do this, I take the first contact normal found in OnCollisionEnter() and apply a relatively large force (in my world, 1 unit = 1 m and the object is small, so 0.75 is a large magnitude) in the direction of the normal. Code below.

    Code (csharp):
    1.  
    2.   private void OnCollisionEnter(Collision collision)
    3.   {
    4.     Vector3 normal = collision.contacts[0].normal;
    5.     m_rb.AddForce(normal * 0.75f, ForceMode.VelocityChange);
    6.  
    7.     // Debug: draw normal
    8.     LineRenderer lr = GetComponent<LineRenderer>();
    9.     lr.positionCount = 2;
    10.     lr.SetPosition(0, collision.contacts[0].point);
    11.     lr.SetPosition(1, collision.contacts[0].point + normal);
    12.     lr.useWorldSpace = true;
    13.   }
    The problem is that the reaction is totally inconsistent. Sometimes, it appears as though a large magnitude velocity change occurs, and other times, the effect is tiny.

    Here's a video of the problem.

    Note how it sometimes gets pushed strongly but other times less so, especially when colliding horizontally against the wall (the black region it collides with has an invisible mesh -- sorry for the confusion). It has nothing to do with the applied forces used to steer the helicopter (because if anything, the faster it moves toward the ground, the larger the bounce, despite the reaction being opposite to the control inputs). I'm printing out collision.impulse and it's always zero. What's going on here and how can I achieve a more consistent effect?

    Thanks!

    Bart
     
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    The OnCollisionEnter event means that the rigidbody has already collided and the physics system has already computed and applied an impulse to resolve the collision. So applying an additional impulse will sum to the impulse already applied by the physics. This explain the incoherent results.

    If you want to calculate and resolve the collisions yourself, first step is telling the physics system to ignore the collisions with your helicopter. You may do so by using layers and configuring the Layer-based collision detection, or using Physics.IgnoreCollision.

    Next step is detecting and resolving the collisions yourself. You may use Physics.ComputePenetration (invoked from FixedUpdate) for detecting the collisions.
     
    trzy likes this.
  3. trzy

    trzy

    Joined:
    Jul 2, 2016
    Posts:
    128
    Thanks Edy! Sorry for the late reply! I'm experimenting with this now. If my understanding is correct, the physics system would essentially resolve penetrations using a method consistent with ComputePenetration's result, correct? One of my fears is devising a solution that can accidentally push the helicopter through the wrong side of the wall, which can easily happen if disabling collisions with the wall layer and trying to do something cheap and simple like applying a force in the opposite direction of velocity at time of first intersection.
     
  4. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    I think so, but I don't have a solid base to give a proper answer. ComputePenetration resolves the contact once the bodies are inter-penetrating. But maybe contacts / collisions are first detected in some other way.