Issue with Dynamic Laser Reflection on Walls

Hello, community!

I’m kind of a begginer on scripting and I’m making some sort of billiard game.

I’m having troubles with the reflection of the “power line” on the table walls, being the “power line” the line that’s shown when you charge your launch in-game and the “table walls” the colliders that will reflect the shot.

To get you guys underway, the laser should work like this:

  • The power line is casted from a place called “LaserSpawn”;
  • Whenever I click somewhere inside the game screen and hold the mouse button, the power line should be shown, and it’s complete width (untill now) is equal to the width from the Laser Spawn to the mouse position, and it must go in the opposite direction; also the power line updates itself every frame the mouse button is hold;
  • I’m casting a raycast2D from the Laser Spawn and, as soon as it collides with a wall, a new raycast is casted from that point in the reflected direction with a calculated width between the first raycast’s end point and the collision point with the wall;
  • Finally, if the new ray collides with another wall, the process should repeat: a new raycast should be casted from the next collision point, etc.

By now, I’m keeping the Line Renderer unabled, I’d rather make the raycast work first so that i guess I’ll be able to make the line renderer propperly work next.

The thing is, when I set up the game to reflect the power line just ONE TIME it works perfectly, here’s a sample:

But when I set it to reflect MORE THAN ONE TIME, the reflections seem to happen, but they start flickering. Because I can’t upload more than two images, here’s only a sample of the non-reflected line, it should be reflecting in the next wall:

Here’s my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DirectionLineModified : MonoBehaviour
{
    public Transform laserSpawner;
    public LayerMask _layerMask;
    LineRenderer line;

    void Start()
    {
        if(gameObject.GetComponent<LineRenderer>() != null)
        {
            line = gameObject.GetComponent<LineRenderer>();
        }

        for(int i = 0; i < line.positionCount; i++)
        {
            line.SetPosition(i, new Vector3(laserSpawner.position.x, laserSpawner.position.y, 0));
        }
    }

    void Update()
    {

        if (Input.GetMouseButton(0))
        {
            line.enabled = true;
            DrawLine(laserSpawner.position, new Vector3((2 * laserSpawner.position - Camera.main.ScreenToWorldPoint(Input.mousePosition)).x, (2 * laserSpawner.position - Camera.main.ScreenToWorldPoint(Input.mousePosition)).y, 0), 1);
        }

        else
        {
            for (int i = 0; i < line.positionCount; i++)
            {
                line.SetPosition(i, new Vector3(laserSpawner.position.x, laserSpawner.position.y, 0));
            }
            line.enabled = false;
        }

    }

    void DrawLine(Vector2 initRayPos, Vector2 lastRayPos, int linePosIndex)
    {
        if (linePosIndex < line.positionCount)
        {
            RaycastHit2D hit = Physics2D.Raycast(initRayPos, lastRayPos - initRayPos, Vector3.Distance(lastRayPos, initRayPos), _layerMask);

            if (hit.collider != null)
            {
                if (hit.collider.tag == "FalseWalls")
                {
                    float remDist = Vector3.Distance(lastRayPos, initRayPos) - hit.distance;
                    Vector2 refVect = remDist * Vector2.Reflect((hit.point - initRayPos), hit.normal).normalized;
                    DrawLine(hit.point, refVect + hit.point, linePosIndex + 1);
                }

            }
  
            Debug.DrawRay(initRayPos, lastRayPos - initRayPos);
        }
        
    }
}

I’ve been trying for like three weeks and I can’t seem to make it work, send help please :frowning:

I GOT IT!!!

So after duplicating your scene, I played around a bit with your scene. After a lot of testing, I discovered that the hit.normals weren’t consistently facing the desired direction. I looked this up online, and found this post, which basically says not to use hit.point when Drawing the line.
So what I did then was change
DrawLine(hit.point, refVect + hit.point, linePosIndex + 1);
to DrawLine(hit.point + new Vector2(refVect.x * 0.1f, refVect.y * 0.1f), refVect + hit.point, linePosIndex + 1); which just offsets the initRayPos by a little bit. If it’s too big, you can just downscale the 0.1f value.

This solution worked for me, I hope it works for you as well!