Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Issue with for-loop and array

Discussion in 'Scripting' started by DaveB-90, Jun 22, 2018.

  1. DaveB-90

    DaveB-90

    Joined:
    Jul 5, 2017
    Posts:
    13
    Hey guys,

    i want to script an endboss with a phase, in which you have to react to falling gameobjects. For this to happen, i scripted a for-loop, that should randomly choose 4 out of 6 gameobjects to fall. I thought it might be easy, but the script won't work properly. The "i--" should keep the for-loop from taking random-numbers twice.

    Code (CSharp):
    1. for (int i = 0; i < 4; i++)
    2.         {
    3.             int random = Random.Range(0, 5);
    4.             if (FettSpawner_rechts[random].activeSelf == false)
    5.             {
    6.                 FettSpawner_rechts[random].SetActive(true);
    7.             }
    8.             if (FettSpawner_rechts[random].activeSelf == true)
    9.             {
    10.                 i--;
    11.             }
    12.         }
    Is there anyone who is a pro with for-loops and arrays? :)
    thx for your help,
    Dave
     
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,140
    So, the issue you are most likely running into is your are entering your loop, trying to activate stuff, but trying to check if it's active to take a step back. Since you didn't mention what was going wrong, my guess is the stuff doesn't get activated while you're in your loop in time for it to avoid picking the same object.

    So either you need a coroutine where you can yield null after each activate, or you need to add the gameobjects to a second list and once you get 4 unique items in that list (check it before adding) then loop through and activate stuff in the second list.
     
  3. DaveB-90

    DaveB-90

    Joined:
    Jul 5, 2017
    Posts:
    13
    So the yield null shuts down the for-loop immediately to start it again? What do you say about the i--? Is that a proper way to get the foor-loop going until there are 4 different objects activated? I also thought about another variable instead of the number 4, that will be increased instead of the "i--".
     
  4. WheresMommy

    WheresMommy

    Joined:
    Oct 4, 2012
    Posts:
    890
    You can also use a ienumerator and a while() loop. So as long something is lower then your max count, the code gets executed
     
  5. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    Not as the code is posted. The "i" is the loop counter. The random number is called "random" (line 3). They are completely independent. :)

    The problem is that Line 6 guarantees the object is active. Line 10 will then always be called and decrement the loop counter. Thus it is an infinite loop.

    If you want to choose an index from 7, you would use Random.Range(0, 7). This will return an index of 0 through to 6 (inclusive).

    If you want to prevent duplicate selection during the for-loop, you would have to remove the chosen index from the possible selection. There are a number of ways you could do this. If you are happy to use LINQ, you could try something like this :
    1. At the start of the method, create the set of possible values with
      var numberList = Enumerable.Range(0, 7).ToList();
    2. Start the for-loop.
    3. Set
      random
      to a value from this list. You now have a random number in the range 0->6 that has not been used before.
    4. Remove
      random
      from
      numberList
      .
    5. Use
      random
      as necessary.
    6. Loop will now either end or return back to point 3 (do not explicitly change the value of
      i
      here).
     
  6. DaveB-90

    DaveB-90

    Joined:
    Jul 5, 2017
    Posts:
    13
    Ah thanks. Now I see. So it goes through both ifs and random isnt changed or set new.
     
  7. DaveB-90

    DaveB-90

    Joined:
    Jul 5, 2017
    Posts:
    13
    Code (CSharp):
    1. for (int i = 0; i < 4; i++)
    2.         {
    3.             int random = Random.Range(0, 6);
    4.             if (FettSpawner_rechts[random].activeSelf == false)
    5.             {
    6.                 FettSpawner_rechts[random].SetActive(true);
    7.                 i++;
    8.             }
    9.             if (FettSpawner_rechts[random].activeSelf == true)
    10.             {
    11.                 i--;
    12.             }
    13.         }
    I tested it a few times with the additional "i++" in line 7 and I think it now works the way I want to. Thanks to all :)
     
  8. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    Personally, I would recommend considering the debugger. It makes it very easy to follow the path taken through your code and is a very useful tool to become comfortable with.

    As a general rule, it is worth avoiding this sort of use of a for-loop. Remember that the purpose of a for-loop is to step incrementally through a sequence. There is also the continue and break statements available for an orderly way of controlling the sequence flow.

    If the sequence counter has to be constantly adjusted in some arbitrary way, it may be worth asking whether the for-loop is the right construct for the job at hand (I think this is the point alluded to by asd234w4r5 above).