Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by fjg3d · Feb 14, 2017 at 06:26 AM · listraycastingnormalshitaverage

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

Comment
Add comment · Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image bad_pixel_ru · Feb 18, 2017 at 12:23 AM 0
Share

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

avatar image fjg3d bad_pixel_ru · Feb 18, 2017 at 01:56 AM 0
Share

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.

avatar image fjg3d · Feb 18, 2017 at 10:15 PM 0
Share

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; 
 }

avatar image fjg3d · Feb 19, 2017 at 10:51 PM 0
Share

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);
     }

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by bad_pixel_ru · Feb 19, 2017 at 10:49 PM

Debug.DrawRay(tProbes[i].transform.position, pRay, Color.black, normalLength);

Refer to the Unity documentation - all overloaded DrawRay() 4th parameter is float duration

averageTerrainPoint = surfPositions[ii] / surfPositions.Count;

Here you are overwrighting value stored in 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
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

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

Can anyone help me modify this script? (C#) 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges