- Home /
The question is answered, right answer was accepted
Making an Array of Rays
Hi all,
I'm trying to perform a Raycast scan around an object with a set granularity (i.e. 100 rays per 360 degrees) and read all of the Rays I generate that do not hit something and those that do into separate Arrays. However, the code I have written comes up with an 'object not set to reference of an object' and I can't see why.
Just for the record, I'd rather use arrays than lists for this since I want this to work as quickly and efficiently as possible, but if lists work I won't complain!
Any thoughts would be really appreciated!
Cheers,
Popuppirate
public Ray[] free_rays;
public Ray[] hit_rays;
public RaycastHit[] hit_ray_info;
public int granularity;
public float step;
public float safe_distance;
// Use this for initialization
void Start () {
safe_distance = 3f;
granularity = 100;
step = 0;
}
// Update is called once per frame
void Update () {
if (step <= 360f) {
for (int i=0; i<granularity; i++) {
RaycastHit hit;
Vector3 scan = Quaternion.AngleAxis (step, transform.forward) * transform.forward;
Ray ray = new Ray (transform.position, scan);
if (Physics.Raycast (ray, out hit, safe_distance)) {
hit_rays [i] = ray;
hit_ray_info [i] = hit;
} else {
free_rays [i] = ray; //ERROR HERE
}
step +=360f / granularity * 1.0f;
}
}else {
step =0f;
}
Answer by fafase · Oct 26, 2014 at 06:25 PM
I would guess the arrays are not set to any size.
Though List is pretty much as fast as Array that you would not consider them in this case. Particularly since you are making a mess of your arrays. You place the hit in the arrays based on the value of i. How do you know where is the next one in this case? I give you a clue, you don't.
This is what it is about to look like:
Index ArrayHit ArrayNoHit
0 Hit null
1 Hit null
2 null NoHit
3 Hit null
4 null NoHit
5 Hit null
With a list you would add as they come and one list is full of hit and the other full of no hit and no space between each of them.
And this is what it is about to look like:
Index ListHit ListNoHit
0 Hit NoHit
1 Hit NoHit
2 Hit
3 Hit
You could probably get arrays to work for you, and not have to worry about the 'null padding' type situation described in this answer, but it would be at the expense of readability.
I think it would be much better to use a list here (since things like this are pretty much exactly the reason the list object exists).
Thanks fafase,
The reason I'm using arrays is because I'm doing a lot of fast sorting. For example, I want to sort my arrays by various conditions.
As such, here is my full code that I've written to instantiate and sort my arrays; I don't know how I'd go about sorting the lists in such a way. If you would take a glance I'd appreciate it PS. no room for comments:
using UnityEngine;
using System.Collections;
public class Pathfinder_Control : $$anonymous$$onoBehaviour {
public Vector3 destination;
public Ray[] free_rays;
public Ray[] hit_rays;
public int granularity;
public float step;
public float safe_distance;
public Vector3 move_direction;
private Ray temp_sort_free_ray;
private Ray temp_sort_hit_ray;
private float temp_angle;
// Use this for initialization
void Start () {
safe_distance = 3f;
granularity = 100;
step = 0;
}
// Update is called once per frame
void Update () {
// transform.position = Vector3.Lerp (transform.position, destination, Time.deltaTime);
if (step <= 360f) {
for (int i=0; i<granularity; i++) {
RaycastHit hit;
Vector3 scan = Quaternion.AngleAxis (step, transform.forward) * transform.forward;
Ray ray = new Ray (transform.position, scan);
if (Physics.Raycast (ray, out hit, safe_distance)) {
hit_rays [i] = ray;
} else {
free_rays [i] = ray;
}
step +=360f / granularity * 1.0f;
}
}else {
step =0f;
}
for (int i=0; i<free_rays.Length; i++) {
for (int j=0; j<free_rays.Length; j++) {
float dot_i=1f-Vector3.Dot (destination, free_rays[i].direction);
float dot_j=1f-Vector3.Dot (destination, free_rays[j].direction);
if(dot_i<dot_j){
temp_sort_free_ray=free_rays[i];
free_rays[i]=free_rays[j];
free_rays[j]=temp_sort_free_ray;
}
}
}
for (int i=0; i<free_rays.Length; i++){
float angle_j=$$anonymous$$athf.Infinity;
float angle_k=$$anonymous$$athf.Infinity;
for (int j=0; i<hit_rays.Length; j++){
for(int k=0; k<hit_rays.Length; k++){
if ($$anonymous$$athf.Abs(Vector3.Angle(free_rays[i].direction, hit_rays[j].direction))<angle_j){
angle_j=Vector3.Angle(free_rays[i].direction, hit_rays[j].direction);
}if ($$anonymous$$athf.Abs (Vector3.Angle(free_rays[i].direction, hit_rays[j].direction))<angle_k){
angle_k=Vector3.Angle(free_rays[i].direction, hit_rays[k].direction);
}
if (angle_j<angle_k){
temp_sort_hit_ray=hit_rays[j];
hit_rays[j]=hit_rays[k];
hit_rays[k]=temp_sort_hit_ray;
}
}
}
RaycastHit hit_0;
RaycastHit hit_1;
Physics.Raycast (hit_rays [0], out hit_0);
Physics.Raycast (hit_rays[1], out hit_1);
if (Vector3.Distance (hit_0.point, hit_1.point)>safe_distance) {
move_direction=free_rays[i].direction;
}
}
transform.position = Vector3.$$anonymous$$oveTowards (transform.position, move_direction, 1f);
}
}
I am working to develop this further using lists; I shall let you guys know when it's done!
You can sort List the same as you sort an array. You create a method that will return -1,0 or 1 depending on the action, in your case it would be the comparison of the dot product then you pass that method in
list.Sort(Comparison$$anonymous$$ethod);
And you get a sorted list.
You posted that one on its own thread and I think you got an answer there so let's close this one shall we :) ?