Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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
0
Question by madmike6537 · Mar 01, 2013 at 12:06 AM · listarrays

Need some help looping through an array or list

Hi Unity,

I am stumped on a script I am trying to write, hoping you can come through.

Basically I have an array full of cubes with a a transform of course. I need to loop through this array and find any cubes that have a matching position.x or position.y. Then I need to count how many of of the cubes match in that axis.

The other problem is I need to do this in the update function because cubes will be added continuously up to a point.

I am pulling my hair out over this one!!

     // Update is called once per frame
     void Update () 
     {
         //Add all cube "lines" into an array
         lines = GameObject.FindGameObjectsWithTag("Line");
         //loop through array
         for(int cnt = 0; cnt < lines.Length; cnt++)
         {
             //store the current position.x of the index??
             tempPosX = lines[cnt].transform.position.x;
             //if there is more than one cube..
             if(cnt >= 1)
             {
                 //and if this index matches the transform of the one of previous ones..?? I dont really know
                 //where I am going at this point..
                 if(tempPosX == lines[cnt].transform.position.x)
                 {
                     //We found a matching line cube on the x axis.
                     //Yay.. cubeCountX++? I dont know..
                 }
             }
         }
         
     }

I tried something like the above but just cant figure out where to go from here..

If you are wondering what I am trying to make with this, its essentially a line drawn using cubes that are instantiated. I am trying to find the lenghth of the line and therefore be able to canculate square feet. (I am trying to make an app that you can calculate square feet by drawing an outline of a room).

Thanks a million!!

Comment
Add comment
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

2 Replies

· Add your reply
  • Sort: 
avatar image
3
Best Answer

Answer by hoy_smallfry · Mar 01, 2013 at 01:26 AM

Iterating through so many elements in an array is a computationally exhaustive procedure. Think about the scenario here: you have to check every object with every other object.

If there's only 2 objects, there's only 1 comparison. If there are 3 objects, its 2 comparisons. With 4 objects, 6 comparisons. With 10, it's 45; with 11, 55; with 12, 66

Just 25 objects will raise it to 300 comparisons! This is referred to as the handshake problem in mathamatics. The number grows at a high rate, and those comparisons can give your CPU too much to do if the number is too high.

Thankfully, we can leverage memory against computational time.

So, you're trying to figure out which objects share the same axis value, right? Imagine that you can group GameObjects you come across into groups labeled by the axis value.

In C#, the perfect container for such a task is System.Collections.Generic.Dictionary. Just like an array associates data with an integer index value, a dictionary can associate data with any key, like so:

 // create a container that associates a string with an int
 Dictionary<string, int> map = new Dictionary<string, int>();

 map.Add("Bob", 1);
 Debug.Log(map["Bob"]) // prints out 1 to the log
 map["Bob"] = 5; // makes the element at "Bob" equal to 5 

With dictionaries, you can associate any data type as the key

 // create a container that associates a float with an int
 Dictionary<float, int> map = new Dictionary<float, int>();

 map.Add(3.14f, 1);
 Debug.Log(map[3.14f]) // prints out 1 to the log
 map[3.14f] = 5; // makes the element at 3.14f equal to 5 

So, if you make a dictionary where the data is a list of GameObjects, we have a way of grouping GameObjects by float values.

 Dictionary<float, List<GameObject> > xAxisMap = new Dictionary<float, List<GameObject> >();

You can then loop through your array, and place each one in the list that matches the X-axis value:

 var lines = GameObject.FindGameObjectsWithTag("Line");
 //loop through array
 for(int cnt = 0; cnt < lines.Length; cnt++)
 {
     var x = tempPosX = lines[cnt].transform.position.x;

     /* tries to find the value at x. if it was found, saves the value to 
      * 'group' and returns true. if not found, returns false. */
     List<GameObject> group = null;
     var wasFound = xAxisMap.TryGetValue(x, out group);

     // if it was NOT found, then...
     if (!wasFound)
     {
         // create a new group
         group = new List<GameObject>();

         // add the list to the dictionary at x. 
         xAxisMap.Add(x, group);
     }
  
     // now that we have the group, we add our gameObject to it
     group.Add(lines[cnt]);
 }

Doing it this way, we've now sorted all the lines that are on the same X value into groups. We only have to loop through the lines once. A much better alternative to checking each object against each other object.

To get the x values all your objects are on:

 foreach (float x in xAxisMap.Keys())
 {
     // do something with this x value!
 }

To iterate through your groups:

 foreach (List<GameObjects> group in xAxisMap.Values())
 {
     // do something with this group!
 }

To get the x values and the groups:

 foreach (var pair in xAxisMap)
 {
     // do something with this x value!
     Debug.Log("Key: " + pair.Key);

     // do something with this group!
     List<GameObject> group = pair.Value;
 }

Hope that helps!

Comment
Add comment · Show 10 · 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
avatar image madmike6537 · Mar 01, 2013 at 01:31 AM 0
Share

That was one hell of an answer! Thanks! I have been wanting to start using dictionaries but wasnt quite sure where to start. This really helps me see how easy they can be to use, and how useful as well. Thanks much!!!!

avatar image hoy_smallfry · Mar 01, 2013 at 01:35 AM 0
Share

fixed the definition for xAxis$$anonymous$$ap. it got stripped out probably because the submission throught it was an HT$$anonymous$$L tag or something

avatar image madmike6537 · Mar 01, 2013 at 01:36 AM 0
Share

No problem, I was able to figure out what you meant. I am trying this now and will report back with results.

avatar image madmike6537 · Mar 01, 2013 at 01:42 AM 0
Share

Can you tell me a bit more about what this does? I think I get the rest of it: List group = null; (hmm doesnt want to display right list of GameObjects = null basically)

And where does wasFound become true exactly?

avatar image madmike6537 · Mar 01, 2013 at 01:45 AM 0
Share

Never $$anonymous$$d I figured out where wasFOund becomes true. Ya lines 9 and 10 are a bit over my head, but I will read up on that code and try and understand it.

Show more comments
avatar image
0

Answer by madmike6537 · Mar 03, 2013 at 04:42 AM

Here is what I ended up with for anyone interested out there. I realize it wasnt really necessary to put everything in a function, but I was trying to fix something and then I ended up just leaving it that way.

 public class SquareFootage : MonoBehaviour 
 {
     //array to hold all the line cubes
     GameObject[] lines;
     private float lastLineCount = 0;
     
     public Dictionary<float, List<GameObject> > xAxisMap = new Dictionary<float, List<GameObject>>();
     
     // Update is called once per frame
     void Update () 
     {
         lines = GameObject.FindGameObjectsWithTag("Line");
         
         if(lines.Length > lastLineCount)
         {
             print ("new line added");
             BuildLineGroups();
             lastLineCount = lines.Length;
         }
         
 
     }
     
     void BuildLineGroups()
     {
         
         //loop through array of lines
         for(int cnt = 0; cnt < lines.Length; cnt++)
         {
             print ("Looping through lines");
             var x = lines[cnt].transform.position.x;
             
             //Check to see if there is already an entry for x
             //if there is, then it returns true otherwise its false
             List<GameObject> myList;
             bool wasFound = xAxisMap.TryGetValue(x, out myList);
             
             if(wasFound)
             {
                 print("matching group found for value " + x);
                 //check if this is a line that was already put into a group 
                 //we do this by checking the "key" for the entry that it matches and we check to see if there is a matching transform.position in that entry
                 for(int i = 0; i<myList.Count; i++)
                 {
                     //if the position of this line matches that of any in the listed with key "X" then get outta here..
                     if(myList[i].transform.position == lines[cnt].transform.position)
                     {
                         print ("existing line found that matches this position, no line will be added");
                         return;
                     }
                     
                     else
                     {
                         print ("line added to existing group" + x);
                         //otherwise, add this specific cube "line" to that group.
                         xAxisMap[x].Add(lines[cnt]);
                     }    
                 }
             }
 
             
             //if no group with this position was found..
             if(!wasFound)
             {
                 print ("new group created: " + x);
                 //add to list as entry x(a float)
                 xAxisMap.Add(x, new List<GameObject>());
                 xAxisMap[x].Add(lines[cnt]);
             }
         }
     }
     
     void OnGUI()
     {
         foreach(KeyValuePair<float, List<GameObject>> line in xAxisMap)
         {
             Debug.Log(line.Key + "=" + line.Value.Count);
             if(line.Value.Count > 1)
             {
                 GUI.TextArea(new Rect(0,0,100,50), line.Value.Count.ToString());
             }
         }
     }
 }
Comment
Add comment · Show 2 · 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
avatar image madmike6537 · Mar 03, 2013 at 04:49 AM 0
Share

But it still has some issues. It always thinks my line is in the same spot as another. Not sure if you can compare Vector 3's like I did or not, maybe I will post this in a new question.

avatar image hoy_smallfry · Mar 04, 2013 at 03:19 PM 0
Share

On the contrary, I believe programmers should use functions whenever they can.

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

10 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

A node in a childnode? 1 Answer

How do i convert this code snippet to a list? 1 Answer

How to store gameobjects with specific scripts in a list ? 1 Answer

[C#]Inventory script help. 3 Answers

UnityScript for unique simpleJSON lists 0 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