Strange LineRenderer Flip when reflecting

I have this script for a laser reflector. If there is not reflection the LineRenderer looks fine from all angles but if it’s reflected it flips when you look at it from outside the reflection angle. Here’s a recording of the flip since it’s hard to explain:

And this is the script I’m working on:

 [SerializeField] LaserSwitch[] laserSwitches;
    private int reflectionCount = 100;
    private LineRenderer lineRenderer;
    private Ray ray;
    private RaycastHit hit;

    public GameObject HitEffect;
    public float HitOffset = 0;
    public bool useLaserRotation = false;

    public float MaxLength;

    public float MainTextureLength = 1f;
    public float NoiseTextureLength = 1f;
    private Vector4 Length = new Vector4(1, 1, 1, 1);

    private ParticleSystem[] Effects;
    private ParticleSystem[] Hit;

    private void Start()
    {
        lineRenderer = GetComponent<LineRenderer>();
        Effects = GetComponentsInChildren<ParticleSystem>();
        Hit = HitEffect.GetComponentsInChildren<ParticleSystem>();
    }

    private void Update()
    {
        lineRenderer.material.SetTextureScale("_MainTex", new Vector2(Length[0], Length[1]));
        lineRenderer.material.SetTextureScale("_Noise", new Vector2(Length[2], Length[3]));

        ray = new Ray(transform.position, transform.forward);
        lineRenderer.positionCount = 1;
        lineRenderer.SetPosition(0, transform.position);
        ProcessRaycastReflection();
    }

    private void ProcessRaycastReflection()
    {
        for (int i = 0; i < reflectionCount; i++)
        {
            if (Physics.Raycast(ray.origin, ray.direction, out hit, MaxLength))
            {
                lineRenderer.positionCount += 1;
                lineRenderer.SetPosition(lineRenderer.positionCount - 1, hit.point);
               
                ray = new Ray(hit.point, Vector3.Reflect(ray.direction, hit.normal));
               
                HitEffect.transform.position = hit.point + hit.normal * HitOffset;
                if (useLaserRotation) HitEffect.transform.rotation = transform.rotation;
                else HitEffect.transform.LookAt(hit.point + hit.normal);

                foreach (var AllPs in Effects)
                {
                    if (!AllPs.isPlaying) AllPs.Play();
                }

                Length[0] = MainTextureLength * (Vector3.Distance(transform.position, hit.point));
                Length[2] = NoiseTextureLength * (Vector3.Distance(transform.position, hit.point));

                if (hit.collider.tag == "LaserSwitch")
                {
                    hit.transform.SendMessage("LaserRaycastHit");
                }
                else
                {
                    foreach (LaserSwitch laserSwitch in laserSwitches) if (laserSwitch.activated) laserSwitch.Deactivate();
                }

                if (hit.collider.tag != "LaserReflector") break;
            }
        }
    }

Anyone knows why the LineRenderer is flipping? I just can’t figure this one out. Any help will be most appreciated.

First, that looks awesome. Love it, especially the little spitty-sparky particles shooting along with the laser.

What I see above is just normal line renderer billboarding, which can look degenerate when viewed from very narrow-down-line angles like that.

You can actually kinda see it just by using a LineRenderer in a blank scene viewing it from various angles and orientations, and the line renderer trying to keep all lines flowing around the billboarding.

You can see it in a simple scene with a 0.2 width line renderer with these settings:

That’s just 3 points… move the 0.79 point up and down slowly and you’ll see how it tries to keep it smooth. You’ll see the bevelling at the start and end of the line changing.

I think your solution is to just use multiple line renderers, one for each segment.

Thanks Kurt-Dekker! I will try that right away.

You might need an extra foof of bright laser light at each reflection point to hide any mismatch between each line segment, but that might actually make it look even cooler.

1 Like

I will post the result! :slight_smile:

When you say use multiple LineRenderers, one for each segments, did you mean prefab the laser beam and use instantiate? Or is there a better approach?

1 Like

I would just make a line renderer pool… maybe a script with a bunch of children line renderer GameObjects below it (parent-wise).

Anything needing a beam segment would ask the pool for one, get one assigned, then when they were done they would hand it back to the pool. You could start the pool with 1 LineRenderer, disable it and keep it as a template. Then just instantiate copies of it if you run out, yet keep the ones that are handed back, a nice parsimonious approach to pooling.

1 Like

Thanks again for the tip!

1 Like