Can I detect a physic material in scripting? The following does not work:
function OnCollisionStay( colinfo : Collision )
{
for (var contact : ContactPoint in colinfo.contacts)
{
if (contact.otherCollider.material.name == "Bumper Physic")
{
print ("BUMPER!");
}
}
}
That does nothing–the if never triggers. It also failed when I tried using == “Bumper Physic Instance” since that string is the output I get from:
print (contact.otherCollider.material.name);
So maybe name is not what I want?
TIA
ignore the following useless topic: processing contact with more than one object at a time?
Once our player is in contact with the floor, no OTHER contacts get processed. It’s like Unity is ignoring all but the first collider contacted. What am I doing wrong?
Here’s my simple test, attached to the player:
function OnCollisionStay( colinfo : Collision )
{
for (var contact : ContactPoint in colinfo.contacts)
{
print (contact.otherCollider.name);
}
}
The result: as soon as the level loads, the player contacts the floor, and the floor’s name is printed. Then when the player bumps into other things, nothing is printed for them.
Except… very occasionally–which I think may happen when the player “catches a little air” and thus is not contacting the floor at that precise instant. Then the other collision does get printed to the console.
So how do I get Unity to detect collision with a second object while we’re already in contact with one (the floor)?
(Physically the player does bounce back from all objects–it’s just that my script doesn’t seem to know it.)
I tried the script and it worked fine in a simple setup with a couple of colliders and a rigidbody sphere rolling on top of it. And it worked perfectly fine. Are you sure it’s not printing. Maybe you are getting confused by the collapsing of print messages in the console?
collider.material creates a unique instance. This is to prevent modifying the material that is shared between all colliders, which is usually not what you want.
In the process creating a unique instance the name of the material is changed to “Bumper Collider Instance”.
so instead you can check the material name using the sharedMaterial property which will not create a unique instance:
if (otherCollider.sharedMaterial != null otherCollider.sharedMaterial.name != "Bumper Collider")
Great! Many thanks! I’m always finding new power hidden in Unity.
But now I think I may be hallucinating. The ORIGINAL problem is back: it only detects the first (floor) material it hits, and no others. It’s failing to react to more than one collision at a time, even though physically it’s bouncing back from everything just fine.
Here’s the whole current script:
function OnCollisionStay( colinfo : Collision )
{
for (var contact : ContactPoint in colinfo.contacts)
{
print (contact.otherCollider.sharedMaterial.name);
if (contact.otherCollider.sharedMaterial.name == "Bumper Physic")
{
audio.Play();
}
}
}
The audio DOES play if I put “Floor Physic” in the if. It plays constantly.
But it does not play for collisions with things other than the floor (“Bumper Physic”).
(And since it’s a sound, not a Print, I’m sure it’s not just me misreading the console.)
Depending on your setup, if you use sharedMaterial then it will return null, if you haven’t assigned a physic material to all objects. In that case it will give you a null reference exception.
No nulls, but the problem is found: OnCollisionStay and OnCollisionExit don’t work (since it’s a brief contact that rebounds) but OnCollisionEnter does
Everything is functional (But just out of curiosity, why wouldn’t OnCollisionExit work? The player bounces off the bumper, but Exit is not triggered, only Enter. It doesn’t matter, I’m just curious )
There seems to be an issue where OnCollsionExit is only called when OnCollsionStay also exists. (This will be fixed in 1.6.) The behaviour for OnCollsionStay is that it is only called when it is staying in contact, that is in contact for more than a frame. I think the behaviour will change with 1.6 though because i can see it’s not the most intuitive.
You can get at the transform of the object you hit, so then from the transform you can get at the renderer component which contains the material and sharedMaterial of the object. So you would probably want to compare myCollision.transform.renderer.sharedMaterial to something. But be careful because the renderer component will be null if you collide with something without a renderer attached, so you’ll want some if statements in there most likely.
I can provide a code example if that’d be useful, but I think it’s straight forward enough to leave it as an exercise for the reader. (Yummy medicine maybe?)