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 gdubrocks · May 11, 2014 at 05:19 AM · c#turn-basedwhileswitching

How to stop infinite loops in turn based game.

Unity freezes (presumably because there is an infinite loop) when I run this code.

My logic is: I call updateTurn, which organizes the players by speed and calls actionPhase on the next fastest unit. actionPhase sets the turnState to 1, which turns on the actionPhase GUI. At this point the player clicks the move button, which sets the turnState to 2. While turnState is 2, update polls the users mouseclicks until a valid move is made, at which point turnState is updated to 9, ending the turn.

All methods work properly on their own EXCEPT actionPhase, which always freezes the game. How can I stop the infinite loop from happening?

Sorry about the formatting. I swear it's impossible to copy/paste code :(

     //Update turn orders players by speed and then calls action phase on them
     void updateTurn()
     {
         int playerSize = players.Count;
         int index = 0;
         PlayerStats ps;
         //turnState = 0;
                 
         print("Turn Started");
                 
         //calculate fastest player
         sortPlayersBySpeed();
         index = 0;
         
         //ps = players[index].GetComponent<PlayerStats>();
         
         index = 0;                
         while(index < playerSize)
         {
             print("entering loop");
             ps = players[index].GetComponent<PlayerStats>();
             if(ps.dead == false)
             {
                 print("Starting Action Phase " + index);
                 actionPhase(players[index]);
                 print("Ended Action Phase" + index);
             }            
                 index++;
                 }
     }
 
 
 void actionPhase(GameObject player){
         turnState = 1;
         
         while(turnState != 9)
         {
             switch(turnState)
             {
             case 0:
                 //No player selected
                 break;
             case 1:
                 //player selected, actionphase begun, wait for GUI
                 break;
             case 2:
                 //move selected, update is getting new click positions
                 print("move selected");
                 if(moveValid(player, clickPosition) == true)
                 {
                     StartCoroutine(moveObject(player, clickPosition));
                     turnState = 9;
                 }
                 break;
             case 9:
                 print("turns over");
                 return;
 
             }
         }
     }
 
 void OnGUI () {
         if(turnState == 1 || turnState == 2 || turnState == 8)
         {
             if (GUI.Button (new Rect (10,10, 100, 50), moveButton)) 
             {
                 print ("you clicked move");
                 if(turnState == 1)
                 {
                     turnState = 2;
                 }
             }
         }
     }
 
     // Update is called once per frame
     void Update () {
         if(turnState == 2 || turnState == 8)
         {
             clickPosition = getTaggedClickPos("Ground");
             print(clickPosition);
         }
       }
Comment
Add comment · Show 1
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 Benproductions1 · May 11, 2014 at 09:37 AM 0
Share

You should properly indent your code and you won't have as much confusion with the brackets as you have in the code above.

3 Replies

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

Answer by Owen-Reynolds · May 11, 2014 at 04:28 PM

After reading Benprod's reply, it seems like the whole turn sequencing is borked, and needs an overhaul.

So, there's an "action queue" like finalFantasy Tactics, of who goes when. The loop at the bottom of updateTurn goes through the whole list, giving each player a turn using actionPhase. actionPhase completely runs a player's turn, returning when the player has finished.

BUT this should all happen over many frames!! So actionPhase and updateTurn should be coroutines -- yield return null; in actionPhase, and yield startCoroutine(actionPhase..) in updateTurn.

But otherwise the style of programming doesn't feel like a coroutine. As normal code, get rid of all the loops. ActionPhase would just check what you did this frame, and if it was the "confirm action" button, say that player is done. UpdateTurn just runs actionPhase for the current player. If they were done, resort the list (and check the new 1st player next frame.)

Comment
Add comment · Show 3 · 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 gdubrocks · May 11, 2014 at 06:44 PM 0
Share

I think you have the right solution (using coroutines), but I don't fully understand why this is needed.

It should happen over many frames, which is why actionPhase (or updateTurn) is not called within update. Ins$$anonymous$$d the parts of these methods that need to be checked are contained within GUI and Update.

The reason I am looping through actionPhase is because I need to check for the clicks of the users, which may or may not happen in the exact frame that method is called. I need that loop to run because the location will be decided AFTER that method is called.

How would using actionPhase and updateTurn as co-routines solve my problem?

avatar image Owen-Reynolds · May 11, 2014 at 10:19 PM 0
Share

This might help: Users enter input during frames, and code runs between frames. If you check input more than once during a frame, you're just rereading last frame's input, over and over.

avatar image gdubrocks · May 12, 2014 at 01:00 AM 0
Share

That does help, it explains what's happening pretty well. Now to just figure out how to fix it....

avatar image
1

Answer by Benproductions1 · May 11, 2014 at 09:44 AM

Just desk-checking your code in actionPhase (should actually be ActionPhase. We capitalize functions in C#) simply and plainly reveals your infinite loop:

  1. set turnState to 1

  2. Begin a while loop, while turnState is not equal to 9

  3. turnState is equal to 1, so go to case 1 and... break.

  4. Now, we are still in the while loop, so continue from 2. (`turnState` is still 1)

Always remember, break is one level only. In a switch, break will break out of the switch. Nothing more, nothing less.

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 gdubrocks · May 11, 2014 at 06:37 PM 0
Share

turnState is updated in the other methods. As soon as a player clicks on the GUI move button it changes the turnState to 2. This however is never allows to happen as Unity refuses to run.

I can see where the infinite loop is, I explained that. I don't understand WHY it is an infinite loop, as it is being edited within onGUI, which calls every frame.

avatar image gdubrocks · May 11, 2014 at 06:46 PM 0
Share

I am going to seperate turnState into GUIState and turnState so that the code is easier to understand.

avatar image
0

Answer by sandbaydev · May 11, 2014 at 08:12 PM

You have quite many while loops & thingies there.

Instead of "waiting for state 9...", you could consider something like here. This is partially pseudo code, so plenty of figuring it out here. But hopefully this gives some idea about what you could consider doing: break the code into smaller pieces, treat each turn phase in separate blocks. This isn't the final code, you still need to think how you want to arrange your code.

Currently your breaks in line 45, where it can never leave the "while" loop... here's bit of code to hopefully help you out :)


 void updateTurn() {
    switch currentTurnPhase {
      case "newturn":
         initTurn(); 
         currentPlayer = getNextPlayer(); //this one finds the next alive player on the list
         currentTurnPhase = "playerturn";
         break;

      case "playerturn":
         if (clickedMoveSomewhere) { 
           currentPlayer = getNextPlayer(); //returns null in case this was the last chap
         }
         if (currentPlayer == null) {
            //nobody left, let's end the turn
            currentTurnPhase = "endturn";
         }
         break;

      case "endturn":
            // do something
            ...
            // start a new turn
            currentTurnPhase = "newturn"
            break;
  }
 
 }
Comment
Add comment · Show 1 · 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 gdubrocks · May 12, 2014 at 12:59 AM 0
Share

Thanks. That is actually almost exactly what I currently have, the problem is that each "case" becomes long enough to be their own method, which is why I have separated them. The extra states are required because I am planning on having actions, movement, and attacks all occurring within the turn.

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

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

Related Questions

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

apply something on enum 1 Answer

Illuminating a 3D object's edges OnMouseOver (script in c#)? 1 Answer

How to know when turn is over in turn-based game 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