Vector3.Reflect not reflecting correctly

I resolved the question on how to draw a line, so here is the result:

So, now I want to create a line that shows the possible bounce off the wall (and the other ball).

Some suggested I use the Reflect method but it did not work, here is how I implemented it, script is attached to the white que ball:

//
        Ray ray2 = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit2;

        //
        if (Physics.Raycast(ray2, out hit2, 100.0f)){





            //position of white wall
            Vector3 startPos = transform.position;
            //cliked position, translated to the table plane
            Vector3 clickPos2 = new Vector3(hit2.point.x, hit2.point.y, transform.position.z);
             //get direction from ball to clicked position
            Vector3 direction = Direction (clickPos2 - startPos);

              //so I simply should do I reflect, it gives me a bit odd results
            Vector3 reflectDir = Vector3.Reflect(direction, hit2.normal);


            //finally im drawing the line
            lineRenderer.SetPosition(0, startPos);

            Vector3 forward = transform.TransformDirection(direction) * 100;
            lineRenderer.SetPosition(1, forward);

              //reflection?
            lineRenderer.SetPosition(2, hit2.point);

            lineRenderer.SetPosition(3, reflectDir);

Here is what this code gives me:

Any ideas on how to make it work?

Mirza

Something fishy here…

Think about what this code does

Ray ray2 = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit2;

if (Physics.Raycast(ray2, out hit2, 100.0f)){

Then why are you using the normal from this hit later on?

//so I simply should do I reflect, it gives me a bit odd results
Vector3 reflectDir = Vector3.Reflect(direction, hit2.normal);

You’d better do another RayCast from the cue ball in the direction it is going to travel to detect the correct normal.

In the past I had issues with reflect. Not sure why and could have just been my fault, but I ended up using something on this thread instead.

The code is this

    public static Vector3 ReflectDirection(Vector3 inDirection, Vector3 normal)
    {
        inDirection.Normalize();
        normal.Normalize();

        return (2 * ((Vector3.Dot(inDirection, normal)) * normal) - inDirection).normalized * -1;
    }

The inDirection is the direction you are currently moving and the normal is the normal of the surface you want to reflect against. This will (or should) give you the reflected direction.

hi eisenpony

not sure whtat is wrong with this line, maybe this is the wrong normal?

You’re taking a raycast from the CAMERA towards the table… you’re basically getting the normal where you click on the table. This is going to be adjacent to the surface of the table. If you reflect a vector parallel to the table with a vector adjacent to the table, you’ll get NO reflection… by definition of the reflection formula:

v2 = v1 - 2(v1 dot n) * n

Note the v1 dot n, if two vectors are adjacent to one another, their dot product is 0. You get:

v1 - 2 * 0 * n
v1 - 0
v1

You end up with the same result.

You’re using the wrong normal. What I think you are meaning to do is raycast from the camera to get a point to describe in which direction the cue ball should go (you want to shoot TOWARDS the point clicked). This is what this line is doing right?

//get direction from ball to clicked position
Vector3 direction = Direction (clickPos2 - startPos);

Ok, so once you have that… you need to calculate ANOTHER raycast from the cueball position in that direction, and see what THAT hits. That’s the normal you’re going to reflect over.

Vector3 direction = Direction (clickPos2 - startPos);

Thats right…but how do I do a raycast further from the cueball to the direction? this is what fails and Im not what
Im doing wrong:

Vector3 forwardBB = (clickPos2 * 1000);
            Ray ray3 = new Ray(direction, forwardBB);
            RaycastHit hit3;

            if(Physics.Raycast(ray3)) {

                Debug.Log("touching..." + hit2.collider.tag);

            }

you just created an array at the position ‘direction’. That doesn’t make sense.

The constructor for Ray is:

Ray(Vector3 position, Vector3 direction)

So… if ‘this’ is the cue ball you would say:

Vector3 direction = (
Ray ray3 = new Ray(this.transform.position, direction);

And now that’s a ray from the position of ‘this’ (the cue ball) in the direction of ‘direction’. Which is from the cue ball to the point clicked on the table!

How I’d write it completely is:

Ray ray2 = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit2;

if(Physics.Raycast(ray2, out hit2))
{
    var cueBallPos = this.transform.position;
    var dir = (hit.point - cueBallPos);
    dir.z = 0f; //flatten on table plane
   
    Ray ray3 = new Ray(cueBallPos, dir);
    RaycastHit hit3;
    if(Physics.Raycast(ray3, out hit3))
    {
        Debug.Log("Hit the wall!");
        Debug.Log("Wall Collider: " + hit3.collider.name);
        Debug.Log("Wall Normal: " + hit3.normal.ToString());
    }
}

Thanks for answer, it is definitely the right direction. Here is how I wrote it and Im still having a problem with the correct reflection, check the ending lines:

        Ray ray2 = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit2;


      
        //
        if (Physics.Raycast(ray2, out hit2, 100.0f)){

            //
            Vector3 startPos = transform.position;
            Vector3 clickPos2 = new Vector3(hit2.point.x, hit2.point.y, transform.position.z);
            Vector3 direction = Direction (clickPos2 - startPos);


            if(rb.velocity.x == 0.0f && rb.velocity.y == 0.0f){

                gameObject.transform.rotation = startTrans;

                lineRenderer.SetPosition(0, startPos);

                Vector3 forward = transform.TransformDirection(direction) * 100;

                lineRenderer.SetPosition(1, forward);
          
                //lineRenderer.SetPosition(2, hit2.point);

                //lineRenderer.SetPosition(3, reflectDir);

                lineRenderer.enabled = true;

            }

            Vector3 cueBallPos = this.transform.position;
            var dir = (hit2.point - cueBallPos);
            dir.z = 0f; //flatten on table plane
          
            Ray ray3 = new Ray(cueBallPos, dir);
            RaycastHit hit3;

            if(Physics.Raycast(ray3, out hit3)){

                //
                Vector3 reflectDir = Vector3.Reflect(dir, hit3.normal);

                //
                lineRenderer.SetPosition(2, hit3.point);

                //
                lineRenderer.SetPosition(3, dir);

            }

          
        }

Here are the odd results:

What do you think should be tweaked?

Mirza

line 50 in your code isn’t a point…

I notice you often mix up direction vectors and position vectors.

A vector representing direction use in place of a posiiton will give you a point from <0,0,0> that is direction units away from <0,0,0>. That’s what a ‘point’ is… it’s telling you how far away from the origin you are.

So in line 50 where you say:

lineRenderer.SetPosition(3, dir);

You should say something like:

lineRenderer.SetPosition(3, hit3.point + reflectDir.normalized * 100f);

Many thanks that worked!

Hm, direction Vector3 vs Point Vector3, how should I distinguish between both of them?

A vector3 has x,y,z, I dont see where the direction component is, its only a 3 axis in space…not sure.

Mirza

Well… you named them accordingly.

If you have a position like:

var pos1 = this.transform.position; //this property is defined as being a position

And you subtract another position from it:

var pos2 = other.transform.position;
var dir = pos2 - pos1;

In this case ‘dir’ is a vector from pos1 IN THE DIRECTION of pos2.

Dir is a vector representing change in position, a direction. Hence why we called it ‘dir’.

With dir we could actually find pos2.

var pos3 = pos1 + dir;
Debug.Log(pos3);
Debug.Log(pos2);

pos3 and pos2 will be roughly the same (note minor errors may creep in due to float error)

Thanks for the fantastic support, really a great forum!

My next question would be (to avoid starting a new thread):

  1. This is the off the wall reflection I just wrote with your help:

  1. Now I want to create a sort of physics prediction where the two colliding balls would go after the collison (just the direction):

A simple reflect does not work here…since we are not working with wall collisions, but with 2 rigidbodies.

Any suggestions?

Mirza