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 pvzkiller · Oct 17, 2012 at 06:17 AM · loopforeachforbreak

Is having a "break" in a "foreach" loop that is itself inside a "for" loop breaking both loops?

Hi dear members,

Is having a "break" in a "foreach" loop -that is itself inside a "for" loop- breaking both loops (foreach is the direct one where the "break" command is called, but foreach is itself nested in a for loop) or only the direct one (foreach)?

I get no errors, but the behavior is not EXACTLY how I intend it to be, so I am wondering if the problem can originate from how the break command behaves... I want to stop the foreach loop on break, however the for loop should go on until g<4.

Part of my code I wonder about:

 for (g=1;g<4;g++)
 {
     if (g == 1)
     {
         gos = GameObject.FindGameObjectsWithTag("crabtag");
     }
     else if (g == 2) {
         gos = GameObject.FindGameObjectsWithTag("turtletag");
     }
     else if (g == 3)
     {
         gos = GameObject.FindGameObjectsWithTag("jellytag");
     }
 
     foreach(GameObject go in gos)
     {
         if (playerposx == go.transform.position.x && playerposy == go.transform.position.y)
         {
             if (g == 1)
             {
                 crabHere = true;
                 break;
             }
             else if (g == 2)
             {
                 turtleHere = true;
                 break;
             }
             else if (g == 3)
             {
                 jellyHere = true;
                 break;
             }
         }
         else
         {
             if (g == 1)
             {
                 crabHere = false;
             }
             else if (g == 2) 
             {
                 turtleHere = false;
             } 
             else if (g == 3)
             {
                 jellyHere = false;
             }
         }
     }
 }
Comment
Add comment · Show 5
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 Kryptos · Oct 17, 2012 at 07:34 AM 0
Share

I reindented your code. Next time try to use the code formatting option (button "010101").

avatar image fafase · Oct 17, 2012 at 07:46 AM 4
Share

Is this line

 if (playerposx == go.transform.position.x && playerposy == go.transform.position.y) 

getting any success? You are comparing float numbers. Those are really unlikely to be exactly the same. You might want to clamp the value within a range to optimize your chance of success.

avatar image Kryptos · Oct 17, 2012 at 01:21 PM 0
Share

@Fattie Well yes. That's part of my answer already, isn't it? =D

avatar image Fattie · Oct 17, 2012 at 01:40 PM 0
Share

fafase ... re your critical comment. they could also use "$$anonymous$$athf.approximately" (or should at least know about it).

avatar image fafase · Oct 18, 2012 at 10:29 AM 0
Share

Oh yes, there are various ways to achieve that, a couple of if statements would do it and avoid the tiny overhead of a function for instance.But I was just mentioning quickly that there could be something wrong there.

3 Replies

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

Answer by Demigiant · Oct 17, 2012 at 01:25 PM

Just to post a clear answer to the question: no ;)

Breaking within a loop will break only the exact loop you're in, without considering its parents.

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 Fattie · Oct 17, 2012 at 01:34 PM 2
Share

EXCELLENT.

avatar image Demigiant · Oct 17, 2012 at 01:37 PM 0
Share

Thanks! :D

avatar image whydoidoit · Oct 17, 2012 at 01:44 PM 1
Share

That's what it's come to huh - now even Javascript Break isn't considering it's parents. What is the world co$$anonymous$$g to ;)

avatar image Fattie · Oct 17, 2012 at 01:49 PM 0
Share

BTW it's a disturbing point that I actually DID NOT $$anonymous$$NOW the answer to this in the U/S/U3D milieu.

Is it in fact true wot $$anonymous$$e said?

(this is exactly the sort of reason one should never use control structures like this :O for me it all went wrong when we left the oceans and "if" with "go to" :O )

avatar image Demigiant · Oct 17, 2012 at 04:08 PM 0
Share

@Fattie I use some nested loops in the tween engine I made for Unity (HOTween), and I can confirm that break behaves as usual ;) (and I also have to admit I once used a goto, to fully break out of a nested loop - shame on me! :D) (P.S. I have no idea why my answers are nicknamed "$$anonymous$$e" and my comments "Izitmee" :P)

Show more comments
avatar image
0

Answer by echofiend · Oct 17, 2012 at 06:59 AM

As Mike states, the code is hard to read in its current formatting and appears to be linked. As a helpful hint to the future, try to keep only one entry and one exit to every loop/method, multiple breaks and continues can render code hard to debug.

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
avatar image
0

Answer by Kryptos · Oct 17, 2012 at 07:45 AM

To answer your question: No, there is nothing wrong with the break statement.

But your code logic looks a bit weird. Try to make a dedicated method instead of series of if... else. Something like:

 public enum Animal { Crab, Turtle, Jelly }
 
 // ...
 
 void MainMethod(Vector3 playerPosition)
 {
     crabHere = CheckAnimal(Animal.Crab, playerPosition);
     turtleHere = CheckAnimal(Animal.Turtle, playerPosition);
     jellyHere = CheckAnimal(Animal.Jelly, playerPosition);
 }
 
 bool CheckAnimal(Animal animal, Vector3 playerPosition)
 {
     GameObject[] gos = null;
     switch (animal)
     {
     default:
         return false;
 
     case Crab:
         gos = GameObject.FindGameObjectsWithTag("crabtag");
         break;
 
     case Turtle:
         gos = GameObject.FindGameObjectsWithTag("turtletag");
         break;
 
     case Jelly:
         gos = GameObject.FindGameObjectsWithTag("jellytag");
         break;
     }
 
     if (!gos || gos.Length == 0)
     {
         return false;
     }
 
     foreach(GameObject go in gos)
     {
         if (playerPosition.x == go.transform.position.x && playerPosition.y == go.transform.position.y)
         {
             return true;
         }
     }
 
     return false;
 }


The main problems with your code were:

  1. Hard to read.

  2. Hard to debug.

  3. Float comparison as @fafase pointed out. You should consider using Mathf.Approximately or use Vector.sqrMagnitude:

      if (playerPosition - go.transform.position).sqrMagnitude < 1.0f
    
Comment
Add comment · Show 14 · 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 pvzkiller · Oct 17, 2012 at 05:57 PM 0
Share

Thanks to everybody who answered. Sorry for the bad indent, it was looking fine when I previewed my post. The answer to my question was no, it breaks only the loop in where the break is nested. Comparing float values is not a problem for my game development, this is a 2.5D game and it works like a charm comparing them.

One thing though, is there any PERFOR$$anonymous$$ANCE advantage in using Nicolas' way (enumerator) versus $$anonymous$$e?

avatar image Demigiant · Oct 17, 2012 at 06:03 PM 0
Share

I never tested it directly, but actually comparing an int value VS comparing an Enum value should be slightly faster (though way less readable). What he said about float comparisons ins$$anonymous$$d is completely true. When comparing a float, you should always use approximations as he mentioned, otherwise you could have wrong results, sometimes.

avatar image Kryptos · Oct 17, 2012 at 08:43 PM 0
Share

Not at all. Enum/switch are faster because the compiler can optimize the flow control.

avatar image Demigiant · Oct 17, 2012 at 10:16 PM 0
Share

Sorry, I was thinking about the comparison only: a switch that checks an int value (passed directly as a value, meaning "myInt == 1" and not "myInt == anotherInt") VS a switch that checks an enum value should in theory be slightly faster?

avatar image whydoidoit · Oct 17, 2012 at 10:18 PM 0
Share

An enum is stored as an integer in any case. @$$anonymous$$ryptos means that as there are only a limited set of candidate values it is possible for the compiler to predict what values the int can contain, a real int could contain 4bn values, an enum is likely to have a lot fewer values - either that or someone did a lot of typing :)

Show more comments

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

15 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 avatar image avatar image avatar image avatar image avatar image

Related Questions

Instantiate inside foreach loop 1 Answer

How can I make my for loop "reset" if my array contains an value? 5 Answers

Foreach loop wont run completely 3 Answers

Stopping A Loop - Return or Break? 2 Answers

Finding nearest object with a certain tag without for loops. 1 Answer


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