Search Unity

About collisions failing on high speed

Discussion in 'Physics' started by Lockstep, May 29, 2013.

Thread Status:
Not open for further replies.
  1. Lockstep

    Lockstep

    Joined:
    Sep 14, 2012
    Posts:
    18
    It is well known, that the collision between to game objects can fail if one of them is moving at a high speed. I was wondering, which properties affect this behaviour and when does one need to start to worry about countermeasures. Thus I've run some tests and I want to share the results with you.

    The setup:
    The test unit is essentially a script (CollisionTest.cs) which instantiates fast moving projectiles and a target which reports a successful collision. It has properties for:
    • projectile speed as float
    • projectile size as float
    • target scale as Vector3
    • CollisionDetectionMethod
    • number of repeats as int
    The projectile is a simple sphere collider with a rigidbody component attatched. It has gravity and isKinematic turned off and is on a layer which ignores collision among itself. The start position is randomized a bit. This is neccessary since the success of the collision basically depends on the position of the two colliders during each frame. For reference: The projectiles fly only in z-direction.
    The target is simple cube collider. It has a script (Target.cs) attatched which increases a counter on the corresponding CollisionTest.cs.
    After the set amount of shots have been fired, CollisionTest calculates the ratio of hits and total projectiles.
    During the test the frame rate was between 10 and 20 fps.

    Results:
    What does not affect the behaviour (no plot here since horizontal lines are boring):
    1.The global scale.
    Scaling up the speed of the projectile and the scale of both the projectile and the target does not make a difference.
    2.xy-scale of the target.
    The chance for a successful collision only depends on the size of the target in movement direction.
    3.CollisionDetectionMode
    This one is quite disappointing. However in this case the target is a simple cube collider. It could still make a difference for mesh colliders.

    What does affect the behaviour:
    1.The speed.
    Thats the point of this thread, isn't it? In these plots the projectile size is 1 the target size is (1,1,1).The test is repeated 1500 times:



    In the second image you can see, that the collision is save until a speed of 100.



    2.The z-size of the target
    In this plot the projectile size is 1 and its speed is 500. The test is repeated 1500 times:


    3.The size of the projectile
    The same game as for the target z-size (but with a better choice for the x-axis). Target z-size is 1 the speed is 500. The test is repeated 1500 times:



    Conclusion:
    When the speed of an object is large agains its size and its collision partners size, then a collision can fail. Deducing from the plots, I'd say, that as long as the sum of the sizes the collision partners in movement direction times 50 is greater than the speed of the moving partner the collision is save.


    (size_projectile + size_target) * 50 > speed​


    Keep this in mind if you are dealing with high velocities.

    In addition:
    I've run the speed test again for a mesh collider. It has has bounds of (1,1,1), which means it fits tightly into the previous cube target. Due to the nature of mesh colliders, the frame rate dropped below 5FPS during the test.
    Projectile and Targetsize are again 1.




    I was pretty much surprised about this outcome. The discrete collision started to fail a lot sooner. Even less than half of the cube colliders save speed already led to failed collisions. Continuous detection on the other hand always(!) detected the collision correctly. I've rund this test for a maximum speed of 20000 and still the detection never failed.
     

    Attached Files:

    Last edited: Jun 1, 2013
  2. Lockstep

    Lockstep

    Joined:
    Sep 14, 2012
    Posts:
    18
    Source code:

    CollisionTest.cs

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class CollisionTest : MonoBehaviour {
    5.     public float speed;
    6.     public float projectileSize;
    7.     public Vector3 targetScale;
    8.     public int shots = 10000;
    9.     public CollisionDetectionMode detectMethod;
    10.    
    11.     public Transform projectile;
    12.     private Transform target;
    13.     private Transform spawn;
    14.     private int hitCounter = 0;
    15.     private int shotCounter = 0;
    16.     private bool finished = false;
    17.     private bool displayed = false;
    18.     private float finishTime = 0f;
    19.     private string ratio = "";
    20.     // Use this for initialization
    21.     void Start () {
    22.         target = transform.FindChild("Target");
    23.         target.localScale = targetScale;
    24.         target.localPosition = Vector3.forward * (projectileSize + targetScale.z +speed +1);
    25.         spawn = transform.FindChild("BulletSpawn");
    26.     }
    27.    
    28.     // Update is called once per frame
    29.     void Update () {
    30.         if(shotCounter < shots){
    31.             SpawnBullet();
    32.             shotCounter++;
    33.         } else if (!finished){
    34.             finishTime = Time.time;
    35.             finished = true;
    36.         } else if(finishTime + 2f < Time.time  !displayed){
    37.             float f_ratio = (hitCounter + 0.0f)/shots;
    38.             ratio = f_ratio.ToString();
    39.             Debug.Log("HitRatio: " + ratio  +"\nSpeed: " + speed + "\nDetection method: " + detectMethod.ToString() + "\nProjectile size: " + projectileSize + "\nTarget scale: " + targetScale);
    40.             displayed = true;
    41.         }
    42.     }
    43.     void SpawnBullet(){
    44.         Transform bull = (Transform) Transform.Instantiate(projectile, spawn.position +Vector3.forward * Random.value * speed * 0.1f, Quaternion.identity);
    45.         bull.rigidbody.velocity = Vector3.forward * speed;
    46.         bull.rigidbody.collisionDetectionMode = detectMethod;
    47.         bull.localScale = Vector3.one * projectileSize;
    48.         Destroy(bull.gameObject, 2f);
    49.     }
    50.     public void Detected(){
    51.         hitCounter++;
    52.     }
    53.     public bool Displayed{
    54.         get{return displayed;} 
    55.     }
    56.     public string Ratio{
    57.         get{return ratio;} 
    58.     }
    59. }
    Target.cs:
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class Target : MonoBehaviour {
    6.     private CollisionTest test;
    7.     void Start(){
    8.         test = transform.parent.GetComponent<CollisionTest>();
    9.     }
    10.    
    11.     void OnCollisionEnter(Collision other){
    12.         test.Detected();
    13.         Destroy(other.gameObject);
    14.     }
    15.    
    16. }
    Multitest.cs

    Code (csharp):
    1. using UnityEngine;
    2. using System;
    3. using System.IO;
    4. using System.Collections;
    5. using System.Collections.Generic;
    6.  
    7. public enum testMethod{speed, projectileSize, TargetSize, doubleSize, scale, deformed}
    8.  
    9. public class Multitest : MonoBehaviour {
    10.     public int sampleLength;
    11.     public testMethod method;
    12.    
    13.     public int shots;
    14.     public float startSpeed;
    15.     public float startProjectileSize;
    16.     public Vector3 startTargetSize;
    17.    
    18.     public string filename = "filename.txt";
    19.     public Transform testPrefab;
    20.     private List<CollisionTest> discreteList;
    21.     private List<CollisionTest> contList;
    22.     private List<CollisionTest> contDynList;
    23.     private bool hasWritten = false;
    24.     // Use this for initialization
    25.     void Start () {
    26.         discreteList = new List<CollisionTest>();
    27.         contList = new List<CollisionTest>();
    28.         contDynList = new List<CollisionTest>();
    29.         switch(method){
    30.         case testMethod.speed:
    31.             MultiCreateSpeed();
    32.             break;
    33.         case testMethod.projectileSize:
    34.             MultiCreatePSize();
    35.             break;
    36.         case testMethod.TargetSize:
    37.             MultiCreateTSize();
    38.             break;
    39.         case testMethod.doubleSize:
    40.             MultiCreateAllSize();
    41.             break;
    42.         case testMethod.scale:
    43.             MultiCreateScale();
    44.             break;
    45.         case testMethod.deformed:
    46.             MultiCreateDeform();
    47.             break;
    48.         }
    49.     }
    50.     void Update(){
    51.         if(!hasWritten  CheckReady()){
    52.            
    53.         switch(method){
    54.         case testMethod.speed:
    55.             CreateFileSpeed();
    56.             break;
    57.         case testMethod.projectileSize:
    58.             CreateFileProjectileSize();
    59.             break;
    60.         case testMethod.TargetSize:
    61.             CreateFileTargetSize();
    62.             break;
    63.         case testMethod.doubleSize:
    64.             CreateFileSizeRatio();
    65.             break;
    66.         case testMethod.scale:
    67.             CreateFileSizeScale();
    68.             break;
    69.         case testMethod.deformed:
    70.             CreateFileDeform();
    71.             break;
    72.         }
    73.            
    74.             hasWritten = true; 
    75.         }
    76.     }
    77.     bool CheckReady(){
    78.         foreach(CollisionTest t in discreteList){
    79.             if(t.Displayed == false)
    80.                 return false;
    81.         }
    82.         foreach(CollisionTest t in contList)
    83.             if(t.Displayed == false)
    84.                 return false;
    85.         foreach(CollisionTest t in contDynList)
    86.             if(t.Displayed == false)
    87.                 return false;
    88.         return true;
    89.     }
    90.     void CreateTest(float s, float psize, Vector3 tscale, CollisionDetectionMode metho, Vector3 pos){
    91.         Transform testTransform = (Transform) Transform.Instantiate(testPrefab, pos , Quaternion.identity);
    92.         CollisionTest testScript = testTransform.GetComponent<CollisionTest>();
    93.         testScript.speed = s;
    94.         testScript.projectileSize = psize;
    95.         testScript.targetScale = tscale;
    96.         testScript.shots = shots;
    97.         testScript.detectMethod = metho;
    98.         switch (metho){
    99.         case CollisionDetectionMode.Discrete:
    100.             discreteList.Add(testScript);
    101.             break;
    102.         case CollisionDetectionMode.Continuous:
    103.             contList.Add(testScript);
    104.             break;
    105.         case CollisionDetectionMode.ContinuousDynamic:
    106.             contDynList.Add(testScript);
    107.             break;
    108.         }
    109.     }
    110.     void MultiCreateSpeed(){
    111.         for(int i = 0; i < sampleLength; i++){
    112.             CreateTest(startSpeed * (i+1), startProjectileSize, startTargetSize, CollisionDetectionMode.Discrete, new Vector3(Mathf.Max(startTargetSize.x , startProjectileSize) * i * 1.2f, 0,0));
    113.             CreateTest(startSpeed * (i+1), startProjectileSize, startTargetSize, CollisionDetectionMode.Continuous, new Vector3(Mathf.Max(startTargetSize.x , startProjectileSize) * i * 1.2f, Mathf.Max(startTargetSize.x , startProjectileSize) *  1.2f,0));
    114.             CreateTest(startSpeed * (i+1), startProjectileSize, startTargetSize, CollisionDetectionMode.ContinuousDynamic, new Vector3(Mathf.Max(startTargetSize.x , startProjectileSize) * i * 1.2f, Mathf.Max(startTargetSize.x , startProjectileSize) * 2 * 1.2f,0));
    115.         }
    116.     }
    117.     void MultiCreatePSize(){
    118.         for(int i = 0; i < sampleLength; i++){
    119.             CreateTest(startSpeed , startProjectileSize* (i+1), startTargetSize, CollisionDetectionMode.Discrete, new Vector3(Mathf.Max(startTargetSize.x , startProjectileSize* i) * i * 1.2f+1, 0,0));
    120.             CreateTest(startSpeed , startProjectileSize* (i+1), startTargetSize, CollisionDetectionMode.Continuous, new Vector3(Mathf.Max(startTargetSize.x , startProjectileSize* i) * i * 1.2f, Mathf.Max(startTargetSize.x , startProjectileSize*sampleLength) *  1.2f,0));
    121.             CreateTest(startSpeed , startProjectileSize* (i+1), startTargetSize, CollisionDetectionMode.ContinuousDynamic, new Vector3(Mathf.Max(startTargetSize.x , startProjectileSize* i) * i * 1.2f, Mathf.Max(startTargetSize.x , startProjectileSize*sampleLength) * 2 * 1.2f,0));
    122.         }
    123.     }
    124.     void MultiCreateTSize(){
    125.         for(int i = 0; i < sampleLength; i++){
    126.             CreateTest(startSpeed , startProjectileSize, startTargetSize* (i+1), CollisionDetectionMode.Discrete, new Vector3(Mathf.Max(startTargetSize.x * i , startProjectileSize) * i * 2.2f, 0,0));
    127.             CreateTest(startSpeed , startProjectileSize, startTargetSize* (i+1), CollisionDetectionMode.Continuous, new Vector3(Mathf.Max(startTargetSize.x *i, startProjectileSize) * i * 2.2f, Mathf.Max(startTargetSize.x *sampleLength, startProjectileSize) *  1.2f,0));
    128.             CreateTest(startSpeed , startProjectileSize, startTargetSize* (i+1), CollisionDetectionMode.ContinuousDynamic, new Vector3(Mathf.Max(startTargetSize.x *i, startProjectileSize) * i * 2.2f, Mathf.Max(startTargetSize.x *sampleLength, startProjectileSize) * 2 * 1.2f,0));
    129.         }
    130.     }
    131.     void MultiCreateAllSize(){
    132.         for(int i = 0; i < sampleLength; i++){
    133.             CreateTest(startSpeed , startProjectileSize*(i+1), startTargetSize* (i+1), CollisionDetectionMode.Discrete, new Vector3(Mathf.Max(startTargetSize.x * i , startProjectileSize*i) * i * 2.2f+2, 0,0));
    134.             CreateTest(startSpeed , startProjectileSize*(i+1), startTargetSize* (i+1), CollisionDetectionMode.Continuous, new Vector3(Mathf.Max(startTargetSize.x *i, startProjectileSize*i) * i * 2.2f+2, Mathf.Max(startTargetSize.x*sampleLength , startProjectileSize*sampleLength) *  1.2f,0));
    135.             CreateTest(startSpeed , startProjectileSize*(i+1), startTargetSize* (i+1), CollisionDetectionMode.ContinuousDynamic, new Vector3(Mathf.Max(startTargetSize.x *i, startProjectileSize*i) * i * 2.2f+2, Mathf.Max(startTargetSize.x*sampleLength , startProjectileSize*sampleLength) * 2 * 1.2f,0));
    136.         }
    137.     }
    138.     void MultiCreateScale(){
    139.         for(int i = 0; i < sampleLength; i++){
    140.             CreateTest(startSpeed * (i+1), startProjectileSize*(i+1), startTargetSize* (i+1), CollisionDetectionMode.Discrete, new Vector3(Mathf.Max(startTargetSize.x * i , startProjectileSize*i) * i * 1.2f, 0,0));
    141.             CreateTest(startSpeed * (i+1), startProjectileSize*(i+1), startTargetSize* (i+1), CollisionDetectionMode.Continuous, new Vector3(Mathf.Max(startTargetSize.x *i, startProjectileSize*i) * i * 1.2f, Mathf.Max(startTargetSize.x*sampleLength , startProjectileSize*sampleLength) *  1.2f,0));
    142.             CreateTest(startSpeed * (i+1), startProjectileSize*(i+1), startTargetSize* (i+1), CollisionDetectionMode.ContinuousDynamic, new Vector3(Mathf.Max(startTargetSize.x *i, startProjectileSize*i) * i * 1.2f, Mathf.Max(startTargetSize.x*sampleLength , startProjectileSize*sampleLength) * 2 * 1.2f,0));
    143.         }
    144.     }
    145.     void MultiCreateDeform(){
    146.         for(int i = 0; i < sampleLength; i++){
    147.             CreateTest(startSpeed , startProjectileSize, startTargetSize +(Vector3.up *startTargetSize.y + Vector3.right * startTargetSize.x)  * i, CollisionDetectionMode.Discrete, new Vector3(Mathf.Max(startTargetSize.x + i , startProjectileSize) * i * 1.2f, 0,0));
    148.             CreateTest(startSpeed , startProjectileSize, startTargetSize+(Vector3.up *startTargetSize.y + Vector3.right * startTargetSize.x) * i, CollisionDetectionMode.Continuous, new Vector3(Mathf.Max(startTargetSize.x +i, startProjectileSize) * i * 1.2f, Mathf.Max(startTargetSize.x*sampleLength , startProjectileSize*sampleLength) *  1.2f,0));
    149.             CreateTest(startSpeed , startProjectileSize, startTargetSize+(Vector3.up *startTargetSize.y + Vector3.right * startTargetSize.x) * i, CollisionDetectionMode.ContinuousDynamic, new Vector3(Mathf.Max(startTargetSize.x +i, startProjectileSize) * i * 1.2f, Mathf.Max(startTargetSize.x*sampleLength , startProjectileSize*sampleLength) * 2 * 1.2f,0));
    150.         }
    151.     }
    152.     void CreateFileSpeed(){
    153.         if(File.Exists(filename))
    154.         {
    155.             Debug.Log(filename+ " already exists");
    156.             return;
    157.         }
    158.         StreamWriter sw = File.CreateText(filename);
    159.         sw.WriteLine("#CollisionTest Data");
    160.         sw.WriteLine("#####################");
    161.         sw.WriteLine("#Ratio over speed");
    162.         sw.WriteLine("#Testlengt: " +shots);
    163.         sw.WriteLine("#Projectile size: " + startProjectileSize);
    164.         sw.WriteLine("#Target size: " + startTargetSize);
    165.         for(int i = 0; i < sampleLength; i++){
    166.             sw.WriteLine((startSpeed * (i+1))+"\t"+discreteList[i].Ratio+"\t"+contList[i].Ratio+"\t"+contDynList[i].Ratio);
    167.         }
    168.         sw.Close();
    169.     }
    170.     void CreateFileProjectileSize(){
    171.         if(File.Exists(filename))
    172.         {
    173.             Debug.Log(filename+ " already exists");
    174.             return;
    175.         }
    176.         StreamWriter sw = File.CreateText(filename);
    177.         sw.WriteLine("#CollisionTest Data");
    178.         sw.WriteLine("#####################");
    179.         sw.WriteLine("#Ratio over projectile size");
    180.         sw.WriteLine("#Testlengt: " +shots);
    181.         sw.WriteLine("#speed: " + startSpeed);
    182.         sw.WriteLine("#Target size: " + startTargetSize);
    183.         for(int i = 0; i < sampleLength; i++){
    184.             sw.WriteLine((startProjectileSize * (i+1))+"\t"+discreteList[i].Ratio+"\t"+contList[i].Ratio+"\t"+contDynList[i].Ratio);
    185.         }
    186.         sw.Close();
    187.     }
    188.     void CreateFileTargetSize(){
    189.         if(File.Exists(filename))
    190.         {
    191.             Debug.Log(filename+ " already exists");
    192.             return;
    193.         }
    194.         StreamWriter sw = File.CreateText(filename);
    195.         sw.WriteLine("#CollisionTest Data");
    196.         sw.WriteLine("#####################");
    197.         sw.WriteLine("#Ratio over target size");
    198.         sw.WriteLine("#Testlengt: " +shots);
    199.         sw.WriteLine("#speed: " + startSpeed);
    200.         sw.WriteLine("#Projectile size: " + startProjectileSize);
    201.         for(int i = 0; i < sampleLength; i++){
    202.             sw.WriteLine((startTargetSize.z * (i+1))+"\t"+discreteList[i].Ratio+"\t"+contList[i].Ratio+"\t"+contDynList[i].Ratio);
    203.         }
    204.         sw.Close();
    205.     }
    206.     void CreateFileSizeRatio(){
    207.         if(File.Exists(filename))
    208.         {
    209.             Debug.Log(filename+ " already exists");
    210.             return;
    211.         }
    212.         StreamWriter sw = File.CreateText(filename);
    213.         sw.WriteLine("#CollisionTest Data");
    214.         sw.WriteLine("#####################");
    215.         sw.WriteLine("#Ratio over size ratio");
    216.         sw.WriteLine("#Testlengt: " +shots);
    217.         sw.WriteLine("#speed: " + startSpeed);
    218.         for(int i = 0; i < sampleLength; i++){
    219.             sw.WriteLine((startProjectileSize / startTargetSize.z * i)+"\t"+discreteList[i].Ratio+"\t"+contList[i].Ratio+"\t"+contDynList[i].Ratio);
    220.         }
    221.         sw.Close();
    222.     }
    223.     void CreateFileSizeScale(){
    224.         if(File.Exists(filename))
    225.         {
    226.             Debug.Log(filename+ " already exists");
    227.             return;
    228.         }
    229.         StreamWriter sw = File.CreateText(filename);
    230.         sw.WriteLine("#CollisionTest Data");
    231.         sw.WriteLine("#####################");
    232.         sw.WriteLine("#Ratio over scale");
    233.         sw.WriteLine("#Testlengt: " +shots);
    234.         sw.WriteLine("#speed: " + startSpeed);
    235.         for(int i = 0; i < sampleLength; i++){
    236.             sw.WriteLine((i)+"\t"+discreteList[i].Ratio+"\t"+contList[i].Ratio+"\t"+contDynList[i].Ratio);
    237.         }
    238.         sw.Close();
    239.     }
    240.     void CreateFileDeform(){
    241.         if(File.Exists(filename))
    242.         {
    243.             Debug.Log(filename+ " already exists");
    244.             return;
    245.         }
    246.         StreamWriter sw = File.CreateText(filename);
    247.         sw.WriteLine("#CollisionTest Data");
    248.         sw.WriteLine("#####################");
    249.         sw.WriteLine("#Ratio over xy length");
    250.         sw.WriteLine("#Testlengt: " +shots);
    251.         sw.WriteLine("#speed: " + startSpeed);
    252.         sw.WriteLine("#z size: " +startTargetSize.z);
    253.         for(int i = 0; i < sampleLength; i++){
    254.             sw.WriteLine((i *startTargetSize.x)+"\t"+discreteList[i].Ratio+"\t"+contList[i].Ratio+"\t"+contDynList[i].Ratio);
    255.         }
    256.         sw.Close();
    257.     }
    258. }
    259.  
     
    Last edited: May 29, 2013
  3. Nanity

    Nanity

    Joined:
    Jul 6, 2012
    Posts:
    148
    You are my hero, I felt somehow stupid when the elevator let drop my char through the bottom at a certain velocity. From your stats I notice that there's hardly a difference between discrete and continous detection.... frustrating ;/
     
  4. xCyborg

    xCyborg

    Joined:
    Oct 4, 2010
    Posts:
    523
    Wow thanks for all your efforts and for the formula:)
    I wonder why the ratio falls so horribly just after 100 (unit per second I suppose).
    On a second note, I'm even more surprised that the CollisionDetectionType doesn't affect the ratio much, I was expecting Continuous to improve that ratio, so no more Continuous.
    At least making the target or projectile thicker helps a bit.
    Bottom line is: an update to the Physics department is Urgent!!
     
  5. MooseMouse

    MooseMouse

    Joined:
    Sep 14, 2011
    Posts:
    515
    Thank you for researching this! Failed collisions are a huge problem in my current game, forcing me to change the design of levels (size and speed of objects). I also am disappointed that CollisionDetectionMode doesn't seem to do anything. That has been my experience, but I also wondered if I was setting things up incorrectly.

    I am using the DontGoThroughThings script, which helps but does not completely cure the problem when speed vs. size is too extreme. Would be great to have an airtight solution, if possible.
     
  6. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    1,513
    Unsurprising that this fails for both Continuous and ContinuousDynamic since from the docs,

    So for both collision modes the target would need a MeshCollider applied in order for them to work. Meaning all you've done is test Discrete collision three times ;)

    In terms of your conclusions, its always been that discrete collision can only detect a collision if the two objects overlap for the specific fixed time frame. So the max speed will be related to projectile length, target length and the fixed Timestep (i.e physics rate).
     
    Last edited: May 30, 2013
  7. MooseMouse

    MooseMouse

    Joined:
    Sep 14, 2011
    Posts:
    515
    Wow, that is good info. I never picked up on that from the docs. I wonder why they didn't make it so Continuous and ContinuousDynamic work with box, sphere, and capsule colliders?
     
    Last edited: May 30, 2013
  8. Forge Vault

    Forge Vault

    Joined:
    Feb 18, 2012
    Posts:
    214
    Correct me if I'm wrong but isn't speed relevant to the scale in which you are working? In a world built in small scale the speed required to cover a distance equal to a world built in large scale is much smaller. So theoretically, if you reduce the scale of your world you should have a lower speed requirement thus resolving any collision issues with speed.

    It's just a theory I didn't test...
     
  9. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    1,513
    Yeah I wondered that myself and had to re-read the docs several times to make sure they really meant MeshColliders ( not i've not actually tested this stuff), but I figured if it worked for any then they would have just said 'static mesh geometry is any collider which ..'

    Still its odd as I assume continuous just means they are doing sweep collision of the 'projectile' starting at time t and ending at t1, in which case I would have thought doing it against box, sphere and even capsule would be easier than a mesh hull as it should be possible using the standard equations for creating such shapes. Though its been many years since I looked at coding anything with collisions, so maybe i'm missing something and its just easier to do it against a mesh.

    Though its another case where the docs could be a bit more explicit, perhaps bolding the same segment as I did in the quote as it would be so easy to miss or simply read MeshColllider as Collider.

    Nope as its all relative. If you reduce the scale of your world, your projectile will appear to travel faster, unless you reduce its speed by the same scale. If you reduce both then you've not changed anything.

    For discrete collisions you either have to reduce the speed of the travelling object or increase the fixedFrameRate of the physics simulation (i.e have smaller physics timesteps so the objects move smaller distances each step), both will increase the chances of the two objects overlapping at a specific time and thus causing a collision to be detected.
     
    Last edited: May 30, 2013
  10. ZJP

    ZJP

    Joined:
    Jan 22, 2010
    Posts:
    2,646
  11. Reisuj

    Reisuj

    Joined:
    Aug 13, 2012
    Posts:
    16
    I'm probably way off on this question. But could this also be related to why box and sphere colliders dropped in a stack will bounce even when bounciness is set to 0 and with a high threshhold?
     
  12. xCyborg

    xCyborg

    Joined:
    Oct 4, 2010
    Posts:
    523
    If Continuous mode worked only on MeshColliders, the CollisionDetectionMode drop list from the RigidBody attached to a BoxCollider woudn't show Countinuous.
    I think they mean any collider, proof: in other places Dynamic geometry is any collider with a RigidBody, you woudn't thin that UT would be able to implement CCM on a complext mesh collider but fail to do so on a simple box collider:/
    Let's face it, there's room for improvement for physx, there's failing collisions on a side and performance regression if you increase fixedTime on the other side, choose your poison:)
     
  13. Kryger

    Kryger

    Joined:
    Oct 3, 2012
    Posts:
    169
    Thank you for your research and most of all for sharing. I was going crazy with these collision problems.
     
  14. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    1,513
    Nope, because you are mixing up static vs dynamic target objects. ;)

    Static geometry must have a MeshCollider attached to it for a rigidbody using Continuous or ContinuousDynamic method to collide with it consistently and robustly.

    If both objects have rigidbody applied, but one of them doesn't move, then yes, you should be able to set both to ContinuousDynamic or the 'static' rigidbody to Continuous and dynamic (projectile) rigidbody to ContinuousDynamic and all collisions should be detected.



    I actually took the time to confirm this now using the OP's code, though I wish they had simply provided a Unity package as it took way too long to figure out how to set up a scene, create prefabs,, attach scripts to scene or prefab objects etc. I think I've got it all set up correctly, but can't be 100% sure.

    I've attached a package of my version below.

    There is a single scene and the multiTest script is attached to the maincamera. Here you can drag either the 'Test_BoxCollider' or 'Test_MeshCollider' prefabs onto the 'Test Prefab' property of the 'MultiTest' script, then run the test and view the results in the console. I've added a bool to enable/disable writing the results to file as I didn't need it.

    In running the tests with high speed values, the 'Test_BoxCollider' version detects no collisions for any collision method. However when swapped with the 'Test_MeshCollider' prefab, it still doesn't detect any collisions using 'discrete' method, but detects every collision for the 'Continuous' 'ContinuousDynamic' methods.

    So I'd say that's pretty conclusive proof, but please feel free to double check my findings.



    Edit:
    Confirmed rigidbody to rigidbody tests, with a 'static' cube target using a box collider and a rigidbody with gravity off and isKinemtaic set to true.

    Target rigidbody set to discrete, no collisions are detected, regardless of the rigidbody collision method on the projectile.
    Target rigidbody set to Continuous, then only the projectiles using ContinuousDynamic will detect a collision.
    Target rigidbody set to ContinuousDynamic, then projectiles using both Continuous ContinuousDynamic will detect collisions.

    Updated the package to include the 'Test_BoxColliderRigidBody' prefab - you need to open up the prefab, select target and switch it between the various collision methods to test how it is affected by the projectiles.

    NB: All test results assume original posters code base is correct.
     

    Attached Files:

    Last edited: Jun 1, 2013
  15. MooseMouse

    MooseMouse

    Joined:
    Sep 14, 2011
    Posts:
    515
    Thanks for doing this, noisecrime!

    Here are my results. In the "tables" below
    - the first number in each row is speed.
    - the second number is a boolean for whether a collision was detected when the projectile was set to the Discrete collision method.
    - the third number is a boolean for whether a collision was detected when the projectile was set to the Continuous collision method.
    - the forth number is a boolean for whether a collision was detected when the projectile was set to the ContinuousDynamic collision method.

    Static Box Collider on Target
    467.53.......0.......0.......0
    935.06.......0.......0.......0
    1402.59.......0.......0.......1
    1870.12.......0.......0.......0
    2337.65.......0.......0.......0

    Rigidbody Box Collider on Target. Collision method set to Continuous on Target
    467.53.......0.......1.......1
    935.06.......0.......0........ 0
    1402.59.......1.......0.......0
    1870.12.......0.......0.......0
    2337.65.......1.......0.......0

    Static Mesh Collider on Target
    467.53.......0.......1.......1
    935.06.......0.......1.......1
    1402.59.......0.......1.......1
    1870.12.......0.......1.......1
    2337.65.......0.......1.......1

    So, from my quick tests, it looks like the only way to guarantee collision detection with fast projectiles is to make sure the static target has a Mesh Collider and the projectile collision detection method is set to Continuous or ContinuousDynamic. In my tests it seems that adding a Rigidbody to the target did not help.
     
    Last edited: Jun 1, 2013
  16. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    1,513
    No problem, I figured it was about time I put my money where my mouth was ;)

    About the Rigidbody tests, I found that both the target and the projectile had to have ContinuousDynamic set for it to detect collisions. If the target only had Continuous, then only projectiles using ContinuousDynamic would collide with them.

    Though your results suggest that this isn't true when the target is set to just Continuous, which is strange as i've re-ran each test several times and it works 100% for me. Would you mind running that test again and double checking your results. For reference i'm using Unity 3.5.7 on Windows 7, intel cpu.

    I've re-ran my tests again (same speed as you) swapping target rigidbody between Continuous and ContinuousDynamic and get the same results as before. With Continuous, only projectiles with ContinuousDynamic collide, but with ContinuousDynamic projectiles with either Continuous or ContinuousDynamic collide 100%

    Just to be clear the only changes that should be made with the demo is to swap out the test prefabs, no other script properties need to be changed, unless using the 'Test_BoxColliderRigidBody' in which case you have to select the target in that prefeb and switch its collision methods to check against all permutations.

    Edit: Couple of other points
    Changing the projectile from a SphereCollider to a BoxCollider (no rigid body) has the same results as my previous post. However changing the projectile to a MeshCollider (no rigid body) resulted in all collision tests failing!

    So I guess that is something else to watch out for that you can't do mesh to mesh collision, though I don't think thats anything new, pretty sure Unity docs mention it somewhere.
     
    Last edited: Jun 1, 2013
  17. MooseMouse

    MooseMouse

    Joined:
    Sep 14, 2011
    Posts:
    515
    I just re-ran it with a fresh project in which I didn't mess with anything.. same results as I got previously (unreliable collision detection). The target with Rigidbody was set to ContinuousDynamic this time. I am using Unity 4.1.3 on a Window 7, Intel CPU.

    This shows my complete ignorance about computer hardware, but does nVidea PhysX use the CPU or the GPU? I only ask because nVidea makes graphics cards.. I know nothing on the subject so maybe it is a silly question. I have a Radeon 5700 series graphics card.
     
    Last edited: Jun 1, 2013
  18. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    1,513
    Interesting, I think I have 4.1.3 (Pro) installed i'll check with it. Is that Unity free or Pro?

    Not 100% sure about PhysX using nvidia cards or not these days, but i'm pretty sure that Unity's implementation of PhysX doesn't use the gpu as it needs to support so many devices.

    EDIT:
    AHA Oh dear, running in 4.1.3 I seem to get very inconsistent results with the rigid body target using ContinuousDynamic, suggesting the same results that you have. Perhaps we've discovered a Unity bug.

    Yep, pretty sure this is a bug or at least a nasty regression since 3.5.7 ;(
     
    Last edited: Jun 1, 2013
  19. MooseMouse

    MooseMouse

    Joined:
    Sep 14, 2011
    Posts:
    515
    Well, at least there is some consistency. I was even more concerned when it appeared to be working on your computer and not on mine. I'll file a bug report and see what happens.
     
  20. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    1,513
    Yeah, I've logged a bug/regression for it too, with a project and a long description and explanation ;)
     
  21. Meltdown

    Meltdown

    Joined:
    Oct 13, 2010
    Posts:
    5,421
    Although it doesn't sound like it makes sense, I've noticed improved collision performance when scaling the entire world larger. Often I've had a ball go through a mesh collider, et when I increased everythings scale by a few times, sometimes the ball stopped going through the walls. Why, I have no idea.
     
  22. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    25,609
    Really tiny and really large numbers have issues with precision. Most likely when you scaled everything up, not everything got scaled up the same way like forces, masses, etc.
     
  23. Forge Vault

    Forge Vault

    Joined:
    Feb 18, 2012
    Posts:
    214
    Could be what hippo said. Could be anything - it shouldn't be going through walls though. I once had a sidescroller with a crooked wall, and a player who's X was set to 0 "while grounded"... He kept jumping through walls, and I kept cursing the physics until I caught on :)
     
  24. Lockstep

    Lockstep

    Joined:
    Sep 14, 2012
    Posts:
    18
    Thanks for your replies. I've redone the speed test with a mesh collider to test the condinuous collision method. The results have been edited into the first post.
    Since people requested it, I also included a custom package with my test scene.
     
  25. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    1,513
    Just an update, got a reply for the problem I noticed where all collisions were broken between 3.5.7 and 4.x versions of Unity. Looks like it was a bug and it will be fixed in an upcoming update of Unity, though not sure when.

    Knew there was a reason I didn't like scaling stuff in Unity ;)

    Seem to remember running into issues with this before with physics, I think setting the scale to 0 caused objects to always fail collisions even after resetting the scale. Though that was some time ago so hopefully that bug was already fixed.
     
    Last edited: Oct 18, 2013
  26. skinnysimmons

    skinnysimmons

    Joined:
    Oct 6, 2012
    Posts:
    20
    Reviving this thread.

    My game's collision were working fine before updating to 5.2.3 (not exactly sure which version it was at before... but it would have been active as of Feb 2015)
    Regardless, now my character (with a circle collider, colliding with other circle colliders) seems to go past the boundaries of the circles quite often, when it used to not do that at all... Any ideas as to what might have changed in the versions from Feb 2015 to 5.2.3 that might have them computing differently?

    Thanks all!
     
  27. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    25,609
    Hi, please post another thread. This thread is using an entirely different version of the physics engine and none of the data or findings are relevant to 5 whatsoever.
     
Thread Status:
Not open for further replies.