Search Unity

BUG? relativeVelocity.magnitude is measured differently in 5.3.1p1

Discussion in 'Physics' started by enhawk, Jan 1, 2016.

  1. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    Code (csharp):
    1. void OnCollisionEnter2D(Collision2D coll) {
    2.     float impact = coll.relativeVelocity.magnitude;
    3.     print(impact);
    4. }
    In 5.3 this outputs the relativeVelocity.magnitude of the impact after the object has collided (low number usually 0 or same as resting relativeVelocity.magnitude).

    In 5.2 this outputs the relativeVelocity.magnitude of the impact during the impact (usually a high number)

    This methodology is suggested by Unity as a means to make sound effects, damage etc related to the force of the impact, currently this is no longer possible in 5.3.

    Example: http://docs.unity3d.com/ScriptReference/Collision-relativeVelocity.html
     
  2. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    @MelvMay Just wondering if this is a known issue. I found a way around it by monitoring the velocity before impact, but relativeVelocity.magnitude on Collision doesn't seem to work the way it used to.
     
  3. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    @MelvMay Would be nice to get some kind of answer, grunt or smoke signal on this, right now it's stopping all the colliders from sensing if they are taking impact damage, basically a bunch of the game stopped working when upgrading unity. I filed a bug report: 758422
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    I'm not seeing this behaviour at all and there's no simple reproduction project in the case. Can you attach something that demonstrates it?
     
  5. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    Hi @MelvMay sure, have attached sample here. If you run the Scene in 5.3 it'll output the impact registered.

    Here's the example from the manual (this bit is broken in 5.3 it would seem, impact is always 0)
     

    Attached Files:

    Last edited: Jan 12, 2016
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    Hi,

    Just letting you know that I'll be looking at this bug and two others that have come in during the next few days; it's not been forgotten or anything.
     
    enhawk likes this.
  7. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    Noticing this is affecting some others, I'll post my work around here for use in the meantime:

    Code (csharp):
    1.  
    2. public float velocityForHurt = 27.5f;
    3. public bool willGetHurt;
    4.  
    5. void FixedUpdate() {
    6.     if (rb.velocity.magnitude > velocityForHurt) willGetHurt = true;
    7. }
    8.  
    9. void OnCollisionEnter2D(Collision2D coll) {
    10.     if (willGetHurt) HurtMe();
    11.    willGetHurt = false;
    12. }
    13.  
    This should be enough to detect impact velocity.
     
    theANMATOR2b likes this.
  8. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    Happy to report this has been fixed in 5.3.3f1

    Many thanks @MelvMay
     
  9. grosssmutttr

    grosssmutttr

    Joined:
    Apr 15, 2014
    Posts:
    168
  10. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    Sorry for the delay.

    This has been fixed and will be in a 5.3 patch release (also in 5.4 beta).

    So you understand what's happening here, I thought I'd give you a breakdown of why this became broken. So this problem was caused (regressed) due to another fix that was applied. The other fix was to ensure that when Box2D has updated, all contacts are in sync with body/collider positions. In Box2D, this simply isn't the case; it checks for contacts first then runs the discrete solver then the continuous (TOI) solver. Some of these contacts won't be updated until the next step (FixedUpdate). This can be a problem in some case and it's a particular annoyance for me. You can find a reference to it on the Box2D forums here.

    An example of how this has shown up is that a user used `IsTouching` to see if an object was touching after a force had been applied to cause the object to jump away from a ground collider. The problem is that the force is applied during a fixed update but the contacts are not updated until the following one. This means a delay in what IsTouching reports because Box2D won't update the contacts until the next step.

    There was a change in Unity in 5.3 where we tried to update only those contacts which needed it and for the most part, that worked well without incurring too much overhead. This solved the above case and others that were being reported. The oversight was that in some cases, it meant the relative-velocity was updated more than once. What this results in is that it's reported correctly the first time and we store it but then during the same time-step, it updates again but at this point, the velocity may have been stopped (due to a collision) and hence is near zero and this is what ends up being reported. :(

    There is more aggressive change that completely solves this issue but it is far too big a change to land in 5.3. That work and more will be in a 2D preview release coming soon. Essentially it's a complete rewrite of the contact processing system and various changes to Box2D. It also solves reporting `exit` conditions when colliders are deleted and pretty much guarantees all contact points will be returned. There's also a non-allocating `GetContacts` API allowing you to retrieve all contacts for a collider or rigidbody. As I say though; far too big a change to land in our 5.3 release which we're trying to get as stable as possible without major changes or features added.

    What I'm doing then is to simply revert the earlier change so that contact-velocity is reported correctly. After all, there are workarounds for the `IsTouching` case but none for the contact-velocity case. Lesser of two evils?

    I hope that explains it well. I'm trying to get this into then next available 5.3 patch release. The next cut-off for that is Monday 21st March and I'm not sure if I'll make that so maybe the subsequent one.

    Again, sorry for the delay but this has been a tricky one to solve.
     
    eirikwahlitema and grosssmutttr like this.
  11. grosssmutttr

    grosssmutttr

    Joined:
    Apr 15, 2014
    Posts:
    168
    Thanks for the detailed info.
    Hope the app users will be patient ;)

    Downloaded Unity 5.3.4f1 today and was really disappointed that the issue still isn't resolved. After reading your detailed explanation I began to think possitive and hope the fix will make it into the next patch release.

    Thanks again!
     
  12. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    The change has been pushed. It's now under review then it'll go to our trunk then be back-ported to 5.4 and, if it can be justified, 5.3. Know that our 5.3 is our stable release so the bar is very, very high for changes there.
     
  13. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    I have just pushed the fix to 5.3.4p2
     
    eirikwahlitema and grosssmutttr like this.
  14. grosssmutttr

    grosssmutttr

    Joined:
    Apr 15, 2014
    Posts:
    168
    @MelvMay Just installed the patch release and it seems as if the calculations are correct now but unfortunately another bug appeared.

    If you take a look at the project (Case 774128) and play level 10 of the "CatapultGame" you'll see that the items which must be shot sometimes suddenly disappear when the slingshot is released!

    So you can't shoot the items...they just disappear on release...
     
  15. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    The fix applied corrects the relative-velocity reporting back to how it was a while back. That may cause behavioural changes on projects that rely on relative-velocity. It should now be correct. This may be the case for the 'bug' in your project.

    You have a large game attached to that case so you are the best person to narrow down what is going wrong; it sounds like you want us to debug your application and that is difficult as it's complex and we're not familiar with it. In many cases we do this but in this case, it's very difficult.

    Could it not be that the constants you're using for relative-velocity are causing the object to be destroyed because they exceed some value now that relative-velocity is correct again? Without knowledge of how your game works, it'd take hours figuring it out. If you can't figure out why your object is deleted, we're going to really struggle! ;)

    Can you not produce a simpler reproduction case of your problem? Also, reusing the same case to report another problem isn't good for tracking in our system, even assuming it's an actual bug on our side.

    For now, I'm going to assume you're trying to narrow it down already but haven't yet figured it out.
     
    Last edited: Apr 9, 2016
  16. grosssmutttr

    grosssmutttr

    Joined:
    Apr 15, 2014
    Posts:
    168
    Thanks for your reply.

    It's not really difficult to see what's going wrong as I described it in the last bug report mail.
    Just go to scene "CatapultGame" and start it. When releasing the projectile it will suddenly disappear.
    I haven't change anything and it worked since Unity 4.6 -5.3.4

    I'll invest more time to narrow this bug down but perhaps you can find some time too.

    Thanks again
     
  17. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    I belive you're seeing the contacts being removed when you change the body type (IsKinematic). Changing the body type is a non-trivial thing in Box2D and removes contacts from the body and recreates them later during the next fixed-update.

    You should have your project starting using Rigidbody2D.simulated = false then setting it to true when you want the Rigidbody2D, its colliders and joints to work.

    In your case, when it starts it's touching the 'Resetter' collider then you change the body-type and it exits. You have a script that deletes the gameobject in that case.

    Perhaps the best way for you to make a quick change is to have the colliders disabled and enable them when you mouse-up.

    I hope this helps you resolve your problem; I spend many hours this Sunday trying to figure out what's happening in your scripts.
     
    Last edited: Apr 10, 2016
  18. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    I wanted to add this separately but adding a trigger collider over the whole game area can become expensive as its a collider that needs to check all AABB of other colliders inside Box2D using its broad-phase tree. It's far less expensive to use colliders that surround the edge of the player area either boxes or even more efficiently, a single EdgeCollider2D. Obviously when using an edge, you need to ensure your objects are not moving super fast or that they use continuous collision detection so they don't pass through an edge.

    This would also stop your issue as when changing the body-type of the projectile, it won't exit the trigger as it's not already in the trigger.

    Note that the issue above only affects static triggers. It might be possible to modify that behaviour that is backwards compatible but I would need to be very careful.

    EDIT: I ended-up taking a look and I believe it's safe to make a change related to the very specific case you're seeing i.e. static triggers against a changing body-type outside of fixed-update however I need to ensure it's completely safe before pushing it to the 5.3 release stream.

    In the meantime, you can easily use better and faster methods of achieving what you're doing anyway.
     
    Last edited: Apr 10, 2016
  19. grosssmutttr

    grosssmutttr

    Joined:
    Apr 15, 2014
    Posts:
    168
    I already thought about the trigger thing when watching the Unity tutorial on how to create an angry bird like slingshot game. A trigger over the whole scene is completely bullshit but when an official tutorial shows the way to go I thought this wouldn't mind :D

    Thanks a lot for your investigations, I'll try to find a good workaround. :);)
     
  20. grosssmutttr

    grosssmutttr

    Joined:
    Apr 15, 2014
    Posts:
    168
    Two additional questions:
    1. Isn't it wrong that it calls the exit method when you set a gameobject with isKinematic=true to false? Because it really doesn't exit? In my case the whole "trigger over the scene" thing is stupid but in other cases this should be working?

    2. In my project the first projectile always disappears and the others not, why? :rolleyes:
     
    Last edited: Apr 10, 2016
  21. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    The problem is that there's a LOT of things in Box2D that cause it to delete contacts and there's nothing that can be done about that, changing body-types is certainly one of them. What has to be done then is wait until the next fixed-update and correlate old recorded contacts with new ones and then update the collision state. In a simple set-up, this wouldn't be too hard but in Unity where pretty much everything is exposed via properties and anything can be changed in the meantime, this logic gets fairly complex and creates a whole bunch of edge-cases.

    Animation, reparenting, changing collider geometry, changing body properties etc all do this and it's easy for edge-cases to appear.

    As I mentioned previously, I've essentially rewritten the contact processing to massively simplify the whole set-up but there's no way that kind of huge change could be backported to 5.3 unfortunately.

    I spent a good proportion of the day figuring out what the edge-case was here and eventually found it and it's super subtle but the good news is that I've identified and fixed it. Seems that problem has always been there and a recent change just made it more likely to show itself.

    Without the fix, the Exit callback always happens but with the fix it never happens. It's already pushed for review then it'll go in the 5.3 patch.

    Regarding the placing of the trigger over the whole scene: Yeah, even official tutorials don't get it right all the time but I think in this case, it's just that it's not as efficient to do that and was probably just a simple method to demonstrate.
     
    Last edited: Apr 11, 2016
  22. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    The update went through test and review really quick. It has already been pushed to 5.3.4p4. With this in-place, your app works without change although I would still recommend using a surrounding edge collider anyway. :)
     
    grosssmutttr likes this.
  23. shochet

    shochet

    Joined:
    Dec 17, 2013
    Posts:
    30
    Can you confirm if this bug was also a problem/fix for 3D collisions?
    I'm seeing Collision objects where the relativeVelocity is zero in Unity 5.3.4f1 (I have not tried the patch releases yet).
     
  24. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    No, this relates to 2D physics only. I don't deal with 3D physics and I'm not aware of a similar problem.
     
    shochet likes this.
  25. Slapworth

    Slapworth

    Joined:
    Aug 11, 2013
    Posts:
    19
    Hi -

    I've started using Collision2D.relativeVelocity and I'm trying to tell whether it's acting weird, or if I don't understand its intended behavior.

    If I get an OnCollision2DEnter() call for a collision between a Rigidbody2D, whose movement is driven solely by physics, and a stationary collider, should I expect that the magnitude of Rigidbody2D.velocity and Collision2D.relativeVelocity to be identical?

    Debug logging says I'm seeing higher relativeVelocity magnitudes, somethings MUCH higher (ranging from +5% to +90%).

    What SHOULD I expect here?

    (I saw this behavior in 5.3.4p1, and it remained in 5.3.4p2.)

    Thanks - Slapworth
     
    Last edited: Apr 14, 2016
  26. robw00t

    robw00t

    Joined:
    Mar 27, 2016
    Posts:
    1
    I was having issues with this as well in 5.3.4f1... inconsistent results where some values were super small & others were huge. Fixed in 5.3.4p3


    Code (CSharp):
    1.     void AddExplosionForce (Rigidbody2D body, float expForce, Vector3 expPosition, float expRadius)
    2.     {
    3.         var dir = (body.transform.position - expPosition);
    4.         float calc = 1 - (dir.magnitude / expRadius);
    5.         if (calc <= 0) {
    6.             calc = 0;      
    7.         }
    8.  
    9.         body.AddForce (dir.normalized * expForce * calc);
    10.     }
    11.  
     
  27. Slapworth

    Slapworth

    Joined:
    Aug 11, 2013
    Posts:
    19
    Thanks for the info, robw00t!

    Unfortunately, I just tried updating the 5.3.4.p3, and I'm still having this issue.

    The player's Rigidbody2D.velocity.magnitude and Collision2D.relativeVelocity.magnitude are still very different in a case when I'd expect them to be identical (colliding with a stationary collider).
     
  28. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    It's possible they can be the same but they are not supposed to be the same. If they were meant to be the same then it'd be pointless having both.

    Rigidbody2D.velocity is obviously the velocity of a single Rigidbody2D and Collision2D.relativeVelocity is the difference in velocity between two Collider2D contacting.

    If you read the Rigidbody2D.velocity in a collision callback, you're reading it after the solver has applied impulses to solve the collision and has modified the velocity. Collision2D.relativeVelocity was the relative-velocity betwen the two contacting bodies at the time of impact i.e. before impulses are applied to solve the collision.

    Remember, you get a collision callback to tell you that the collision has already happened, not that it is about to happen. It should make sense that a collision involves changing the velocity of bodies hence the velocity reported is the after-collision velocity.

    If you are moving along the tangent of a collision without gravity or friction then you can be in contact but the solver applies none or very little force during the collision. In this case, assuming one of the colliders is stationary, then the moving body velocity can be the same as the relative-velocity.
     
  29. Slapworth

    Slapworth

    Joined:
    Aug 11, 2013
    Posts:
    19
    Thanks, MelvMay. This helps a lot.

    I understand the difference in purpose between the two velocity properties; the question was mostly about why they would differ in a situation where I believed they'd be identical -- where one of the contributors to relativeVelocity = Vector2.Zero.

    If I'm following, the cause for a difference here is that the player's velocity is affected at the moment of collision, before the callback?

    To make sure I understand what's going on: If I was caching the Rigidbody2D velocity on each FixedUpdate, would there be a more consistent relationship between that cached velocity and the Collision2D's relativeVelocity (presuming a collision with a stationary object)?
     
  30. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    I've kind of explained it in detail above but I can try to explain it again in different words but I'm not sure what this intent is on trying to make the two independent things the same.

    Relative-velocity is calculated before the callback but that's not accurate. It's calculated prior to Box2D solving the contact during a pre-solve stage (prior to the Box2D solver dealing with the contact). The relative-velocity is calculated by taking the linear-velocity at the contact point of both bodies and subtracting one from the other. Note that the relative-velocity isn't just linear velocity, it takes into account angular velocity as well. Then the solver runs and produces impulse forces to solve the collision contact. It also adjusts velocities for gravity, drag and adds any forces added by the user.

    When the solver has finished and Box2D finishes the update, we then perform the callbacks. You then read the linear velocity and the relative-velocity. They are as I described above.

    If one body is static or (for some other reason) cannot be moved and another body is moving but no rotating and in contact and that body has no gravity or forces applied and the collider in contact has no friction and no restitution (bounce) then there's a chance the body velocity and relative-velocity at its contact point are similar if not the same.

    Another way of describing this is for you to calculate the relative-velocity yourself in the collision callback and note that it may be different than the one calculated by Unity.

    You can use Rigidbody2D.GetPointVelocity on the contact point for both bodies. Then subtract one from the other. This won't necessarily be the same because the linear/angular velocity may have been adjusted by the Box2D solved because of the contact, gravity, friction etc.
     
  31. Slapworth

    Slapworth

    Joined:
    Aug 11, 2013
    Posts:
    19
    Until recently, I had game collision logic driven by Rigidbody2D.velocity, because all of the obstacles involved were stationary. The reason I'm asking so many questions is so I can understand how the new number will affect that logic (which translates impact speed into damage, factoring in the dot-product of relativeVelocity and velocity, and mass).

    In other words, I'm not trying to get relativeVelocity to behave like velocity; I'm trying to understand the relationship between them in the one scenario where they seemed likely to behave identically. They produce fairly radically different magnitudes in a situation where I'd expected them to be similar, and wasn't sure why. And it was throwing off my efforts to transpose the logic to the new input.

    Thanks for the detailed information.
     
  32. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    To be clear, these are not 'new numbers'. Recently, relative-velocity reporting was broken, it's now fixed. It's not something radically new that you need to figure out.

    To save this thread, if you want to continue then I'd be happy to help you however I suggest you message me directly on the forum system so we can continue without getting off-topic.

    ... or can I assume you've now got everything you need from the above information?
     
  33. Slapworth

    Slapworth

    Joined:
    Aug 11, 2013
    Posts:
    19
    I think I'm set. (I meant that the number was "new to my game logic," not new to Unity.)

    If I come up with questions afterwards, I'll keep the thread clear and message you instead. Thanks again!
     
  34. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    Ah okay. Good luck!