Search Unity

Compound Dynamic Body is behaving strange

Discussion in 'Physics for ECS' started by argibaltzi, Oct 13, 2020.

  1. argibaltzi

    argibaltzi

    Joined:
    Nov 13, 2014
    Posts:
    220
    Hello
    I have issues with compound bodies, they behave very strange compared to simple box colliders

    EXAMPLE:
    Compound Body with 10 box colliders

    if 2 compound colliders are penetrating each other due to some explosion force they they will both start dancing around and rotate like mad....

    Another strange behaviour possibly due to interpolation is that they will jitter on screen when they collide with something

    They also look very unstable once they start colliding with lots of objects, they have trouble coming to a rest and usually because some simple box body is penetrating the compound collider

    Are there any best practices or known issues with compound bodies?

    I can make a video if needed

    Let me know!
    thanks!

    ps i am using havok
     
  2. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    Are things the same with Unity Physics as they are with Havok Physics?
    My guess is that the collisions between 2 interpenetrating compound bodies are trying to resolve themselves but can't.
    A video or simple repro would help.
     
  3. argibaltzi

    argibaltzi

    Joined:
    Nov 13, 2014
    Posts:
    220
    here is a video

    https://i.imgur.com/II6cuEu.mp4

    this compound collider is made of 3 boxes, it loops the movement you see forever....
    below is a static floor and around it some other small box bodies


    Everything is formed dynamically in runtime ( i make new colliders and bodies if needed)
    its a block destruction system

    I am also using inertia tensor on X and Y set to zero

    This is one of the examples that seems wrongs, i have other cases similar to this
     
  4. argibaltzi

    argibaltzi

    Joined:
    Nov 13, 2014
    Posts:
    220

    The colliders in debug mode
     
  5. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    Since you are doing everything dynamically, what are the mass properties initially (before you set the two axis to 0). Seems like this has spherical mass properties, thus the wobble.
     
  6. argibaltzi

    argibaltzi

    Joined:
    Nov 13, 2014
    Posts:
    220
    This is object A with a compound collider and dynamic body (no render object)
    under object A there are several smaller boxes with no collider or bodies obviously as the physics are controlled by the parent

    One thing that is questionable is that the parent has float3(0,0,0) position and i am using the children render/collider position to put them in the right place initially... can that give any problems?


    here is a debug photo in the CreateDynamicBody function before i modify the inertia tensor and create the body
     
  7. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    I've just tried locally what you are doing (setting inverse inertia on a compound to 0 on 2 axis) and everything seems fine. Makes me wonder if something else is wrong here.

    You mentioned that your child boxes of the compound don't have a collider. Is that true? That could be an issue.

    The position stuff should be fine, I don't see a problem with that. Are you making a compound on your own? Maybe share that piece of code as well to verify?
     
  8. argibaltzi

    argibaltzi

    Joined:
    Nov 13, 2014
    Posts:
    220
    Code (CSharp):
    1. public static void CreateDynamicBody(Entity entity, float mass, float3 startAngularVelocity, float3 startLinearVelocity, float gravityFactor, float linearDamping, float angularDamping, ref PhysicsCollider colliderComponent, bool lockTo2DPhysics = true)
    2.     {
    3.         PhysicsMass physicsMass = PhysicsMass.CreateDynamic(colliderComponent.MassProperties, mass);
    4.         if (lockTo2DPhysics)
    5.         {
    6.             physicsMass.InverseInertia[0] = 0;
    7.             physicsMass.InverseInertia[1] = 0;
    8.             physicsMass.InverseInertia[2] = physicsMass.InverseInertia[2];
    9.         }
    10.         EntityManagerRef.AddComponentData(entity, physicsMass);
    11.  
    12.         float3 angularVelocityLocal = math.mul(math.inverse(colliderComponent.MassProperties.MassDistribution.Transform.rot), startAngularVelocity);
    13.         EntityManagerRef.AddComponentData(entity, new PhysicsVelocity()
    14.         {
    15.             Linear = startLinearVelocity,
    16.             Angular = angularVelocityLocal
    17.         });
    18.  
    19.         EntityManagerRef.AddComponentData(entity, new PhysicsDamping()
    20.         {
    21.             Linear = linearDamping,
    22.             Angular = angularDamping
    23.         });
    24.  
    25.         if (gravityFactor != 1)
    26.         {
    27.             EntityManagerRef.AddComponentData(entity, new PhysicsGravityFactor()
    28.             {
    29.                 Value = gravityFactor
    30.             });
    31.         }
    32.     }
    Code (CSharp):
    1.    List<int4> colliderBoxes = BuildColliderAssistant.BuildOptimizesColliders(newIndexListFromRootInstance, newInstance.MeshBoxes, newInstance.Width, newInstance.Height);
    2.         NativeArray<Unity.Physics.CompoundCollider.ColliderBlobInstance> Blobs = new NativeArray<Unity.Physics.CompoundCollider.ColliderBlobInstance>(colliderBoxes.Count, Allocator.Temp);
    3.  
    4.         float massCalculator = 0;
    5.         for (int i = 0; i < colliderBoxes.Count; ++i)
    6.         {
    7.             Vector3 outColliderPosition, outColliderSize;
    8.             PixelMeshData.CreatePositionForBox(colliderBoxes[i], out outColliderPosition, out outColliderSize);
    9.             outColliderSize.z = PixelMeshData.GetPixelZSize(PixelCollisionType.Compound);
    10.             outColliderPosition.z = 0;
    11.  
    12.             BlobAssetReference<Unity.Physics.Collider> boxCollider = PhysicsAssistant.CreateBoxCollider(float3.zero, outColliderSize, 0, newInstance.PhysicsMaterialTemplate);
    13.  
    14.             Blobs[i] = new Unity.Physics.CompoundCollider.ColliderBlobInstance()
    15.             {
    16.                 Collider = boxCollider,
    17.                 CompoundFromChild = new Unity.Mathematics.RigidTransform(
    18.                   Quaternion.identity,
    19.                   outColliderPosition)
    20.             };
    21.  
    22.             massCalculator += colliderBoxes[i].w * colliderBoxes[i].z;
    23.         }
    24.  
    25.         massCalculator /= PixelMeshData.MassVolume;
    26.  
    27.         BlobAssetReference<Unity.Physics.Collider> MyCollider = Unity.Physics.CompoundCollider.Create(Blobs);
    28.         Blobs.Dispose();
    29.  
    30.         PhysicsCollider physicsCollider;
    31.         PhysicsAssistant.CreateCollider(ref newInstance.EntityRef, ref MyCollider, out physicsCollider);
    32.  
    33.         PhysicsVelocity existingVelocity = new PhysicsVelocity() { Angular = newInstance.PhysicsBodyTemplate.InitialAngularVelocity, Linear = newInstance.PhysicsBodyTemplate.InitialLinearVelocity };
    34.         if (rootInstance.IsStaticOrDynamic == BlockPhysicsType.Dynamic)
    35.         {
    36.             existingVelocity = Game.Instance.EntityWorld.EntityManager.GetComponentData<PhysicsVelocity>(rootInstance.EntityRef);
    37.         }
    38.  
    39.         PhysicsAssistant.CreateDynamicBody(newInstance.EntityRef, massCalculator,
    40.            existingVelocity.Angular,
    41.             existingVelocity.Linear,
    42.             newInstance.PhysicsBodyTemplate.GravityFactor,
    43.             newInstance.PhysicsBodyTemplate.LinearDamping,
    44.             newInstance.PhysicsBodyTemplate.AngularDamping,
    45.             ref physicsCollider,
    46.             true);
    the create body function, which is similar to the samples and the code i use to create the collider and dynamic body
     
    Last edited: Oct 27, 2020
  9. argibaltzi

    argibaltzi

    Joined:
    Nov 13, 2014
    Posts:
    220

    in my video, the entity that rotates weird, here is a snapshot from the entity debug, the translation/rotation/localtoparent/physicsvelocity data change every frame because of the rotation bug
     
  10. argibaltzi

    argibaltzi

    Joined:
    Nov 13, 2014
    Posts:
    220
    I just noticed, the entity that behaves strange... i changed its compound collider during the game but i did not update anything in the dynamic body... is that wrong?

    What happens is....
    Block A is destroyed in half, B and C
    B is completely new dynamic body and physics collider
    C is actually Entity A but with an updated collider (i remake the compound collider)

    Code (CSharp):
    1. PhysicsCollider physicsCollider = new PhysicsCollider() { Value = MyCollider };
    2.                 EntityManagerRef.SetComponentData<PhysicsCollider>(existingInstanceEntity, physicsCollider);
     
  11. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    Does the same strange behavior happen when you don't change stuff at runtime like this?
     
  12. argibaltzi

    argibaltzi

    Joined:
    Nov 13, 2014
    Posts:
    220
    its not as stable as in with normal inertia tensor.... but more or less is ok

    I fixed it!!! updating just the compound collider is not enough

    Code (CSharp):
    1.   public static void UpdateColliderAndPhysicsMass(Entity entity, ref BlobAssetReference<Collider> collider, float mass, bool lockTo2DPhysics)
    2.     {
    3.         PhysicsCollider physicsCollider = new PhysicsCollider() { Value = collider };
    4.         EntityManagerRef.SetComponentData<PhysicsCollider>(entity, physicsCollider);
    5.  
    6.         PhysicsMass physicsMass = PhysicsMass.CreateDynamic(physicsCollider.MassProperties, mass);
    7.         if (lockTo2DPhysics)
    8.         {
    9.             physicsMass.InverseInertia[0] = 0;
    10.             physicsMass.InverseInertia[1] = 0;
    11.             physicsMass.InverseInertia[2] = physicsMass.InverseInertia[2];
    12.         }
    13.  
    14.         EntityManagerRef.SetComponentData(entity, physicsMass);
    15.     }
    I call this function now to update both collider and the physicsmass!
     
  13. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    Oh yeah, if you change the collider mass props need to be recalculated. Glad you solved it!
     
    argibaltzi likes this.