I was looking for a script to bounce a laser off a mirror and I found this: [FREE]bouncing laser script! - Community Showcases - Unity Discussions
I was able to modify it the way I wanted. Currently, in the latest version of that code, the laser will go through any object until it reaches its length. I modified it so that the laser will 1) bounce if it hits a GO with the bounce tag, 2) stop when it reaches its end and 3) stop when it reaches an object it can’t bounce off.
Now, this was in 3d. https://i.imgur.com/WxyAHuf.jpg
But what about a game that’s in 2D?
I changed the raycast to a 2d raycast and noticed the laser (line renderer) flickers after it bounces. I wouldn’t post here unless I really needed help.
I thought this might be Z fighting, so I isolated the problem. There are no background sprites it could be conflicting with.
I thought, just maybe, line renderer is meant for a 3d component? I made a manual line renderer and I can move this one around in a 2D game, so no, that’s not the issue either.
I can’t really take a picture of the flicker, but I have uploaded the project if anyone wants to look at it. You’re also free to use the code if you credit the original creator: https://drive.google.com/file/d/0B28_UAx78Is1aWEwanRRNlRWQkE/view?usp=sharing
The project has a 2D scene and a 3D scene. The 3D one seems to be working, you can rotate (by rotate I mean in the inspector) and the laser updates in real time. The 2D one just flickers as you rotate the mirror.
Just in case anyone is skeptical about downloading a project, here’s the code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[RequireComponent(typeof(LineRenderer))]
public class BouncingLaser2D : MonoBehaviour
{
public float updateFrequency = 0.1f;
public int laserDistance;
public string bounceTag;
public string splitTag;
public string spawnedBeamTag;
public int maxBounce;
public int maxSplit;
private float timer = 0;
private LineRenderer mLineRenderer;
// Use this for initialization
void Start()
{
//spawnedBeamTag = "spawnedBeamTag";
Debug.Log(spawnedBeamTag);
Debug.Log(bounceTag);
timer = 0;
mLineRenderer = gameObject.GetComponent<LineRenderer>();
StartCoroutine(RedrawLaser());
//DrawLaser();
}
// Update is called once per frame
void Update()
{
if (gameObject.tag != spawnedBeamTag)
{
if (timer >= updateFrequency)
{
timer = 0;
//Debug.Log("Redrawing laser");
foreach (GameObject laserSplit in GameObject.FindGameObjectsWithTag(spawnedBeamTag))
Destroy(laserSplit);
StartCoroutine(RedrawLaser());
}
timer += Time.deltaTime;
}
else
{
mLineRenderer = gameObject.GetComponent<LineRenderer>();
StartCoroutine(RedrawLaser());
}
}
IEnumerator RedrawLaser()
{
//Debug.Log("Running");
int laserSplit = 1; //How many times it got split
int laserReflected = 1; //How many times it got reflected
int vertexCounter = 1; //How many line segments are there
bool loopActive = true; //Is the reflecting loop active?
Vector3 laserDirection = transform.forward; //direction of the next laser
Vector3 lastLaserPosition = transform.localPosition; //origin of the next laser
mLineRenderer.SetVertexCount(1);
mLineRenderer.SetPosition(0, new Vector3(transform.position.x,transform.position.y,0f));
RaycastHit2D hit;
while (loopActive)
{
hit = Physics2D.Raycast(lastLaserPosition, laserDirection, laserDistance);
if (hit && ((hit.transform.gameObject.tag == bounceTag) || (hit.transform.gameObject.tag == splitTag)))
//
// if (Physics2D.Raycast(lastLaserPosition,laserDirection, laserDistance))
//if (Physics2D.Raycast(lastLaserPosition, laserDirection, out hit, laserDistance) && ((hit.transform.gameObject.tag == bounceTag) || (hit.transform.gameObject.tag == splitTag) /*|| hit.transform.gameObject.tag == "Node")*/))
{
//Debug.Log("Physics.Raycast(" + lastLaserPosition + ", " + laserDirection + ", out hit , " + laserDistance + ")");
//Debug.Log("hit");
//Debug.Log("Bounce");
laserReflected++;
vertexCounter += 3;
mLineRenderer.SetVertexCount(vertexCounter);
mLineRenderer.SetPosition(vertexCounter - 3, Vector3.MoveTowards(hit.point, lastLaserPosition, 0.01f));
mLineRenderer.SetPosition(vertexCounter - 2, hit.point);
mLineRenderer.SetPosition(vertexCounter - 1, hit.point);
mLineRenderer.startWidth = mLineRenderer.endWidth = .01f;
lastLaserPosition = hit.point;
Vector3 prevDirection = laserDirection;
laserDirection = Vector2.Reflect(laserDirection, hit.normal);
if (hit.transform.gameObject.tag == splitTag)
{
//Debug.Log("Split");
if (laserSplit >= maxSplit)
{
Debug.Log("Max split reached.");
}
else
{
//Debug.Log("Splitting...");
laserSplit++;
Object go = Instantiate(gameObject, hit.point, Quaternion.LookRotation(prevDirection));
go.name = spawnedBeamTag;
((GameObject)go).tag = spawnedBeamTag;
}
}
}
else
{
//Debug.Log("No Bounce");
if (hit.transform == null)
{
// Debug.Log("hit is null/no bounce");
//Debug.Log("No Bounce");
laserReflected++;
vertexCounter++;
mLineRenderer.SetVertexCount(vertexCounter);
Vector3 lastPos = lastLaserPosition + (laserDirection.normalized * laserDistance);
//Debug.Log("InitialPos " + lastLaserPosition + " Last Pos" + lastPos);
mLineRenderer.SetPosition(vertexCounter - 1, lastLaserPosition + (laserDirection.normalized * laserDistance));
}
else
{
//hits something
laserReflected++;
vertexCounter += 3;
mLineRenderer.SetVertexCount(vertexCounter);
mLineRenderer.SetPosition(vertexCounter - 3, Vector2.MoveTowards(hit.point, lastLaserPosition, 0.01f));
mLineRenderer.SetPosition(vertexCounter - 2, hit.point);
mLineRenderer.SetPosition(vertexCounter - 1, hit.point);
mLineRenderer.SetWidth(.01f, .01f);
lastLaserPosition = hit.point;
Vector2 prevDirection = laserDirection;
laserDirection = Vector2.Reflect(laserDirection, hit.normal);
if (hit.transform.gameObject.tag == "Player")
{
Debug.Log("hit player");
}
}
loopActive = false;
}
if (laserReflected > maxBounce)
loopActive = false;
}
yield return new WaitForEndOfFrame();
}
}
One thing I did notice is if you comment out line 90 lastLaserPosition = hit.point; then it bounces off the first mirror, won’t bounce off a second mirror, but it doesn’t flicker. I am not sure if that helps you.
I have tried replacing hit.point with hit.point.x, hit.point.y,0 and seeing if that helped, but it didn’t. I have also tried +1 and -1.
If anyone has any idea I really, really would be grateful for your input.
Edit: Further testing: The flickering is ONLY on the final bounce segment.