Compound Dynamic Body is behaving strange

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

1. 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

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

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

Joined:
Nov 13, 2014
Posts:
220

The colliders in debug mode

5. 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

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

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

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.         }
11.
12.         float3 angularVelocityLocal = math.mul(math.inverse(colliderComponent.MassProperties.MassDistribution.Transform.rot), startAngularVelocity);
14.         {
15.             Linear = startLinearVelocity,
16.             Angular = angularVelocityLocal
17.         });
18.
20.         {
21.             Linear = linearDamping,
22.             Angular = angularDamping
23.         });
24.
25.         if (gravityFactor != 1)
26.         {
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

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

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

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

12. 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

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.