Search Unity

Physics not working as intended?

Discussion in 'Physics' started by MWizard, Jun 13, 2018.

  1. MWizard

    MWizard

    Joined:
    Jan 5, 2017
    Posts:
    78
    So I made this short little example to test something, and I can't figure out why.

    As you will see in the video below, the collision starts, but after one rotation, it stops. Both objects' rigidbody is set to Continuous Dynamic collision specifically to force it to work, as ugly as it may be. I'm trying to understand limitations and this one seems... well too limiting... maybe... I dunno.

    Looking for Unity related answers, please. A physics lecture about quantum phases would be hilarious, but let's be focused :p

    This is the video
     
  2. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Let's see some code. How are you moving the stick? Physics.MoveRotation? Rigidbody.AddTorque?

    What happens if you slow it down?
     
  3. MWizard

    MWizard

    Joined:
    Jan 5, 2017
    Posts:
    78
    The only code I'm using:

    Code (CSharp):
    1. rb.transform.Rotate(0,5,0);
    There's obviously the variable declaration, etc. I've slowed it down to 2 on the rotational axis (0,2,0) and it still eventually does something similar.

    If I slow it down in the Physics engine (more calculations per sec) it still does the same thing.

    As I mentioned, I was just trying to see what my limitations are, and this one seems odd to run into such limitations at such a low speed collision. I could understand if it were spinning at like 500RPM but it's more like 60RPM.
     
  4. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    That's likely your problem. You generally don't get correct physics results when you directly modify the position/rotation of a transform. Instead, use MoveRotation (https://docs.unity3d.com/ScriptReference/Rigidbody.MoveRotation.html) to rotate, or MovePosition (https://docs.unity3d.com/ScriptReference/Rigidbody.MovePosition.html) to change the rigidbody's position. Those methods behave properly with the physics simulation.

    Note: You should do this within the FixedUpdate() method, not in the Update() method.
     
    AlanMattano likes this.
  5. MWizard

    MWizard

    Joined:
    Jan 5, 2017
    Posts:
    78
    Thanks! I knew it was something I was doing wrong... As I said, it seemed far too limiting to be having that issue so early on. I will give that a try later on today and let you know. Thanks!
     
  6. MWizard

    MWizard

    Joined:
    Jan 5, 2017
    Posts:
    78
    Ok, so I used MoveRotation. I literally copied and pasted the example, and at first it worked, but then I tried to see what would happen at faster speeds, and it did the same... exact... thing. I could post a video but it's the same thing.

    With the default code set at 100, it's fine. But it was a little slow for what I was testing. I bumped it to 300 and it starts to collide but then all of a sudden the collisions just stop happening like in the original video. It's almost like it crashes the collider in a way that it stops functioning after a second, but I really have no clue. I guess it's going to be part of working around the engine. I just have to be aware of that before I commit to any long term ideas.
     
  7. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Extremely high speed collisions are always going to be an issue with the physics system. The physics simulation runs at regular intervals for a fixed length of time. If an object moves too far between two consecutive passes, the physics might "miss" the collision, especially if one of the colliders involves is fairly small. A good example of this is bullets, which a very small, and very fast. It's common for bullets to move so far in one physics update that they simply jump from one side of a collider to another, never registering the collision. This occurs even with Continuous Dynamic collisions enabled.

    You can try overcoming this by adjusting some of the settings in Edit -> Project Settings -> Physics. For example, Default Solver Iterations can be adjusted to improve the physics calculation at the expense of more CPU load. You can also go into Edit -> Project Settings -> Time, and adjust the Fixed Timestep, which is the number of seconds that pass between Physics simulation. I'm less familiar with exactly how to adjust those values, but they can have an impact on physics accuracy. Try playing around with those and see if it improves the behavior.

    In the event that it does not, the fallback that people use is to perform Raycasting to detect whether a collision will occur in a given frame, and then manually apply forces to the object. To extend the "bullet" example, I was having issues with my projectiles going through walls, because the projectile was fast and small. So I wrote a little code to perform a raycast forward every frame, and see if there was anything in front of the projectile close enough that it would hit it on the next frame. If so, I considered the projectile to have "hit" the object, and performed the same thing I would have normally performed in an OnCollisionEnter event. That's probably a trickier thing to manage with your spinning bar, though.
     
    MWizard likes this.
  8. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,512
    This specific case might be dealing with the limits of the physics engine.

    The methods for continuous collision detection typically work by projecting the volume between two consecutive positions of the object, then checking the collisions against the projected volume.

    Imagine a moving box. In a given time step the box is in a specific position. The next time the box will be located in a different position, which will be far away form the first position is the box is moving fast. The physics engine "connects" both positions and creates a long volume between them. Then the collision detection is performed against this volume instead of the box alone. Thus, collisions in the middle of a step can be detected even if the box is moving really fast.

    Back to your case. When the stick rotates at moderate speeds then the projection between two consecutive positions allow the collision with the ball to be detected. However, increasing the rotation speed will reach a point where two consecutive positions of the stick are nearly the same. For example, if the stick rotates 180 degrees in a single step then it will literally occupy the same position in two consecutive steps. The continuous collision detection will create the projection between these positions, but it will be the same, so it won't detect the collision with anything in other positions.

    It's rather simple to calculate the maximum angular velocity for which the collisions will be detected.

    delta Angle = Angular Velocity * delta Time

    Angular Velocity = delta Angle / delta Time

    Lets assume the collisions are acceptable when rotating the stick up to 90 degrees each time step. Still, some collisions might be missed in the edge of the "ideal" circle caused by the rotation, but this is a good starting point (the "continuous collision volume" will become narrower beyond 90 degrees per step). Using the default time step in Unity (0.02 seconds) yields:

    Angular Velocity = 90 / 0.02 = 4500 degrees per second = 12.5 revs per second
    That's pretty much the maximum rotation speed at which you can get rather coherent collisions in Unity with Continuous Collision detection with the default time step.

    Also, the smaller delta Angle the more accurate collisions in the edge of the circle defined by the rotation of the stick.

    So if you want to improve things from here, some of your choices are:
    • Increasing the maximum Angular Velocity --> reduce the time step
    • Increasing accuracy of the collisions in the edges of the rotation --> reduce the maximum delta Angle (but this also reduces the maximum Angular Velocity).
     
    Last edited: Jun 17, 2018
  9. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
  10. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,512
    I don't think so. I'm not entirely sure, but as for what I've been able to see, solver iterations affect the situations where some state is "not correct" and must be converted to "correct". Then an iterative process is performed using the configured solver iterations.

    These situations include the joint constraints for sure. Maybe also the de-penetration situations and the contact resolution. But as far as I can tell, the motion and the contact detection itself (even continuous dynamic) are not affected.