- Home /
Average the hit info from a list of GameObject's RaycastHits.
Edit - I've updated this question with a better example. Here is an update with code and video.
Its easy to replicate this scene with a capsule GO, a few empty GO's tagged Probes Issues:
1) Why are the rays lingering after they are initially drawn?
2) Need help averaging the values of a list of hit.points and hit.normals - not sure why it places them back at 0, 0, 0.
public class Raycasting2 : MonoBehaviour
{
[Header("Probe Objects")]
public GameObject[] tProbes; //the terrain probe list
public List<Vector3> surfPositions;
public List<Vector3> surfNormals;
public float probeLength = 2f;
public float normalLength = 1f;
private Vector3 pRay;
private Vector3 averageTerrainNormal;
private Vector3 averageTerrainPoint;
private RaycastHit hit;
// Use this for initialization
void Start()
{
tProbes = GameObject.FindGameObjectsWithTag("Probes"); //grab the objects tagged "Probes"
pRay = transform.TransformDirection(Vector3.down) * probeLength;
}
void Update()
{
CastTerrainProbes();
}
void FixedUpdate()
{
}
void CastTerrainProbes()
{
for (int i = 0; i < tProbes.Length; i++)
{
Debug.DrawRay(tProbes[i].transform.position, pRay, Color.black, normalLength);
if (Physics.Raycast(tProbes[i].transform.position, pRay, out hit, probeLength))
{
Debug.DrawRay(hit.point, hit.normal, Color.red, normalLength);
}
surfPositions.Add(hit.point);
for (int ii = 0; ii < surfPositions.Count; ii++)
{
averageTerrainPoint = surfPositions[ii] / surfPositions.Count;
}
surfNormals.Add(hit.normal);
for (int ii = 0; ii < surfPositions.Count; ii++)
{
averageTerrainNormal = surfNormals[ii] += surfNormals[ii] / surfNormals.Count;
Debug.DrawRay(averageTerrainNormal, hit.normal, Color.cyan, normalLength);
}
}
}
}
Original Question I'd like to raycasthit from a list of 'terrain probe' objects and average the normal returned. I'm a bit stuck on how to I iterate over the list and create a ray on each list item. I can do this individually, but thought it would be more efficient to batch the raycast process. This is a specific part of another question that is probably too broad here. Original Question
1st: The 4th parameter of DrawRay() method is duration (time in seconds), not length.
2nd: Here averageTerrainPoint = surfPositions[ii] / surfPositions.Count;
you are overwriting your average on each iteration of the loop. Ins$$anonymous$$d of that, you should calculate sum of all values during the loop and divide it by values count just outside the loop
Thanks for the repy bad_pixel_ru
1st: should have caught that it was duration, thanks.
2nd: Outside of which loop? the initial tprobes loop or others?
3rd: Also, why are the drawrays for the averaged hits displaying at world zero, not somewhere near the terrain. See in video.
Ok, there is the next try.
I created a function that returns the average. The problem here is that the list of hit.normals keeps growing. I tried to set up a Vector3.Angle to check the difference between hit.normals, but it doesn't seem to work, and I'll eventually need to dump some of the entries anyhow.
Any ideas?
//get mesh normal data to rotate towards
public Vector3 GetAverageTerrainNormal()
{
//Iterate through the list of probes
for (int i = 0; i < tProbes.Length; i++)
{
//Draw and cast the rays
Debug.DrawRay(tProbes[i].transform.position, pRay, Color.black);
if (Physics.Raycast(tProbes[i].transform.position, pRay, out hit, probeLength))
{
//Draw each hit.normal
Debug.DrawRay(hit.point, hit.normal, Color.red);
}
}
//Add hit.normals to a list to be averaged only if there is a delta > 10
Vector3 currN = hit.normal;
float deltaN = Vector3.Angle(currN, hit.normal);
if(deltaN > 10f)
{
surfNormals.Add(hit.normal);
}
//Iterate through the list of normals
for (int ii = 0; ii < surfNormals.Count; ii++)
{
//Sum up
sumOfNormals += surfNormals[ii];
}
//Dividing the sum by the count, returning the average
averageTerrainNormal = sumOfNormals / surfNormals.Count;
return averageTerrainNormal;
}
Looks like I don't have enough permission to post comment...
bad_pixel_ru thanks for the reply.
1st: should have caught the 'duration' issue, thanks.
2nd: I'm afraid I'm not able to get your solution to work for your 2nd answer. Outside of which loop? the initial tProbes loop or one the others?
3rd: Also, why are the drawrays displaying at world zero, not somewhere near the terrain. See in video.
for (int i = 0; i < tProbes.Length; i++)
{
Debug.DrawRay(tProbes[i].transform.position, pRay, Color.black);
if (Physics.Raycast(tProbes[i].transform.position, pRay, out hit, probeLength))
{
Debug.DrawRay(hit.point, hit.normal, Color.white);
}
surfNormals.Add(hit.normal);
for (int ii = 0; ii < surfNormals.Count; ii++)
{
sumOfNormals = surfNormals[ii] += surfNormals[ii];
}
averageTerrainNormal = sumOfNormals / surfNormals.Count;
Debug.DrawRay(averageTerrainPoint, averageTerrainNormal, Color.yellow);
}
Answer by bad_pixel_ru · Feb 19, 2017 at 10:49 PM
Refer to the Unity documentation - all overloaded DrawRay() 4th parameter is
Debug.DrawRay(tProbes[i].transform.position, pRay, Color.black, normalLength);
float duration
Here you are overwrighting value stored in
averageTerrainPoint = surfPositions[ii] / surfPositions.Count
;
averageTerrainPoint
on each
for
iteration. No idea for what you are doing so, but it will surely not calculate average value anyway. You should sum your values and then divide it by values count
Your answer
Follow this Question
Related Questions
A node in a childnode? 1 Answer
How to distinguish between different collisions? 2 Answers
raycast destroying player? 2 Answers
Help Playing "Sound Clip" on RayCastHit? (RayCast help?) 2 Answers