Hi there,
I’ve got a rigidbody with a spherecollider and need a way to keep track of all the points it is currently in contact with.
I thought OnCollisionStay would be the way to do this, but somehow it gives unexpected results.
My test cases are the following: The SphereCollider is sitting on a stairway, in case A composed of BoxColliders, in case B a single mesh collider/imported 3dmodel
CASE A (click to enlarge)
CASE B (click to enlarge)
Than I’m printing the contact.points with this script:
function OnCollisionStay (collision : Collision) {
grounded=true;
print(collision.contacts.Length);
for (var contact : ContactPoint in collision.contacts) {
print(contact.otherCollider + " " + contact.point);
}
collisions = collision;
}
As you already may have noticed in the pictures the console output is very, very strange:
In Case A it says it has 2 contact.points, but then prints 2 times the coordinates of the first contact and than 2 times the coordinates of the second, instead of printing both coordinates at once.
CASE B is even worse it says it has 2 to 8 contacts and about half of the printed coordinates belongs to the first and half to the second contact point.
I considered that this might have to do with the number of vertices of the stairway mesh compared to the two box colliders, but I dont see why this should be the way oncollisionstay is supposed to work.
Maybe I’m wrong but shouldn’t be the output more like this:
Number of Contacts
Coordinate 1.Contact
Coordinate 2.Contact
…
Number of Contacts
Coordinate 1.Contact
Coordinate 2.Contact
…
If anybody knows the reason for this, or has any suggestions for a work arround, so that I can have an output like shown above, I would be very glad.
I hope I described the problem well enough, otherwise feel free to ask and I will clarify.
As alway any help is appreciated. Thanks!
There is more to the contact than position. I’ve ran into this too and it is odd at first. But if you draw out the normals your most likely going to see in the first example one normal pointing up y and another out x.
Collision data i’ve found is quite different between different colliders. Like a box collider and a sphere collider will almost always choose to collided off a corner or edge of a box when it can, rather than two seperate faces, Meshes are kind of the same way but with vertices.
I’m not sure what the solution is your looking for though, If its to try and get two seperate positions out of the two contacts with seperate normals, theres not really way built in. You could find the penetration between the two some how and approximate points somehow but it wouldnt be accurate in that you wouldnt have every single point of intersection because that would be the entire outline of the surface areas overlapped.
Hope this helps though, Can be really frustrating dealing with this sort of stuff at this level of detection, more so if you need to rely on it.
Thanks for the hint, I guess it makes sense, but since I only need positions and a total number of contact points I’ll need to work around that!
But I think I found a solution, so that I get an array with only one ContactPoint for each Contact.
I collect all the Contacts found during OnCollisionStay in one JS-Array.
Than in fixedUpdate where I need the data, I convert this array back to a builtin Array. Next I iterate through it and copy the Contacts to another JSarray, only if the previous contact did not have the same position.
After that I’m converting this reduced array to a builtin again, so that I can access all the data.
Finally I delete the array I used for collection so it can be filled with fresh data.
Since I’m just a hobbyist I don’t no if there is an easier way to do this so if anybody has a faster way to do this, just tell.
But it seemed like I had to use all these arrays, because OnCollisionStay would change the Array I’m using for data collection while fixedUpdate is processed. Don’t know if this is true.
Maybe this helps somebody else
function OnCollisionStay (collision : Collision) {
...
for (var i=0;i < collision.contacts.Length;i++) {
collCollect.Push(collision.contacts[i]);
}
...
}
function FixedUpdate () {
var reduced = new Array(0);
var builtinArray : ContactPoint[] = collCollect.ToBuiltin(ContactPoint);
for (var j=0;j < builtinArray.Length;j++) {
if(j==0)reduced.Push(builtinArray[j]);
else if (builtinArray[j-1].point != builtinArray[j].point){
reduced.Push(builtinArray[j]);
}
}
collisions = reduced.ToBuiltin(ContactPoint);
collCollect.Clear();