Solved: Linerender/raycast reflection filtering

Updated on June 16, 2017 in [A] Unity Scripting
Share on Facebook0Tweet about this on TwitterShare on Google+0Share on Reddit0
2 on June 15, 2017

This is really bugging me, I’ve tried asking on StackExchange as well as Unity coders I know, and so far I haven’t been able to find help.

 

 

 

 

 

 

 

I’m working on a game for a game jam (I asked, asking for help is permitted :-)) involving lasers that reflect off of mirrors that are adjusted by the player to make the laser hit a target. Thanks to some tutorials, I managed to get the lasers to reflect, but they reflect off of everything and won’t stop unless I manually set a number of reflections to stop at.

 

 

 

 

 

 

 

I’ve tried adding an if statement to break the reflection loop if it doesn’t hit a mirror, as you’ll see in the code, but it just results in a laser going off on a weird angle before hitting the non-mirror target.(The version I posted on StackExchange reflected after, this is a slight improvement but doesn’t help much.)

 

 

 

 

 

 

 

I should add that I’m very new at this. I’m basically figuring things out as I go for this game jam. So, I know it’s probably a simple mistake, that I need to move the if to somewhere specific,  or maybe I followed the completely wrong tutorial, but I just can’t see it.

 

 

 

 

 

 

 

Can anybody please point me to the mistake?

 

 

 

 

 

 

 

 
 
 
 
 
 
 
void Update()
{
//clamp the number of reflections between 1 and int capacity 
nReflections = Mathf.Clamp(nReflections, 1, nReflections);
//cast a new ray forward, from the current attached game object position 
ray = new Ray(goTransform.position, goTransform.forward);
 
 
 
 
 
 
 
//represent the ray using a line that can only be viewed at the scene tab 
Debug.DrawRay(goTransform.position, goTransform.forward * 100, Color.magenta);
 
 
 
 
 
 
 
//set the number of points to be the same as the number of reflections 
numPoints = nReflections;
//make the lineRenderer have that number of points 
lineRenderer.positionCount = numPoints;
//Set the first point of the line at the current attached game object position 
lineRenderer.SetPosition(0, goTransform.position);
 
 
 
 
 
 
 
lineRenderer.loop = false;
 
 
 
 
 
 
 
for (int i = 0; i <= nReflections; i++)
{
 
 
 
 
 
 
 
//If the ray hasn't reflected yet
 
 
 
 
 
 
 
if (Physics.Raycast(ray.origin, ray.direction, out hit, 100) && hit.collider.tag != "Mirror")
{
break;
}
 
 
 
 
 
 
 
if (i == 0)
{
 
 
 
 
 
 
 
//Check if the ray has hit something 
if (Physics.Raycast(ray.origin, ray.direction, out hit, 100))//cast the ray 100 units at the specified direction 
{
//the reflection direction is the reflection of the current ray direction flipped at the hit normal 
direction = Vector3.Reflect(ray.direction, hit.normal);
//cast the reflected ray, using the hit point as the origin and the reflected direction as the direction
 
 
 
 
 
 
 
ray = new Ray(hit.point, direction);
//Draw the normal - can only be seen at the Scene tab, for debugging purposes 
Debug.DrawRay(hit.point, hit.normal * 3, Color.blue);
//represent the ray using a line that can only be viewed at the scene tab 
Debug.DrawRay(hit.point, direction * 100, Color.magenta);
 
 
 
 
 
 
 
//Print the name of the object the cast ray has hit, at the console 
//Debug.Log("Object name: " + hit.transform.name);
 
 
 
 
 
 
 
//if the number of reflections is set to 1 
if (nReflections == 1)
{
//add a new vertex to the line renderer 
lineRenderer.positionCount = ++numPoints;
}
 
 
 
 
 
 
 
//set the position of the next vertex at the line renderer to be the same as the hit point 
lineRenderer.SetPosition(i + 1, hit.point);
 
 
 
 
 
 
 
}
}
else // the ray has reflected at least once 
{
//Check if the ray has hit something 
if (Physics.Raycast(ray.origin, ray.direction, out hit, 100))//cast the ray 100 units at the specified direction 
{
//the refletion direction is the reflection of the ray's direction at the hit normal 
direction = Vector3.Reflect(direction, hit.normal);
//cast the reflected ray, using the hit point as the origin and the reflected direction as the direction 
ray = new Ray(hit.point, direction);
//Draw the normal - can only be seen at the Scene tab, for debugging purposes 
Debug.DrawRay(hit.point, hit.normal * 3, Color.blue);
//represent the ray using a line that can only be viewed at the scene tab 
Debug.DrawRay(hit.point, direction * 100, Color.magenta);
 
 
 
 
 
 
 
//Print the name of the object the cast ray has hit, at the console 
// Debug.Log("Object name: " + hit.transform.name);
 
 
 
 
 
 
 
//add a new vertex to the line renderer
 
 
 
 
 
 
 
lineRenderer.positionCount = ++numPoints;
 
 
 
 
 
 
 
//set the position of the next vertex at the line renderer to be the same as the hit point 
lineRenderer.SetPosition(i + 1, hit.point);
}
}
 
 
 
 
 
 
 
}
}
 
 
 
 
 
 
 

 

 

 

 

 

 

 

Image of the problem (the upload image button doesn’t seem to like me):

 

 

 

https://1drv.ms/i/s!Aj0TjF5ApmITj-IFExlVzqaD7YydAg

 

 

 

*ETA: If anybody can tell me how to get this text box to keep my code formatting, I’d very much appreciate it too!

  • Liked by
Reply
0 on June 15, 2017

Ok, the issue apparently has absolutely nothing to do with the if statement, as it still happens if I take it out and leave the number of reflections higher than 2. So, looks like there’s a general problem with the script. If anybody can see what it might be, I’d very much appreciate it, but otherwise I think it’s back to searching for new tutorials.

  • Liked by
Reply
Cancel
0 on June 16, 2017

A user on itch.io (adroitconceptions) helped me solve this, As suspected, the whole thing was messed up. Including working code here for anybody who may be having similar problems. 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent (typeof(LineRenderer))]
public class RayCastReflection : MonoBehaviour
{
    //this game object's Transform
    private Transform goTransform;
    //the attached line renderer
    private LineRenderer lineRenderer;
    //a ray
    private Ray ray;
    //a RaycastHit variable, to gather informartion about the ray's collision
    private RaycastHit hit;
    //reflection direction
    private Vector3 direction;
    //the number of reflections
    public int nReflections = 2;
    //max length
    public float maxLength = 100f;
    //the number of points at the line renderer
    private int numPoints;
    //private int pointCount;
    void Awake ()
    {
        //get the attached Transform component  
        goTransform = this.GetComponent<Transform> ();
        //get the attached LineRenderer component  
        lineRenderer = this.GetComponent<LineRenderer> ();
    }
    void Update ()
    {
        //clamp the number of reflections between 1 and int capacity  
        nReflections = Mathf.Clamp (nReflections, 1, nReflections);
        ray = new Ray (goTransform.position, goTransform.forward);    
        //start with just the origin
        lineRenderer.positionCount = 1;
        lineRenderer.SetPosition (0, goTransform.position);
        float remainingLength = maxLength;
        //bounce up to n times
        for (int i = 0; i < nReflections; i++) {
            // ray cast
            if (Physics.Raycast (ray.origin, ray.direction, out hit, remainingLength)) {
                //we hit, update line renderer
                lineRenderer.positionCount += 1;
                lineRenderer.SetPosition (lineRenderer.positionCount - 1, hit.point);
                // update remaining length and set up ray for next loop
                remainingLength -= Vector3.Distance (ray.origin, hit.point);
                ray = new Ray (hit.point, Vector3.Reflect(ray.direction, hit.normal));
                // break loop if we don't hit a Mirror
                if (hit.collider.tag != "Mirror")
                    break;
            } else {
                // We didn't hit anything, draw line to end of ramainingLength
                lineRenderer.positionCount += 1;
                lineRenderer.SetPosition (lineRenderer.positionCount - 1, ray.origin + ray.direction * remainingLength);
                break;
            }
        }
    }
}
  • Liked by
Reply
Cancel