Need help ironing out this weird error in Raycast2D and Vector2.Reflect, for a billiard game test

I combed the entire internet looking for an answer but couldn’t fix it, and I have been at it for a week. I have made a loop that fires a Raycast2D from the position of the gameobject with the reflecting script and it shoots to its transform.right (irrelevant). It reflects from Box Colliders 2D (I have several in the scene called “New Sprite” and clones).

The problem is that, if I move or rotate the origin, at one point or another, it reflects inside that same point over and over. You can see in the “bad” screenshots that after a point or another, its the same values for the line renderer. Sometimes it works good, other times it doesn’t work after the first collision. The first collision is always good.



Here is the code for the bouncing script:

using UnityEngine;
using System.Collections;

[RequireComponent( typeof( LineRenderer ) )]
public class BouncingLaser : MonoBehaviour
	private LineRenderer laserRenderer;

	private int hitCount = 0;

	// Use this for initialization
	void Start()
		laserRenderer = GetComponent<LineRenderer>();
		laserRenderer.SetWidth( 0.03f, 0.03f );
		laserRenderer.SetVertexCount( 1 );

	public static Vector2 xy( Vector3 v )
		return new Vector2( v.x, v.y );

	// Update is called once per frame
	void FixedUpdate()
		hitCount = 0;

		Vector3 origin = transform.position;
		Vector3 direction = transform.right;

		Debug.Log( "-----------" );
		ExtractReflection( origin, direction );

	void ExtractReflection( Vector3 origin, Vector3 direction )
		direction = direction.normalized;

		if( hitCount == 6 )

		Debug.Log( hitCount + " - " + origin + " - " + direction );

		laserRenderer.SetVertexCount( hitCount );
		laserRenderer.SetPosition( hitCount - 1, origin );

		RaycastHit2D laserHit = Physics2D.Raycast( origin, direction * 10 );

		Debug.DrawRay( origin, direction, );

		if( laserHit.collider != null )
			Vector2 reflectPos = Vector2.Reflect( direction, laserHit.normal );

			ExtractReflection( laserHit.point, reflectPos );

			Debug.Log( "No hit at attempt: " + hitCount );


This happens because the new origin of the Physics2D.Raycast is inside the object that you previously found a collision with(right on the edge actually). laserHit.fraction will return 0 for this case.

Additionally, this will also detect Collider(s) at the start of the ray. In this case the ray is starting inside the Collider and doesn’t intersect the Collider surface. This means that the collision normal cannot be calculated in which case the collision normal returned is set to the inverse of the ray vector being tested. This can easily be detected because such results are always at a RaycastHit2D fraction of zero.

You can fix this in multiple ways. A quick and VERY dirty hack: move the new raycast origin outside the already tested object.

ExtractReflection(Vector3.Lerp(origin, laserHit.point, 0.98f), reflectPos );

Also keeping this in FixedUpdate rather than Update will calculate it multiple time per frame and this may not be what you desire.