Search Unity

[Solved] 0g collisions and an obvious violation of Newton's third law of motion!!

Discussion in 'Physics' started by CloudyVR, Jun 6, 2018.

  1. CloudyVR

    CloudyVR

    Joined:
    Mar 26, 2017
    Posts:
    715
    I am working on a space simulator game and require realistic collisions of rigid bodies with various masses.

    I have tried to build a scene where one free floating mass pushes against another free floating mass but the results were less than stunning.

    The piston is simply a child of the of the larger object it is connected to, and both objects have box colliders and a mass of 1000 units.



    When the two bodies impact they do appear to push away from eachother with eual force (which looks correct), however once the collision ends, the bodies appear to stop in place as if they have no added velocity.

    Could someone please help me understand why unity is not applying the proper acceleration/velocity to these bodies?
     
    Last edited: Jun 6, 2018
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    I cannot see your video but at a guess it sounds like the solver is solving an overlap of colliders whose bodies have no velocity.
     
    CloudyVR likes this.
  3. CloudyVR

    CloudyVR

    Joined:
    Mar 26, 2017
    Posts:
    715
    Thanks for pointing that out, and sorry I had it set to private, but should be fixed now.
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    Does the piston have velocity or is it simply being repositioned?
     
  5. CloudyVR

    CloudyVR

    Joined:
    Mar 26, 2017
    Posts:
    715
    its a very simple repositioning script:

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class Piston : MonoBehaviour {
    7.  
    8.     [SerializeField]
    9.     float rate = 1f;
    10.  
    11.     [SerializeField]
    12.     Vector3 dir;
    13.  
    14.     Vector3 initipos;
    15.  
    16.     [SerializeField]
    17.     Transform piston;
    18.     // Use this for initialization
    19.     void Start () {
    20.         initipos = piston.localPosition;
    21.     }
    22.    
    23.     // Update is called once per frame
    24.     void Update () {
    25.         piston.localPosition = initipos + Mathf.Sin ((Mathf.PI ) * Time.time * rate) * dir;
    26.     }
    27. }
    28.  
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    This is simply teleporting the collider instantly from position to position and the solver is simply moving the other colliders out of overlap. There is no energy being passed and the collider, specifically the body it is attached to has no momentum.

    I can get you an example of how to do it soon but I'm not at the computer right this second.
     
    Last edited: Jun 7, 2018
    CloudyVR likes this.
  7. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    So what you want to do is add a Kinematic Rigidbody to the Piston itself and move it with Rigidbody.MovePosition instead which then gives you this: https://gyazo.com/8608cec2960d8b69c51222c6e212cec7

    Here's a simple reproduction of what you had that does exactly this: https://oc.unity3d.com/index.php/s/3ubyRf446NjTrGh

    Note that I kept the example "Piston" script as close to what you had to illustrate the change but you can simplify it by just grabbing the Rigidbody component from the "Piston" GameObject assuming the script is on it. Finally, because the Kinematic Rigidbody effectively has infinite mass, you don't need to configure this anywhere as it is irrelevant.

    Hope this helps.
     
  8. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,512
    MelvMay likes this.
  9. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    Yes thanks, I forgot to mention that!
     
  10. CloudyVR

    CloudyVR

    Joined:
    Mar 26, 2017
    Posts:
    715
    Thank you MelvMay for the hint about programmatically adding momentum, I was able to create a working concept that does look convincing for multiple free floating masses:


    Code (csharp):
    1. using System.Collections;
    2. using UnityEngine;
    3.  
    4. public class ApplyRBVelocity : MonoBehaviour {
    5.     /*simply attach this script to a free floating rigid body which is non kinematic and use gravity is false*/
    6.     Rigidbody rb;
    7.     Vector3 previous = Vector3.zero;
    8.  
    9.     void Awake() {
    10.         rb = GetComponent<Rigidbody> ();
    11.         previous = rb.position;
    12.     }
    13.     void OnCollisionEnter(Collision col) {
    14.         previous = transform.position;
    15.     }
    16.     void OnCollisionStay(Collision col) {
    17.         doOnFixedUpdate = doOnFixedUpdate != null ? doOnFixedUpdate : StartCoroutine (DoOnFixedUpdate());
    18.     }
    19.  
    20.     Coroutine doOnFixedUpdate;
    21.     IEnumerator DoOnFixedUpdate() {
    22.         yield return new WaitForFixedUpdate ();
    23.  
    24.         var velocity = (1f / Time.fixedDeltaTime) * (transform.position - previous) ;
    25.         previous = transform.position;
    26.  
    27.         rb.velocity = velocity;
    28.         //Debug.DrawRay (rb.transform.TransformPoint(rb.centerOfMass), velocity * 10, Color.cyan);
    29.         doOnFixedUpdate = null;
    30.     }
    31. }

    Thanks.
     
    Last edited: Jun 11, 2018