Search Unity

How to get the motion vector after the collision?

Discussion in 'Scripting' started by Scarabey, Oct 18, 2014.

  1. Scarabey

    Scarabey

    Joined:
    Oct 18, 2014
    Posts:
    7
    Hi everyone,
    At the beginning I set the direction straight. There is a barrier on the object's path(track). After the collision with it the object pushs away in an arbitrary direction. How to get it a new direction vector2? Or how to accelerate the object in the puhing away direction?
     
  2. BobFinery

    BobFinery

    Joined:
    Oct 14, 2014
    Posts:
    46
    You will want the reflection vector so something like

    Where xVelocity is your velocity vector at time of impact, xNormal is the surface normal you have hit.

    Vector2 xReflection = 2.0f*Vector2.Dot(xVelocity,xNormal)*xNormal-xVelocity;

    This will give a vector the same magnitude as the input xVelocity.

    If you want to reduce the velocity after impact you could do something simple like:

    xReflection *= 0.9f;
     
    Scarabey likes this.
  3. Scarabey

    Scarabey

    Joined:
    Oct 18, 2014
    Posts:
    7
    Maybe it can be made easier? For example, using rigidvody2d.velocity. Or it will not work?
     
  4. BobFinery

    BobFinery

    Joined:
    Oct 14, 2014
    Posts:
    46
    Which part do you want making easier?
     
  5. Scarabey

    Scarabey

    Joined:
    Oct 18, 2014
    Posts:
    7
    I did so:

    public float speed = 0.000001f;

    void FixedUpdate () {
    if (Input.GetKey("space"))
    {
    rigidbody2D.velocity = rigidbody2D.velocity * speed;
    }
    }
    But there was the problem of acceleration. After the second pressing key, object greatly increase the speed and disappears off the screen
     
    Last edited: Oct 19, 2014
  6. BobFinery

    BobFinery

    Joined:
    Oct 14, 2014
    Posts:
    46
    ok well that is a completely different problem to the OP...

    Your rigidbody should pretty much stop when you scale it by that tiny value so you would need to give more detail as the problem is likely elsewhere.
     
  7. Scarabey

    Scarabey

    Joined:
    Oct 18, 2014
    Posts:
    7
    I have a moveable object and a few obstacles. At the beginning of the object is moving up, then he collides with an obstacle, bounces from it and lose the initial speed.
    I want to get the object by pressing the key again to pick up speed.

    using UnityEngine;
    using System.Collections;

    public class PLayerMove : MonoBehaviour {

    public float speed = 0.0000001f;

    // Use this for initialization
    void Start () {
    rigidbody2D.AddForce (Vector2.up * speed);
    }

    // Update is called once per frame
    void FixedUpdate () {
    if (Input.GetKey("space")){
    rigidbody2D.velocity = rigidbody2D.velocity * speed;
    }
    }
    }

    But for some reason by pressing the key the object very fast flies away off the screen.
     
    Last edited: Oct 19, 2014
  8. BobFinery

    BobFinery

    Joined:
    Oct 14, 2014
    Posts:
    46
    You don't really want to be using velocity like that because it coulc have any magnitude, even zero. Scaling it by 0.0000001f will result in a very small velocity vector...

    does rigidbody2D not have a direction component?

    You want to be saying rigidbody2D.AddForce(direction*speed);

    If the rigidbody2D does not calculate this for you you will need to use code similar to that which I provided to get your new direction (in the oncollision function or somesuch.

    Have you tried the transform.forward vector?
     
  9. BobFinery

    BobFinery

    Joined:
    Oct 14, 2014
    Posts:
    46
    you might want to try transform.right as your "direction" vector as seemingly 2D doesn't use the forward vector

    So you could try

    // Update is called once per frame
    void FixedUpdate () {
    if (Input.GetKey("space")){
    rigidbody2D.AddForce(transform.right * speed);
    }
    }
     
  10. Scarabey

    Scarabey

    Joined:
    Oct 18, 2014
    Posts:
    7
    transform.forward vector - works only in 3D
    rigidbody2D.AddForce(transform.right * speed) - If you do so then the object will only move to the right in all circumstances
    apparently need to manipulate the x and y
     
    Last edited: Oct 20, 2014
  11. BobFinery

    BobFinery

    Joined:
    Oct 14, 2014
    Posts:
    46
    It won't always go to the right because the rigidbody2d system manipulates it. It will always go to the right of the objects forward (or in 2D "up") vector.

    Depending on how you are displaying/moving your object, say its a top down car facing up to the top of the screen then you would have its "forward" vector using transform.up. IF you apply a force AddForce(transform.up*fForceScale) then yeah it will move up the screen. If it hit something and rotated 90 degrees to the left then its transform.up now points to the left of the screen and subsequently adding a force using transform.up will now move the car to the left of the screen.

    Although I have a lot of experience with physics systems I have not used Unity's rigidbody2d so to double check I wrote this simple script:

    using UnityEngine;
    using System.Collections;

    public class NewBehaviourScript : MonoBehaviour {
    public Vector2 m_xRight = Vector2.right;
    public Vector2 m_xUp = Vector2.up;
    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {
    m_xRight = transform.right;
    m_xUp = transform.up;

    if (Input.GetButton ("Jump"))
    {
    GetComponent<Rigidbody2D>().AddForce(m_xUp*10.0f);
    }

    }
    }

    I added this component to a game object with a rigidbody2d component and a box collider.

    pressing "Jump" makes it move up as expected.

    I then added a second rigidbody2d, again with a box collider, but it below and slightly off center to the first object. I then set its gravity scale to 0 to make it stay where I put it.

    The first box falls onto it and rotates due to the collision forces, pressing "Jump" now made it accelerate off in the direction of its new up vector, again as I expected.

    Note, in my examples I ahve given you I have used "transform.right" and not the static Vector2.right (which will never change). Maybe that has led to some confusion?

    Note also that you don't need to assign the transform vectors to member vars, I did this simply so I could see the values changing in the editor as the simulation ran.
     
  12. Scarabey

    Scarabey

    Joined:
    Oct 18, 2014
    Posts:
    7
    I did in the beginning. But in this version of the code object after the collision starts randomly turns.
    Suppose after the collision strayed to an angle of 45 degrees and I need to give it the acceleration in the direction of where he had strayed. But due to the rotation, it will change direction different from 45 degrees.
     
    Last edited: Oct 21, 2014
  13. Scarabey

    Scarabey

    Joined:
    Oct 18, 2014
    Posts:
    7
    I did what I wanted. If anyone interested in the code below:

    usingUnityEngine;
    usingSystem.Collections;

    publicclass PLayerMove : MonoBehaviour {

    publicfloat speed = 10f;
    bool collisionCheck = false;

    Vector2 vel;
    float xdir;
    float ydir;

    // Use this for initialization
    void Start (){
    rigidbody2D.AddForce(Vector2.up* 100f);
    }

    void OnCollisionEnter2D(Collision2D coll){
    if(coll.gameObject.tag=="NPC"){
    vel = rigidbody2D.velocity;
    xdir = rigidbody2D.velocity.x;
    ydir= rigidbody2D.velocity.y;
    }

    }

    // Update is called once per frame
    void FixedUpdate (){
    if(Input.GetButton("Jump")){
    xdir = xdir*speed;
    ydir = ydir*speed;
    rigidbody2D.velocity=new Vector2 (xdir,ydir);

    }
    }
    }

    Thank you BobFinery :)