Object Reflecting off a Wall

Discussion in 'Scripting' started by CgRobot, Jan 16, 2011.

  1. CgRobot

    CgRobot

    New Member

    Joined:
    Jan 4, 2011
    Messages:
    175
    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:

    $Rocket 1.png

    $Rocket 2.png

    I have no idea where to begin (I'm pretty new to unity) so any help is appreciated!
  2. Mike L

    Mike L

    New Member

    Joined:
    Sep 14, 2010
    Messages:
    1,035
    adding a collider and a rigidbody should work on its own
  3. spinaljack

    spinaljack

    Member

    Joined:
    Mar 18, 2010
    Messages:
    798
    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.
    Last edited: Jan 16, 2011
  4. CgRobot

    CgRobot

    New Member

    Joined:
    Jan 4, 2011
    Messages:
    175
    Thanks for helping! But I'm having a hard time putting that math into a script. Could you help me out?:confused: 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.
  5. celinscak

    celinscak

    New Member

    Joined:
    May 4, 2010
    Messages:
    102
    In the Mesh collider in the Inspector try giving it a physic material Bouncy.
  6. Mike L

    Mike L

    New Member

    Joined:
    Sep 14, 2010
    Messages:
    1,035
    and if the rigidbody has freeze rotation enabled, turn it off
  7. Loftless

    Loftless

    New Member

    Joined:
    Mar 20, 2011
    Messages:
    16
    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):
    1.  
    2. var velocity : Vector3; //Our movement velocity
    3. var speed : float; //Speed of object
    4.  
    5.  
    6. function Awake()
    7. {  
    8.     velocity = this.transform.forward; //Placeholder default velocity // Change to whatever you need
    9.     speed = 20;
    10. }
    11.  
    12.  
    13. function Update()
    14. {
    15.     this.transform.position += velocity * Time.deltaTime * speed; //Update our position based on our new-found velocity
    16. }
    17.  
    18.  
    19. function OnCollisionEnter( info : Collision ) //When we run into something
    20. {
    21.     //'Bounce' off surface
    22.     for( var contact : ContactPoint in info.contacts ) //Find collision point
    23.     {
    24.         //Find the BOUNCE of the object
    25.         velocity = 2 * ( Vector3.Dot( velocity, Vector3.Normalize( contact.normal ) ) ) * Vector3.Normalize( contact.normal ) - velocity; //Following formula  v' = 2 * (v . n) * n - v
    26.        
    27.         velocity *= -1; //Had to multiply everything by -1. Don't know why, but it was all backwards.
    28.     }
    29. }
    30.  
  8. ScriptGeek

    ScriptGeek

    Member

    Joined:
    Mar 4, 2011
    Messages:
    31
    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):
    1.  
    2. function OnCollisionEnter( info : Collision ) //When we run into something
    3. {
    4.     //'Bounce' off surface
    5.     for( var contact : ContactPoint in info.contacts ) //Find collision point
    6.     {
    7.         //Find the BOUNCE of the object
    8.         velocity = Quaternion.AngleAxis(180, contact.normal) * transform.forward * -1;
    9.     }
    10. }
    11.  
    Last edited: Feb 28, 2013
  9. Bradford Hinkle

    Bradford Hinkle

    Member

    Joined:
    Aug 12, 2013
    Messages:
    2
    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):
    1. void OnCollisionEnter2D (Collision2D col)
    2.     {
    3.         ContactPoint2D contact = col.contacts[0]; // logs the collision vector data in an array I believe
    4.         c_collisionPoint = contact.point; // defines the collision data
    5.  
    6.         c_Velocity = Quaternion.AngleAxis(180, contact.normal) * transform.forward -1; "Operator'-' cannot be applied to operands of type 'UnityEngine.Vector3' and 'int'"
    7. }
    8. }
  10. novashot

    novashot

    Member

    Joined:
    Dec 12, 2009
    Messages:
    277