- Home /
Create a sine wave(using line renderer) and reflect it from colliders
Hello guys. I have bumped into really bad trouble. I have a line renderer which draws a line and reflects in other direction(creates a clone of that line in hit point with defined direction) if hits a collider with defined tag. So... I need to draw it not as a straight line, but as a line in sine pattern and reflect in the same way. I have no idea how to find a specific segment which would become a start point for a new(cloned) line :((( I tried a lot of ways to do it, but it failed :((( Here's my script and a picture of concept which I want to bring with a script into unity:
using System.Collections;
using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class SignalLine : MonoBehaviour
{
public float updateFrequency = 0.1f;
public float lineWidth = 1.0f;
public int lineDist;
public string reflectLineTag;
public string splitTag;
public string clonedLineTag;
public int maxBounce;
public int maxSplit;
public int maxSliptPerObj;
[Tooltip("Set Min & Max value(inclusive in range)")]
public Vector2 randXrange, randYrange, randZrange;
private float timer = 0;
private LineRenderer line;
private void Start()
{
timer = 0;
line = gameObject.GetComponent<LineRenderer>();
StartCoroutine(RedrawLaser());
}
private void Update()
{
if (gameObject.tag != clonedLineTag)
{
if (timer >= updateFrequency)
{
timer = 0;
//Debug.Log("Redrawing line");
foreach (GameObject lineSplit in GameObject.FindGameObjectsWithTag(clonedLineTag))
Destroy(lineSplit);
StartCoroutine(RedrawLaser());
}
timer += Time.deltaTime;
}
else
{
line = gameObject.GetComponent<LineRenderer>();
StartCoroutine(RedrawLaser());
}
}
private IEnumerator RedrawLaser()
{
//Debug.Log("Running");
int lineSplit = 1;
int lineReflected = 1;
int posIndex = 1; //How many line segments are there
bool loopActive = true; //Is the reflecting loop active?
Vector3 lineDir = transform.forward; //direction of the next line
Vector3 lastLinePos = transform.localPosition; //origin of the next line
line.positionCount = 1;
line.SetPosition(0, transform.position);
RaycastHit hit;
while (loopActive)
{
//Debug.Log("Physics.Raycast(" + lastLinePos + ", " + lineDir + ", out hit , " + lineDist + ")");
if (Physics.Raycast(lastLinePos, lineDir, out hit, lineDist) && ((hit.transform.gameObject.tag == reflectLineTag) || (hit.transform.gameObject.tag == splitTag)))
{
//Debug.Log("Bounce");
lineReflected++;
posIndex += 3;
line.positionCount = posIndex;
line.SetPosition(posIndex - 3, Vector3.MoveTowards(hit.point, lastLinePos, lineWidth));
line.SetPosition(posIndex - 2, hit.point);
line.SetPosition(posIndex - 1, hit.point);
line.startWidth = lineWidth;
line.endWidth = lineWidth;
lastLinePos = hit.point;
//Vector3 prevDirection = lineDir; for other method of splitting the line
lineDir = Vector3.Reflect(lineDir, hit.normal);
if (hit.transform.gameObject.tag == splitTag)
{
//Debug.Log("Split");
if (lineSplit >= maxSplit)
{
//Debug.Log("Max split reached");
}
else
{
//Debug.Log("Splitting");
lineSplit++;
for (int k = 0; k < maxSliptPerObj; k++)
{
GameObject clone = Instantiate(gameObject, hit.point, Quaternion.FromToRotation(hit.point, new Vector3
(Random.Range(hit.normal.x + randXrange.x, hit.normal.x + randXrange.y),
Random.Range(hit.normal.y + randYrange.x, hit.normal.y + randYrange.y),
Random.Range(hit.normal.z + randZrange.x, hit.normal.z + randZrange.y))));//Use Quaternion.LookRotation(prevDirection) to send line clone through the obj
clone.GetComponent<LineRenderer>().startColor = Color.red;
clone.GetComponent<LineRenderer>().endColor = Color.red;
clone.name = clonedLineTag;
((GameObject)clone).tag = clonedLineTag;
}
}
}
}
else
{
//Debug.Log("No bounce");
lineReflected++;
posIndex++;
line.positionCount = posIndex;
//Vector3 lastPos = lastLinePos + (lineDir.normalized * lineDist);for debug
//Debug.Log("InitialPos " + lastLinePos + " Last Pos" + lastPos);
line.SetPosition(posIndex - 1, lastLinePos + (lineDir.normalized * lineDist));
loopActive = false;
}
if (lineReflected > maxBounce)
loopActive = false;
}
yield return new WaitForEndOfFrame();
}
}
So do you need to find a segment of the existing LineRenderer? If you have start and end point, you can find the closest one for each in the line array, iterates the collection to find closest for each them and then copy all items in between into a new array. That would be your segment.
Thank you! :) I have already done the method to find the point and now i try to rotate it(when it faces a reflection surface) without cloning and setting rotation of a clone.
Have you thought of taking each point of the result collection and then pass them one by one into Vector3.Reflect ? Then you'd get a new collection of points reflected against the plane.