Advanced Collisions
Default settings should handle most of common use-cases for collision detection.
However, if collisions do not seem to be detected appropriately, advanced setting can help you tune your simulation to your needs.
Collision advanced parameters
LMD Max
When two rigidbodys are close and a collision might happen, we use a dedicated solver that will compute minimal distance for every geometrical section of our mesh. For performance reason, we need to search a reasonable region around the object to search for collision. This search region can be defined using the LMD Max parameter, also called Local Minimum Distance. It is the maximal length (in meters) of collision detection around an object during one timestep.
Timestep is in seconds and can be tuned in XdeScene component.
Fast traveling objects
If an object travels more than LMD Max during one timestep, the physics engine might miss a collision with another rigidbody. You can decrease the Timestep or/and increase the LMD Max.
Composite offset
CAD data need to be tessellated into a mesh to be displayed in 3D applications or to compute simulation. This process induces a chord error (or sag) between the nominal CAD data (exact geometry created from mathematical function) and the tessellated mesh (discretized geometry).
The purpose of the composite offset property (measured in meters) from a XdeRigidBody component is to expand the mesh collider in order to compensate this chord error.
Indeed in convex geometries the mesh volume is smaller than CAD one and it can induce issue on simulating precise collision if the chord error is not taken into account.
With the composite offset we create a dilated mesh collider.
Dilation
In the Xde Mesh Collider component of a physicalize object you will find a dilation property :
The dilation of the mesh collider is measured in meters. This parameter has the same purpose of Composite Offset, except this one will be applied to a specific XdeMeshCollider instead of a XdeRigidbody.
Default value is 0.
Sphere/Capsule collider
It is possible to create a collider for an exact sphere by setting a "dilatation" on a mesh that only has one point. Similarly, a capsule collider can be created by dilating a line.
Velocity limiter
In order to guarantee that every collisions will be detected, it is possible to enable a Velocity limiter in the advanced engine parameters of the XdeScene component.
This limiter will ensure that no object will go faster than LMD max during a timestep.
While this is the mode that will provide the most reliable results, it might slow down the rigidbody consequently, which can be undesirable for interactive manipulation.
Configuring materials friction
XDE provides various friction models to help you add more physical realism to your simulation.
To configure a friction model between two objects, you need to assign a contact material to each object and configure the friction model between the two materials.
-
Create a contact material: To create a new material, use the XdeContactRuleSet component located in the [PhysicsManager] inspector tab and click on Create New Material.
-
Configure the friction model between 2 materials: Click at the intersection of the 2 materials in the friction matrix.
Then select the tangential law (No friction, Coulomb, Coulomb-Contensou) and Normal law (Signorini or Compliant).
The Signorini law is in fact not a friction law, but a contact law. This law ensures that when two objects are in contact, the minimal distance between the two object is null, and there is a strictly positive contact force. On the opposite, when there is no contact, the contact force must be null and the minimal distance between the two object is strictly positive. With this law, there is no tangent force, hence no friction.
The Coulomb law states that when a contact occurs, the tangential force norm must be included in a disk whose radius is mu n, where n is the contact force normal value, and mu the friction coefficient. When the tangential forces lies inside the disk, there is no slipping, whereas when the tangential force is on the circle edge, the contact is slipping, and this slipping occurs in the opposite direction of the tangential force. This is the most frequently used law to model friction.
The Coulomb Contensou law is an extension of the Coulomb law to rotational friction. Indeed, with the coulomb law, no friction occurs when an object is rotated around a contact points. This means that if you grab an object with two material points using Coulomb friction, you won’t be able to control the object orientation around the axis formed by the two contact points. The object will freely rotate around this axis.
-
Assign a contact material: To assign a contact material, on your XdeRigidBody's object select the material in the dropdown list Contact Material.
Assign a material to the player's hands.
In the hierarchy, open [Player_1] > Devices > LeftHand, select all of the children and assign in Contact Material "Player", a material you will have created before. Same for RightHand.
Detecting collisions events
Using an XdeContactMonitor component, you can monitor when a collision is happening and use this event in your custom scripts.
You can monitor a specific pair of XdeRigidbody or a pair of XdeLayer. Below a script example to trigger vibration in designated controller when a collision has been detected.
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.XR.OpenXR.Input;
public class Example_collisions : MonoBehaviour
{
public XdeEngine.Core.Collision.Monitoring.XdeContactsMonitor contactMonitor;
//A XdeContactMonitor component will be needed to monitor when the collision is happening
[SerializeField]
InputActionReference m_leftHapticAction;
[SerializeField]
InputActionReference m_rightHapticAction;
[SerializeField]
private float intensity = 0.1f;
[SerializeField]
private float duration = 0.1f;
private void Start()
{
contactMonitor.OnCollisionStart += TriggerHaptic;
}
public void TriggerHaptic()
{
OpenXRInput.SendHapticImpulse(m_leftHapticAction, intensity, duration, UnityEngine.InputSystem.XR.XRController.leftHand);
OpenXRInput.SendHapticImpulse(m_rightHapticAction, intensity, duration , UnityEngine.InputSystem.XR.XRController.rightHand);
}
}
Don't forget to add the "LefHand/Haptic(Input Action Reference)" in Left Haptic Action, same for the right hand. Help yourself with the picture upper.
Using an XdeInterferenceMonitor component, you can monitor when an interference is happening and use this event in your custom scripts.
You can monitor a specific pair of XdeRigidbody or a pair of XdeLayer. Below a script example to play a sound when an interference has been detected.
//A XdeInterferenceMonitor component will be needed to monitor when the interference is happening
public AudioSource audioSource;
public XdeEngine.Core.Collision.Monitoring.XdeInterferencesMonitor interferenceMonitor;
private void Start()
{
interferenceMonitor.OnInterferenceStart += OnBodyInterferenceEnter;
interferenceMonitor.OnInterferenceEnd += OnBodyInterferenceExit;
}
private void OnBodyInterferenceEnter()
{
audioSource.Play();
}
private void OnBodyInterferenceExit()
{
audioSource.Stop();
}
Get Contact Point Positions
INTERACT allows you to easily display collisions with arrows between your physicalized objects. However, it can be interesting in certain cases to obtain the position of these contact points, to create an animation for example.
Here is a script allowing you to put the contact points in a list, and instantiate a cube where the contact have been established.
Add a empty object in the scene and add this script. Furthermore, drop the [PhysicsManager] in the _physcicsManager
required by the script, then adapt the particle System or change the animation as you wish.
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
using XdeEngine.Core.Collision.Monitoring;
public class CollisionContactPoints : MonoBehaviour
{
[SerializeField] private GameObject physicsManager;
[SerializeField] private GameObject cubeInstantiate;
private XdeCollisionGroupsMonitor _collisionMonitor;
private XdeContactsDisplay _contactsDisplay;
private List<Vector2> _listPosition = new List<Vector2>();
private GameObject cube;
bool _supportsInstancing = true;
void Start()
{
_supportsInstancing = SystemInfo.supportsInstancing;
_collisionMonitor = physicsManager.GetComponent<XdeCollisionGroupsMonitor>();
_contactsDisplay = physicsManager.GetComponent<XdeContactsDisplay>();
}
void Update()
{
if (_collisionMonitor == null || !_supportsInstancing)
return;
xde_types.core.group_contact_events contact_points = _collisionMonitor.ContactPoints;
if (contact_points == null)
return;
List<Vector2> list = _listPosition;
list.Clear();
for (int i = 0; i < contact_points.group_pairs.Count; i++)
{
xde_types.core.contact_grouppair gpair = contact_points.group_pairs[i];
for (int j = 0; j < gpair.body_pairs.Count; j++)
{
xde_types.core.contact_bodypair bpair = gpair.body_pairs[j];
for (int k = 0; k < bpair.points.Count; k++)
{
xde_types.core.contact_point point = bpair.points[k];
if (point.gap > -_contactsDisplay.tolerance && !(point.gap > _contactsDisplay.tolerance))
{
list.Add(point.a_i); ///get position
cube = Instantiate(cubeInstantiate, point.a_i, quaternion.identity); //Create a cube where the collision is made
}
}
}
}
}
}