Hey everyone! I'm trying to make an object "bounce" off a wall when it collides with it. The object has a rigidbody component (gravity disabled), and a mesh collider. It is always moving on its z axis. I want it to be deflected off the wall just like in an old pong type of game, so not by the built in physics. Take a look at these images and it may become clear as to what I'm talking about: I have no idea where to begin (I'm pretty new to unity) so any help is appreciated!
use raycast from the bullet to find the normal of the surface that's going to be hit http://unity3d.com/support/documentation/ScriptReference/RaycastHit-normal.html Basically if you have a vector v, which represents the object's velocity, and a normalized normal vector n, which is perpendicular to the surface with which the object collides, then the new velocity v' is given by the equation: v' = 2 * (v . n) * n - v; Where '*' is the scalar multiplication operator, '.' is the dot product of two vectors, and '-' is the subtraction operator for two vectors. v is reflected off of the surface, and gives a reflection vector v' which is used as the new velocity of the object. Or in the example you've given, the normal would be (0,-1,0) and if you bullet is traveling upwards at 45 degrees its velocity might be (-2,2,0) and after the reflection it'd be moving at (-2,-2,0) But yeah, use colliders and rigid bodies and let the physics engine sort it out. To prevent an object moving on the z-axis you can either attach a physics joint to the object or you can just add a line in function FixedUpdate that sets the z position and velocity to 0. That's very effective at forcing 2D movement. Also use primitive colliders (box, sphere etc) to make sure it's not at an odd angle.
Thanks for helping! But I'm having a hard time putting that math into a script. Could you help me out? Also, the physics engine won't work because when the bullet hits the wall, it just slides to the side as it tries to continue to move forward.
Just wanted to say: This works great. It took me a bit to get it implemented correctly with my current code (had to reprogram how movement was working to be a Vector3 for velocity), but works great. As a quick note for anyone trying to use it: I had to multiply the end result by -1 to make it translate correctly, don't know why. Here's the code, in case anyone wants to try it out for yourself Code (csharp): var velocity : Vector3; //Our movement velocity var speed : float; //Speed of object function Awake() { velocity = this.transform.forward; //Placeholder default velocity // Change to whatever you need speed = 20; } function Update() { this.transform.position += velocity * Time.deltaTime * speed; //Update our position based on our new-found velocity } function OnCollisionEnter( info : Collision ) //When we run into something { //'Bounce' off surface for( var contact : ContactPoint in info.contacts ) //Find collision point { //Find the BOUNCE of the object velocity = 2 * ( Vector3.Dot( velocity, Vector3.Normalize( contact.normal ) ) ) * Vector3.Normalize( contact.normal ) - velocity; //Following formula v' = 2 * (v . n) * n - v velocity *= -1; //Had to multiply everything by -1. Don't know why, but it was all backwards. } }
I was searching around for a solution to do just what this solves... I like this solution, but I found it difficult to visualize the result using the dot product... so I came up with an intuitive solution. Basically, the result needed is a reaction to the impact on a surface normal. So, we need a reflection about the surface normal which is just flipping the velocity vector about the surface normal and correcting the sign to achieve the final solution. Let my solution explain itself rather than me making it more convoluted than it is: Code (csharp): function OnCollisionEnter( info : Collision ) //When we run into something { //'Bounce' off surface for( var contact : ContactPoint in info.contacts ) //Find collision point { //Find the BOUNCE of the object velocity = Quaternion.AngleAxis(180, contact.normal) * transform.forward * -1; } }
i'm trying to do the same thing, but I am doing it in 2d. So the solution scriptgeek gave doesnt work. I get an error I have my collision point. Now I need to normalize it? What if I reflect a ray perpendicular to the collision angle and move my object along that path? From what i can see you can't use .normal in 2d -http://docs.unity3d.com/ScriptReference/RaycastHit-normal.html Any advice would be great. I am completely stuck on this one. Code (CSharp): void OnCollisionEnter2D (Collision2D col) { ContactPoint2D contact = col.contacts[0]; // logs the collision vector data in an array I believe c_collisionPoint = contact.point; // defines the collision data c_Velocity = Quaternion.AngleAxis(180, contact.normal) * transform.forward -1; "Operator'-' cannot be applied to operands of type 'UnityEngine.Vector3' and 'int'" } }