Search code examples
unity-game-enginevectorraycastingnormalsbounce

Issue when trying to get the normal vector of the surface hit by a raycast


I want a projectile that I'm moving by updating its position (dont want to use physics here) to bounce off a wall.

So what I'm doing is detecting the collision, then using a raycast to get the normal of the wall, and then using vector3.reflect to know the new direction. As far as I know, I can't use the collision normal, as it's the normal of the object, and not the wall, right?

The code looks something like that:

        point = collision.contacts[0].point;
        dir = bullet.transform.forward;
        point -= dir; // to step back a bit, for the raycast

        // this raycast is represented by the blue gizmo lines in the image below
        if (Physics.Raycast(point, dir, out RaycastHit hitInfo, 10f, ~LayerMask.GetMask("EnemyBullet", "PlayerBullet"))) {

            // this is the collider surface normal
            // it's represented by the red lines in the image below
            var normal = hitInfo.normal;

            // this part is not important, what matters is finding out why the normal above is going up, and not away from the wall.
            Vector3 reflect = Vector3.Reflect(-bullet.transform.forward, normal).Y(bullet.transform.position.y);
            Debug.Log(reflect);
            return reflect;
        }

        return Vector3.zero;

enter image description here (zoomed in version of the raycast and normal here: https://i.sstatic.net/2jT35.png)

And here's a video of the issue: https://www.youtube.com/watch?v=zq5jL2-I1Kg

  • the white Gizmo line is the normal of the wall, obtained from raycast from the player towards the wall. It was meant as a reference, a debug tool. As you can see, it's in the correct direction

  • the blue lines are meant to represent the raycasts I do from the code above (Physics.Raycast(point, dir). They seem to go through the wall just fine.

  • Now the issue: the red lines are the normals I get from var normal = hitInfo.normal; in the code above. I would have expected them to be in the same direction as the white gizmo line...

Can you see an obvious mistake in the above code? If you need more info, just ask.


Solution

  • I found the issues.

    1 - Vector3.Reflect(bullet.transform.forward, normal).Y(bullet.transform.position.y). I should have set the y position to 0, not to the bullet transform y position.

    2 - In my code I was using the return value of Vector3.Reflect with transform.lookAt(vector) when I should have used transform.rotation = Quaternion.LookRotation(newDirection)

    But overall I simplified the code quite a bit and it seems to work just fine. I just raycast in the forwards direction of the projectile when it collides, and it works fine.