- Home /
Raycast across angle?
Hi, I have a javascipt in progress here :
var anglePartition : float = maxAngle/totalRays;
var startDir : Vector3 = transform.localEulerAngles;
for (var i:int=0;i<totalRays;i++){
var hit : RaycastHit;
if (Physics.Raycast (transform.position, startDir, hit, distance))
{
Debug.DrawLine (transform.position, hit.point, Color.red);
}
startDir.y += anglePartition;
}
I'm trying to raycast a number of times over a specified angle over the y axis. After fiddling with the code for a few hours and having no success, I figured I should ask the question here instead. I'm not an expert on scripting, nor am I in Quaternions/Angles. Does anyone care to explain what I'm doing wrong here, and what I should do?
Answer by AlucardJay · Dec 12, 2012 at 10:04 AM
Edited :
Ok, I have written a new answer for the new information provided.
This script works by calculating a point that is at an angle to the object forward. This angle is then changed by the angle divided by the number of times (segments).
press play, and left click mouse button to briefly see the lines of the raycast (you can spam the LMB for testing just to see the lines where the Linecast is checking. While playing, change the angle and the segments, just make sure that segments is always less than theAngle. And I have made these variables integers, though floats could be used, this is probably accurate enough for what you need.
#pragma strict
public var distance : float = 5.0f;
public var theAngle : int = 45;
public var segments : int = 10;
function Update()
{
if ( Input.GetMouseButtonDown(0) )
{
RaycastSweep();
}
}
function RaycastSweep()
{
var startPos : Vector3 = transform.position; // umm, start position !
var targetPos : Vector3 = Vector3.zero; // variable for calculated end position
var startAngle : int = parseInt( -theAngle * 0.5 ); // half the angle to the Left of the forward
var finishAngle : int = parseInt( theAngle * 0.5 ); // half the angle to the Right of the forward
// the gap between each ray (increment)
var inc : int = parseInt( theAngle / segments );
var hit : RaycastHit;
// step through and find each target point
for ( var i : int = startAngle; i < finishAngle; i += inc ) // Angle from forward
{
targetPos = (Quaternion.Euler( 0, i, 0 ) * transform.forward ).normalized * distance;
// linecast between points
if ( Physics.Linecast( startPos, targetPos, hit ) )
{
Debug.Log( "Hit " + hit.collider.gameObject.name );
}
// to show ray just for testing
Debug.DrawLine( startPos, targetPos, Color.green );
}
}
Let me know =]
Original answer
I found this question very interesting so decided to have a go =]
A list of 'nodes' is generated based on the number of segments in the arc and the range of a circle. Set the circle range with curveAmount (eg 90 = 90', 360' = full circle). Also set the radius and the number of segments (this can all be done in realtime within the script.
This is just an example with some debug lines to demonstrate. Attach script to empty gameObject, hit play and then click left-mouse-button. change the values in the inspector while playing, also change the position and rotation of the empty. The lines should show that the raycast is done relative to the objects forward.
#pragma strict
import System.Collections.Generic;
public var radius : float = 5.0;
public var segments : int = 12;
public var curveAmount : float = 360.0;
private var calcAngle : float;
var nodes : List.< Vector3 > = new List.< Vector3 >(); // private , left out to check in inspector
function Update()
{
if ( Input.GetMouseButtonDown(0) )
{
CalculatePoints();
DrawLines(); // just for testing
CheckForHits();
}
}
function CalculatePoints()
{
nodes.Clear();
calcAngle = 0;
// Calculate Arc on Y-Z
for ( var i : int = 0; i < segments + 1; i ++ )
{
var posY : float = Mathf.Cos( calcAngle * Mathf.Deg2Rad ) * radius;
var posZ : float = Mathf.Sin( calcAngle * Mathf.Deg2Rad ) * radius;
nodes.Add( transform.position + ( transform.up * posY ) + ( transform.forward * posZ ) );
calcAngle += curveAmount / parseFloat(segments);
}
}
function CheckForHits()
{
var hit : RaycastHit;
for ( var i:int = 0; i < nodes.Count - 1; i ++ )
{
if ( Physics.Linecast( nodes[i], nodes[i + 1], hit ) )
{
Debug.Log( "Hit " + hit.collider.gameObject.name );
}
}
}
function DrawLines()
{
for ( var i:int = 0; i < nodes.Count - 1; i ++ )
{
Debug.DrawLine( nodes[i], nodes[i + 1], Color.red, 1.5 );
}
}
It's probably my fault for not being clear when asking the question, I should have named the title "Raycast across angle". $$anonymous$$y intention is actually not to raycast across a circle/arc, but to raycast a specified amount of times over a certain angle on the y-axis. For excample, raycast 10 times over the course of 45 degrees on the y-axis. Thanks for spending time for the answer!
Would it be possible to make an image to illustrate, edit the question to include the image. $$anonymous$$y understanding now is that you want to sweep a raycast infront at different angles, e.g :
I have edited my answer, hopefully I have understood correctly, please let me know =]
Thanks for the great answer! Although I might need to study and modify the script a little to suit my needs. Thanks again!
Answer by JimPD · Dec 22, 2017 at 12:08 PM
Original Converted to C#
public float radius = 5.0f;
public int segments = 12;
public float curveAmount = 360.0f;
private float calcAngle;
private List<Vector3> nodes;
public void Start()
{
nodes = new List<Vector3>();
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
CalculatePoints();
DrawLines(); // just for testing
CheckForHits();
}
}
private void CalculatePoints()
{
nodes.Clear();
calcAngle = 0;
// Calculate Arc on Y-Z
for (int i = 0; i < segments + 1; i++ )
{
float posY = Mathf.Cos(calcAngle * Mathf.Deg2Rad) * radius;
float posZ = Mathf.Sin(calcAngle * Mathf.Deg2Rad) * radius;
nodes.Add(transform.position + (transform.up * posY) + (transform.forward * posZ));
calcAngle += curveAmount / (float)segments;
}
}
private void CheckForHits()
{
RaycastHit hit;
for (int i = 0; i < nodes.Count - 1; i++ )
{
if (Physics.Linecast(nodes[i], nodes[i + 1], out hit))
{
Debug.Log("Hit " + hit.collider.gameObject.name);
}
}
}
private void DrawLines()
{
for (int i = 0; i < nodes.Count - 1; i++)
{
Debug.DrawLine(nodes[i], nodes[i + 1], Color.red, 1.5f);
}
}
Answer by ludomitch198 · Jun 05, 2020 at 10:13 AM
C# implementation for edited answer:
public void RaycastSweep()
{
float distance = 40.0f;
float theAngle = 25.0f;
float segments = 10.0f;
Vector3 startPos = cam.transform.position; // umm, start position !
Vector3 targetPos = Vector3.zero; // variable for calculated end position
int startAngle = Convert.ToInt32(-theAngle * 0.5f); // half the angle to the Left of the forward
int finishAngle = Convert.ToInt32(theAngle * 0.5f); // half the angle to the Right of the forward
// the gap between each ray (increment)
int inc = Convert.ToInt32(theAngle / segments);
RaycastHit hit;
// step through and find each target point
for (int i = startAngle; i < finishAngle; i += inc ) // Angle from forward
{
targetPos = (Quaternion.Euler( 0, i, 0 ) * transform.forward).normalized * distance;
// linecast between points
if ( Physics.Linecast( startPos, targetPos, out hit ) )
{
Debug.Log( "Hit " + hit.collider.gameObject.name );
}
// to show ray just for testing
Debug.DrawLine( startPos, targetPos, Color.green );
}
}