- Home /
List Sort not Returning Value
Hi guys,
I'm trying to make a function that scans around an object using rays at a given number of rays per cycle, or granularity. If the ray does not return with a hit, I want to feed this into a list that refreshes every frame (Others have suggested I use lists for this purpose over arrays).
I then want to sort the list based on the dot product with the players position (the best match being the one with the largest dot product, i.e closest to one, ray with direction nearest to parallel to player position).
I then want to return the ray's direction for the frame in question.
At the moment, the following code doesn't seem to see anything in the list although the step seems to be updating correctly; I find this hard to believe as my Raycast distance is set very small. Can anyone see why this isn't working?
Cheers,
Popuppirate
private System.Collections.Generic.List<Ray> free_rays;
private System.Collections.Generic.List<RaycastHit> free_rays_info;
private int granularity=100;
public float step;
public float safe_zone;
public Vector3 step_target;
// Use this for initialization
void Start () {
step = 0;
safe_zone = 0.1f;
free_rays = new System.Collections.Generic.List<Ray>();
}
// Update is called once per frame
void Update () {
GameObject player=GameObject.FindGameObjectWithTag ("Player");
if (step<=360){
for (int i=0; i<granularity; i++) {
Vector3 scan = Quaternion.AngleAxis (step, transform.forward) * transform.forward;//MAKE NEW VECTOR STEP DEGREES FROM TRANSFORM.FORWARDS
Ray ray = new Ray (transform.position, scan);//MAKE RAY IN THIS DIRECTION
RaycastHit hit;
if (Physics.Raycast(ray, out hit, safe_zone)){
continue;
} else {//IF DIDN'T HIT READ INTO FREE_RAYS
free_rays.Add(ray);
}
step+=(360f/(granularity*1.0f));
}
free_rays.Sort (delegate (Ray ray1, Ray ray2) {
return Vector3.Dot (ray1.direction, player.transform.position).CompareTo (Vector3.Dot(ray1.direction, player.transform.position));
});//SORT BASED ON DOT PRODUCT
Vector3 step_target= free_rays[free_rays.Count-1].direction; //RETURN LARGEST DOT PRODUCT (CLOSEST TO 1).
} else {
free_rays.Clear(); //ON END OF CYCLE, CLEAR LIST AND RESET STEP.
step=0;
}
}
}
Answer by zharik86 · Oct 27, 2014 at 07:05 PM
I think, you must change your delegate little (second parametr in compare is "ray2"):
free_rays.Sort (delegate (Ray ray1, Ray ray2) {
return Vector3.Dot (ray1.direction, player.transform.position).CompareTo (Vector3.Dot(ray2.direction, player.transform.position));
});
But maybe, instead ray better use Physics.OverlapSphere(). I hope that it will help you.
Hi zharik86,
Have certainly tried using your suggestion as follows, though my method is rather different to the above. What I do ins$$anonymous$$d is find all the sphere overlap colliders and draw a ray between the rigidbody object and the collider, applying a force the opposite way along the ray to push it away from the collider until the point at which the sphere no longer collides, after which it will apply a force towards a target. While this does produce a force vector, I do not observe any force on the object.
Really appreciate your help!
Cheers!
using UnityEngine;
using System.Collections;
public class Pathfinder_Control : $$anonymous$$onoBehaviour {
public float safe_zone;
public GameObject player;
public Vector3 target_vector;
public Vector3 force;
private float velocity;
// Use this for initialization
void Start () {
safe_zone = 0.5f;
velocity = 1f;
GameObject player=GameObject.FindGameObjectWithTag ("Player");
}
// Update is called once per frame
void Update () {
target_vector = player.transform.position;
Avoid ();
Debug.DrawRay (transform.position, force, Color.green);
}
void Avoid(){
Collider[] hitColliders = Physics.OverlapSphere(transform.position, safe_zone);
if (hitColliders != null) {
for (int i=0; i<hitColliders.Length; i++) {
Ray ray = new Ray(transform.position, hitColliders[i].transform.position);
force=-ray.direction;
transform.rigidbody.AddForce(-ray.direction);
}
} else {
Vector3 targ_dir = target_vector-transform.position;
force=-transform.position;
transform.rigidbody.AddForce(-transform.position);
}
}
}
@popuppirate I'm not very well understood that it is necessary to you. Probably, it is attached to "player". But looking at your code, I see some errors. Ray.direction value is the normalized vector, i.e. its length is equal 1. It seems to me to you it is necessary to change a few AddForce() method:
public float myForce = 100.0f;
void Avoid() {
Collider[] hitColliders = Physics.OverlapSphere(transform.position, safe_zone);
if (hitColliders != null) {
for (int i=0; i<hitColliders.Length; i++) {
Ray ray = new Ray(transform.position, hitColliders[i].transform.position);
force=-ray.direction;
transform.rigidbody.AddForce(-ray.direction * myForce); //more power
}
} else {
Vector3 targ_dir = target_vector-transform.position;
force=-transform.position.normalized; //maybe normalize
transform.rigidbody.AddForce(force * myForce); //more power
}
}
Cheers for a really insightful answer! I'm sure this code will come in useful at some point, but I discovered the glory of the Navmesh last night- allows pathfinding without my naive attempt to code it myself!
Rather, I'm pleased that you've drawn (no pun intended) my attention to the fact that my ray.direction returns a normalised vector, which i wasn't aware of.
Thanks again!
Popuppirate
Your answer
Follow this Question
Related Questions
A node in a childnode? 1 Answer
Switching Target during Target Lock 1 Answer
How to arrange list 3 Answers
Problem using IComparer to sort list of GameObjects 2 Answers
SQLite Sort and or List Sort 1 Answer