Search Unity

Speed based Contact Point Welding has inconsistent behaviour

Discussion in 'Physics for ECS' started by pverflow, May 23, 2021.

  1. pverflow

    pverflow

    Joined:
    Jun 4, 2019
    Posts:
    7
    Hi,
    We are working on a prototype of a golf like game and decided to test Havok for it and we are actually really happy with how stable the physics are especially compared to PhysX. But we have hit a bump on the road (literally)
    Our issue is that we need high speed precision for a ball to roll on the ground at high and slow speeds.
    So for high speeds we want to enable contact point welding and disable it for slow speeds.

    for this we wrote some code that changes the Custom Tag on the Ball. it looks like follows.
    But we have very persisting instabilities. It does not switch properly even though in the video you can see (on the left side after minute 1:13) that it changes based on speed. What you can see in the latter part of the video that even if it should enable contact welding it completely ignores it there are a lot of ghost hits. Sometimes it enables contact welding and never disables it and that prevents the ball from going into the hole as it floats over the holes. I can make a separate video about this if requested. I can also upload the project.

    Either we did the code wrong or its not possible to switch custom tags at runtime.
    We didn't find a good documentation on this stuff so a lot of trial and error was involved.
    It does not have to be exactly this solution (speed based) as long as we getthe stability at high speeds and accuracy at low speeds.

    We are open to new/other solutions.


    Unity Version: 2021.1.2f1
    Havok Physics 0.6.0 preview.3



    This is the code in question. We also have another script that runs this function below this

    Code (CSharp):
    1.     public static void SetWeldingTags(EntityManager manager)
    2.         {
    3.             foreach (Entity entity in manager.GetAllEntities())
    4.             {
    5.                 if (manager.HasComponent<PhysicsVelocity>(entity))
    6.                 {
    7.                     PhysicsVelocity vel = manager.GetComponentData<PhysicsVelocity>(entity);
    8.                     PhysicsCustomTags customTags = manager.GetComponentData<PhysicsCustomTags>(entity);
    9.                     Debug.Log(
    10.                         $"Entity Velocity: {vel} Entity Index: {entity.Index} Entity Custom Tag: {customTags.Value}");
    11.                     float speed = Vector3.Magnitude(new Vector3(vel.Linear.x, vel.Linear.y, vel.Linear.z));
    12.                     if ( speed > 0.8f )
    13.                     {
    14.                         customTags.Value = 2;
    15.                        
    16.                     }
    17.                     else
    18.                     {
    19.                         customTags.Value = CustomPhysicsBodyTags.Nothing.Value;
    20.                     }
    21.                     manager.SetComponentData(entity, customTags);
    22.                 }
    23.  
    24.                 if (manager.HasComponent<HavokConfiguration>(entity))
    25.                 {
    26.                     HavokConfiguration conf = manager.GetComponentData<HavokConfiguration>(entity);
    27.                     manager.AddComponentData(entity, conf);
    28.                 }
    29.             }
    30.         }

    Code (CSharp):
    1.  
    2. [UpdateBefore(typeof(Unity.Physics.Systems.BuildPhysicsWorld))]
    3. //[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
    4. public class FollowBall : MonoBehaviour
    5. {
    6.     public Entity Ball;
    7.     //public float3 offset = float3.zero;
    8.     public float DifferenceDivider = 512f;
    9.     public LineRenderer LR;
    10.    
    11.     [HideInInspector]
    12.     public Rotation objectRot;
    13.  
    14.     private EntityManager manager;
    15.     // Update is called once per frame
    16.     private void Update()
    17.     {
    18.         EntityObjectTracker.ShootFunction(manager, Ball, LR);
    19.         EntityObjectTracker.SetWeldingTags(manager);
    20.     }
    21.     private void Awake()
    22.     {
    23.         manager = World.DefaultGameObjectInjectionWorld.EntityManager;
    24.     }
    25.     private void LateUpdate()
    26.     {
    27.         if(Ball == null) { return; }
    28.         Translation ballPos = manager.GetComponentData<Translation>(Ball);
    29.         objectRot = manager.GetComponentData<Rotation>(Ball);
    30.  
    31.        
    32.        // Debug.Log(mfd.ForceAmount);
    33.         transform.position = ballPos.Value;
    34.  
    35.     }
    36.  
    37.  
    38.  
    39.  
    40.    
    41. }
    42.  
    upload_2021-5-23_21-57-56.png


    upload_2021-5-23_21-59-44.png
     
  2. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    This looks fun. And that is weird behavior. The welding code is great for the sliding usecase. The rolling usecase can introduce other factors that are not trivial and sometimes have no solution that doesn't just introduce other issues elsewhere. That said, this is a sphere I'm surprised to see things like the ball sticking on the slope of the holes.

    Have you played with the Havok Visual Debugger? If you enable it in the Havok Configuration component on your scene you can start the VDB from the Window>Analysis>Havok Visual Debugger menu. You can then turn on a few viewers e.g. upload_2021-5-24_18-14-47.png
    If you can then record a sample of the problem we can really dig into what is going on.

    Rather than a general welding approach, given that the ball is a 'hero body' it might be worth considering adding logic to tweak the contacts specific to that body i.e. get full control of the process. The ModifyContactJacobians demo and associated script can help there.

    Finally, I'll double check the CustomTag change is definitely being passed through the Havok Physics plugin appropriately.