0
\$\begingroup\$

In the usual Update() of a state (let's call it Attack for simplicity) of an object state manager unit called there's a conditional statement:

if (Condition a)
{
//do something
SwitchState(unit.anotherState)
//then do something else
}

What I don't understand is why, after switching states, then do something else continues execution? Clearly it should terminate execution of Attack and switch to anotherState. So why doesn't it happen?

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Because line of code are executed in order. Nothing is checking your Condition a before the next cycle of Update. Once SwitchState() is called, it will continue with whatever code you have below it. \$\endgroup\$
    – Zibelas
    Jun 22, 2023 at 10:54
  • \$\begingroup\$ This does not look like a question about how to develop a game, but a general programming question about the semantics of C# code. This type of question typically belongs on StackOverflow. \$\endgroup\$
    – DMGregory
    Jun 22, 2023 at 11:21
  • \$\begingroup\$ @DMGregory, could you elaborate on that please, as coding is a substantial part of creating a game. For me, and probably because I am pretty new on SE, this question would fail big time on StackOverflow where I find it more (or less) appropriate here as most here are exploring coding in general. Just learning gamedev and stackoverlow myself. \$\endgroup\$
    – Willem
    Jun 22, 2023 at 22:46
  • \$\begingroup\$ We generally expect questions here to be about topics that not just any programmer could answer, but rather that rely on some game-specific expertise. Understanding how control flow operates around if statements and method calls is soundly in the former group: any programmer using an imperative language could explain this, and no game-specific expertise is needed. \$\endgroup\$
    – DMGregory
    Jun 22, 2023 at 23:03
  • \$\begingroup\$ Your assumption is wrong. The simplest way to think about it is that SwitchState(state) just tells "when doing the next Update() use different state". \$\endgroup\$
    – Nikaas
    Jun 23, 2023 at 5:28

3 Answers 3

1
\$\begingroup\$

Using your example but filling in what is happening

public class Class : Monobehaviour
{

    private int state = 0;

    private void Update()
    {

        if (Condition a)
        {
            //do something
            SwitchState(unit.anotherState)
            //then do something else
        }

    }

    private void SwitchState(int new_state)
    {
    
        state = new_state;
    
    }
}

The execution order is:

1. Update()
2. ->  if (Condition a)
3.     ->  //do something; state = 0;
4.         SwitchState(unit.anotherState)
5.         ->  state = new_state;
           <-
6.         //then do something else; state = unit.anotherState
       <-
   <-

Then on re-entering this Update() again, Condition a is most likely still the same but state != 0. This is an assumption and in coding -> never assume anything.


Besides, this is a class not a state. Also this does make me think you ought to use switches rather then if-statements. No answer/comment here will change though. Reconsideration of your example will have a learning function as you call unit a statemachine, I tend to think SwitchState belongs in unit. As the statemachine is responsible for state-handling. Narrow all your code to the responsible class, it will help you not to repeat your code too.


When SwitchState(...) can fail to change the state, consideration of returning true on success of false on fail would create the ability to put the call into an if-statement to execute it's scope or not. Like:

if(!SwitchState(unit.anotherState)
{
    ...
}

If it will always change the state, code afterwards shouldn't be added when it doesn't suppose to be executed. In case of code after the if-statement should be executed, adding a return in the scope of the if-statement or an else will be your friends, so when the Condition a is not met, that scope is skipped and the code after it will be executed.

private void Update()
{

    if (Condition a)
    {

        //do something
        SwitchState(unit.anotherState);
        return;

    } // else

    if (Condition b)
    {
        //do something
    }

}
\$\endgroup\$
0
\$\begingroup\$

Because SwitchState(unit.anotherState) is a method. And when the method has finished, the program execution continues after the method-call.

If you don't want that, add a return; statement after the method call. This will finish the current method and return execution to the scope it was called from.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ It sounds like this user might benefit from some clarification that the conditions in if statements are not checked continuously throughout a branch's execution. They're an instantaneous junction in the track, and once you pass the junction point, you stay on the rail you chose to wherever it takes you. They're imperative "check this condition and choose a track now", not declarative "execute this code as long as this condition holds". \$\endgroup\$
    – DMGregory
    Jun 22, 2023 at 11:30
0
\$\begingroup\$

I’m going to rewrite your code using different names. And highlight why you would WANT this to work the way it does

if (Condition a)
{
    //do something
    SwitchState(unit.anotherState)
    //then do something else
}


if (Condition applesOnSale)
{

    OpenBasket();
    
    SwitchPeaches(to.Apples);

    RecaclulateTotalPrice();
}

If we want to recalculate our price after we’ve made a switch, we want to make sure that our code completes with all lines running. It wouldn’t make sense to skip that line, since we haven’t reached the closing } yet. Nothing from this code suggests that that line should be skipped.

I think what might be confusing you is that your switch method “shifts control” to the other class. But once that happens and completes it comes back and finishes this function.

We would never want the price recalculation to be skipped after we switch to apples. It’s just another step that occurs after the switch is complete!

\$\endgroup\$
1
  • \$\begingroup\$ That's how I implemented it in the end. I made my life harder by adding various IEnumerators without a thorough understanding of the methodology. \$\endgroup\$
    – Alex
    Jun 28, 2023 at 10:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .