Hi,
In our game, when we are hitting the ball with a greater force(8000N) towards the wall, the ball is not detecting the collision with it and it passes through it. We have set the wall as mesh collider and the ball as sphere collider. is there any problem with the collision detection system? or are we doing anything wrong? This problem is occurring only when we are trying to hit with greater force. Can any one suggest any solution to this issue.
.Prabhakar
A couple of suggestions: Firstly, try increasing the physics time steps - this will definitely help, although can impact on performance in a big way, as it’s running the collision checks more often.
You could also try increasing the depth of the collider along the axis the ball is travelling (so for example, if a ball is travelling perpendicular towards a wall, make the wall collider thicker). This isn’t always possible, as you might need to use the area behind the wall within your game.
We had similar issues with inconsistent physics at higher velocities found the DontGoThroughThings script useful. It uses raycasts (I think!) to see if an object has passed through any colliders corrects the skipped collision. It can sometimes look like the object goes into, then pops back out of a collider but it does the job! 
Hi,
Pixelcocoa, thanks for your reply. Now i am able to detect the collision, but after the collision detection i tried setting the velocity of the rigidbody to zero but it doesn’t work, the body still continues to move. it seems the update loop of the physics engine works continuously in the backend. is there a way to stop and start the physics of the rigidbody. I have searched the documentation but couldn’t find it.
-Prabhakar
Hmmm, it sounds as though you are explicitly applying a force or setting a velocity to your ball in one of the functions Update() or FixedUpdate(). If your ball stops but then accelerates from rest then it is probably the case that you are adding a force in either of the two functions. If you are setting the velocities in each update then your ball will be in constant collision with the wall (assuming a perpendicular collision). If your ball is bouncing back off the wall in the opposite direction then it sounds as though you aren’t actually setting the velocity to zero:
I assume that in the script attached to your rigidbody (ball) you have something like:
function OnCollisionEnter (){
rigidbody.velocity = Vector3(0,0,0);
rigidbody.angularVelocity = Vector3(0,0,0);
}
If so, your ball should stop dead and then just fall under gravity. The angularVelocity bit is to stop your ball from rolling along once it hits the ground. The problem with this is that the ball will stop dead on collisions with ANY object, which may not be what you want (if it hits the ground, for example) but try this and see if it stops your ball then I’d move on from there to use a trigger (look up the Trigger or IsTrigger property of a collider in the reference manual).
If none of this helps then you’ll need to post a description of how you are applying the force or velocity to the ball and I’ll have another look. Hope this helps.
Don’t forget, you can set the physics iteration/solver frequency per object.
I tried using your code but it didn’t help me. please have a glance at my code.
I am using a trigger when the bat hits the ball. This function is written in ball script.
function OnTriggerEnter (other : Collider) // ball script
{
rigidbody.AddForce(-myPlayer.transform.forward * 100);
}
Again on collision with the wall.
function OnTriggerEnter(other : Collider) // wall script
{
//ball.rigidbody.velocity *= 0;
ball.rigidbody.velocity.z *= -1;
}
Am i doing anything wrong here?
the direction of the ball changes for two frames, but later it continues with its earlier direction. This problem is occurring only when the ball has higher velocity.
Actually, you don’t tell it to only perform that function once. What if unity detects it hitting the wall twice?
The ball in theory would end up going in the same direction (inversing something twice = the original variable)
Anyone got a better explanation?
Yeah, JTBentley could be right. Easy to test, just add:
Debug.Log(“COLLISION DETECTED”);
and then if this appears twice in the console then you know that’s your problem. I’m guessing that it’s not though because you want to set it to zero don’t you? Like your commented out line and if it was setting velocity to zero twice then there wouldn’t be a problem.
Let us know what the result of this is and we’ll have another think…
I just set up a little test project and there is definitely a point at which a ball is moving so fast that this script fails to stop it upon collision with a plane. On my machine it took a force of about 6000 (scaled by deltaTime) to do it (velocity at impact was about 60). Turning the physics time step down increases this number but you still get to the point that it fails. I saw no difference between using a mesh collider and box collider in the wall plane.
UPDATE: You can improve this by increasing the thickness of the box collider of the plane.
I suppose the simplest solution would be to make the object kinematic upon collision detection and then just set its transform position back to the near side of the wall. It may flicker though depending on how far it penetrates through the wall from frame to frame before it is set back.
UPDATE: This solution won’t work because there is a velocity at which the collision events stop firing entirely. Instead I think you could just check the value of the ball x or z value and if it has collided with the wall, stop the ball, or make it bounce off, etc.
I’d certainly be interested in hearing other possible solutions.
Here the script from my test scene which was just a ball, a floor plane and a wall plane:
public var speedVal: float = 0.0;
private var acceptInput: boolean = false;
private var hasCollided: boolean = false;
private var forceDir: float = 0.0;
private var ballRB: Rigidbody;
function Start() {
this.ballRB = this.gameObject.GetComponent(Rigidbody);
this.acceptInput = true;
}
function Update () {
if (this.acceptInput) {
this.forceDir = Input.GetAxis("Vertical") * -1;
}
else {
this.forceDir = 0;
}
return;
}
function FixedUpdate() {
this.ballRB.AddForce(Vector3.forward * this.forceDir * this.speedVal * Time.deltaTime);
}
function OnCollisionEnter(other: Collision) {
if (this.hasCollided) {
return;
}
if (other.gameObject.name == "FarWall") {
this.acceptInput = false;
this.hasCollided = true;
this.ballRB.velocity = Vector3.zero;
}
return;
}
It seems like my problem is solved by this code.
function Update()
{
var targetDir = ball.rigidbody.position - transform.position;
var forward = transform.forward;
var angle = Vector3.Angle(targetDir, forward);
if(angle > 90) // collision response
{
var fdwVel = ball.rigidbody.velocity.magnitude;
var vel = ball.rigidbody.velocity;
var refVec = vel - 2 * transform.forward * Vector3.Dot(transform.forward, vel);
refVec.Normalize();
ball.rigidbody.velocity = refVec*fdwVel;
}
}
Thank you all for your replies.
.Prabhakar
As long as the ball is moving at a velocity below the point where collision events stop firing, your code will work. Above that velocity and it will still fail. I have found that rigidbody velocities where gravity is at work seem to look good under 50 or so, and at that velocity your should still be below the point the collision fails.
I have applied almost 10000N of force and checked the collision. My code is working fine. But i can’t apply this script to every object in the world. Is there any other solution to this kind of problem. why the system is failing to recognize the collision and generate its response at the higher velocities is a mystery to me.
The issue is not the force you apply to the rigidbodies but rather the velocities that they reach by the time they hit the colliders (which is of course a function of their mass, drag, the force value and the duration for which the force is applied). There is definitely a velocity at which the collisions are no longer detected by the engine and therefore any script that depends on the the enter, stay or exit collision events is going to fail.
Depending on the geometry of your game, the most fool proof and inexpensive way to do this would be to check the transform locations of the moving game objects relative to the positions of the walls they need to collide with. When the game object moves beyond the point that a collision would have otherwise stopped it then you can run your impact code the same way you fire it from the collision events.
Another way to go is to constraint the velocities of the rigidbodies. Add a line of code after you apply your force in the FixedUpdate that caps the velocity at a point that the collisions still occur. This could lead to some unrealistic looking physics, though, so you’d have to experiment.
Finally you could try detecting your own collisions by casting rays from the moving game objects. This is expensive to do for a significant number of objects though, so you’d have to experiment and see how much it degrades performance in your game.