I am trying to make a customized bounce effect that can makes a 2d rigidbody always bounce off along 45 degree by the collision normal when colliding. (not like the 2d physics material that simply bonce objects reflectively which will invert a perpendicular incoming collider, and this is what I try to avoid.)
The problem is the rigidbody2d.velocity in OnCollisionEnter2D is always return Vector2.zero.
So,how do I get the income direction/velocity of a collision? Are there any official ways to deal with this?
I have figured out this myself, the answer is the “collision.relativeVelocity”.
And I wish unity can supply more customizable physics material that we can much easily setup limitation for bouncing angle or apply more complex bouncing trajectory/behaviour.
Anyway, Here is my solution of customized bounce, which divides situations in two ways, 1-) The inDir more parallel to impact plane, i.e., the angle between inDir and normal is larger than 45 degree; Use simple Refection . 2-) The inDir more perpendicular to impact plane,i.e. the angle between inDir and normal is smaller than 45 degree. Determine on which side (Left or Right) of normal and then apply a perfect 45 degree refection;
function OnCollisionEnter2D(collision:Collision2D){
var dirIn:Vector2; // Direction In
var a0:float; //angle to normal
var dirOut:Vector2; //Direction Out
var dir3:Vector3;
var check:int; //Check incoming direction on which side of normal, left or right or parallel
var rotateDir:Vector3;
dirIn = collision.relativeVelocity.normalized;//***THIS IS WHAT I NEED !***/
a0 =Vector3.Angle(-collision.contacts[0].normal , dirIn);
if(a0> 45.0){ //direction more parallel to the impact plane (more perpendicular to the normal), use Reflect will be good
dir3 = Vector3.Reflect(dirIn, collision.contacts[0].normal );
dirOut.x = dir3.x;
dirOut.y = dir3.y;
}else{ //direction more parallel to the normal, we need to avoid inverse or concave outcome, the reflect out angle restrict to 45 degree
check = CheckLeftRight(-dirIn, collision.contacts[0].normal);
if(check == 0){///Right
rotateDir = Quaternion.Euler(0,0,-45.0) * collision.contacts[0].normal;
}else if(check == 1){//Left
rotateDir = Quaternion.Euler(0,0,45.0) * collision.contacts[0].normal;
}else{//Parallel, randomly choose left or right
if(Random.value > 0.5){
rotateDir = Quaternion.Euler(0,0,-45.0) * collision.contacts[0].normal;
}else{
rotateDir = Quaternion.Euler(0,0,45.0) * collision.contacts[0].normal;
}
}
dirOut.x = rotateDir.x;
dirOut.y = rotateDir.y;
}
rigidbody2D.velocity = Vector2.zero;
rigidbody2D.AddForce(300.0* dirOut); //Deploy the bouncing force
}
function CheckLeftRight(v0:Vector2, v1:Vector2):int{
var dot:float;
var dot2:float;
var ccwV1:Vector2 = Quaternion.Euler(0,0,-90.0) * v1;
dot = Vector2.Dot(v0, ccwV1);
if(dot < 0){ //On the Right
return 0;
}else if(dot >0){ // On the Left
return 1;
}else{// forward or back
dot2 = Vector2.Dot(v0, v1);
if(dot2 >= 0){// same direction
return 2;
}else{ //inverse direction
return 3;
}
}
}