- Home /
"goto" does not work as expected?
Why does Unity keep crashing when using goto like so...
public int i = 0;
private void Update ( ) {
Infinity:
if(i == 0) goto i0; else
if(i == 1) goto i1;
i0:
print("Hello 1");
goto Infinity;
i1:
print("Hello 2");
goto Infinity;
}
It works while doing this in a c# console app but in Unity it just crashes. How does goto work in Unity?
Answer by MacDx · Oct 16, 2017 at 09:39 PM
Because that's an infinite loop, you call it infinite yourself and you know what an infinite loop causes to a program right? (Hint: it crashes the program) Every time you get out of the Infinity block you go straight into it again, basically, your Update function never resumes. Not sure about why it wouldn't crash in your c# console app, maybe it's because there's some code there (that isn't here, or maybe it is the environment where it runs) that makes the application yield, but in this code you are showing there's nothing to stop the loop to give everything else a chance to run.
So yeah. Try something like this instead:
public int i = 0;
private void Update () {
if(i == 0)
print("Hello 1");
else if(i == 1)
print("Hello 2");
}
Also, as a fellow programmer, I strongly advise you to stop using the goto statement. Practically every time it is unnecessary and it can easily lead to spaghetti code.
This is driving me crazy, It works every time in c# (console or forms app). I just tried returning after each goto label so it doesn't enter anything below it, and it works. But using return defeats the whole purpose of goto, because I can only jump down the code and not up and down. Also it is much easier to read spaghetti code, rather then a bunch of if else statements nested inside eachother!
private void Update ( ) { if(i == 0) goto i0; else if(i == 1) goto i1;
i0:
print("Hello 1");
return;
i1:
print("Hello 2");
return;
}
Rather then a bunch of if else statements nested inside eachother!
Yeah but there is no nesting in the code I put, I have the same amount of if statements as you did. Besides I would argue here that if your code needs to have a whole bunch of if/else statements nested then what you really need is polymorphism.
But you lost me at this phrase buddy, I wont argue anything further after this phrase
Also it is much easier to read spaghetti code
Good luck.
Yeah but there is no nesting in the code I put, I have the same amount of if statements as you did.
I guess I should have not assumed that one would think that maybe I wrote the code in the question with 2 statements ins$$anonymous$$d of 100 of them because it would be repetitious.
Using if else makes things difficult to read when they are nested like this * 100, so that is why I want to use goto, but Unity doesn't like them.
if(i == 0){
//Do stuff its its 0
}else{
if(i == 1){
//Do stuff its its 1
}else{
if(i == 2){
//Do stuff its its 2
}else{
if(i == 3){
//Do stuff its its 3
}else{
//Lets say I add about 20 more,
//you see how all these brackets can get confusing and
//long with multiple lines of code in each statement
}//end of 3
}//end of 2
}//end of 1
} //end of 0
Note that an infinite loop does not crash an application but it causes the application to hang / freeze. There's a huge difference. When your application runs into an infinite loop it still works and still runs, but it is stuck inside that loop and it only does execute that loop, nothing else.
Answer by Bunny83 · Oct 16, 2017 at 10:53 PM
The fundamental difference when creating a console application is that you are responsible for:
reading input
updating the output
A Unity application also has such an infinite loop which is generally called the "main loop". However the main loop is part of the engine and works in cooperation with the operating system. It actually communicates with the OS, is reading messages which have been send to your application and also updates the screen.
Your code is called from the middle of the main loop. It allows your code to react to input that has been read by the engine. However if you don't give the control back to the engine you will cause a freeze of your application. Unity can never finish the current frame, can never actually render the scene and can never update the screen. It also can't update the input state as you trapped the thread inside your infinite loop.
It's completely pointless to compare a Unity application to a console application . It's like comparing an industrial robot with a rock. Both can be used as tools. However they work fundamentally different and serve different purposes and have their own limitations. A rock works without electrical power and isn't sensitive to rain, but a rock can't be used to positioning hightech chips in a production line with a few nano meters tolerance.
ps: If you create an infinite loop inside the OnClick callback of a button of a WinForms applicatio, the application will freeze just the same way.
If you want to have sequencial logic spread over multiple frames you may want to look into coroutines. However a bit more general C# programming and OOP training wouldn't hurt.
You may want to have a look at the event execution order documentation page and scroll down to the "Script Lifecycle Flowchart" to get an idea how Unity works.
Answer by gwnguy · Oct 17, 2017 at 07:27 AM
In your example, you don't need the else. There may be examples in real life where you really do need a bit of nested if/then/else but goto is rarely a good option.
if(i == 0){
//Do stuff its its 0
} //end of 0
if(i == 1){
//Do stuff its its 1
} //end of 1
if(i == 2){
//Do stuff its its 2
} //end of 2
if(i == 3){
//Do stuff its its 3
}//end of 3
if(i == 4){
//Do stuff its its 4
}//end of 4
if(i > 4){
//Do stuff if it isnt 0,1,2,3, or 4
}
Also, take a look at Switch and Case
switch (i)
{
case 1:
//Do stuff its its 1
break;
case 2:
//Do stuff its its 2
break;
case 3:
//Do stuff its its 3
break;
case 4:
//Do stuff its its 4
break;
default:
// Do stuff if it isnt 0,1,2,3, or 4
break;
}
Why do you think he doesn't need "else" in this case? Using else after each if statement is a very different code flow as you will not check any if statements further down if one if is true. Your code does always check all ifs in order.
So your if statements are different from your switch case example.
True. I stand corrected.
How about wrapping the if statements in a while loop. Additional overhead: 1 time: bool var and while construct each loop: set bool var and add continue statement Less overhead: else statement
[code]
bool flgNot$$anonymous$$atch = true;
while(flgNot$$anonymous$$atch)
{
if (i == 0)
{
//Do stuff if its 0
flgNot$$anonymous$$atch = false;
continue;
}
if (i == 1)
{
//Do stuff if its 1
flgNot$$anonymous$$atch = false;
continue;
}
if (i == 2)
{
//Do stuff if its 2
flgNot$$anonymous$$atch = false;
continue;
}
if (i == 3)
{
//Do stuff if its 3
flgNot$$anonymous$$atch = false;
continue;
}
// no match. variable i isnt 0,1,2,3
// Do stuff if its none of the above
} // end of while(flgNot$$anonymous$$atch)
[/code]
Ultimately, I would still use case/switch. It has the least execution since only the specific case block is executed. The "if" way of doing things will still execute each if statement until the match is found, after which it will "continue" out or "else" out (if using if/else)
But I think while/continue is a reasonable way to use if statements and not have successive execution after a match.
Answer by zachwuzhere · Oct 16, 2017 at 11:52 PM
Apparently threading works in Unity, But I cant call any mono behaviour stuff from this thread(input, getcomponent, ect.) bacause opf restrictions. I guess this will work for now.
static int i = 3;
static Thread MainThread = new Thread(main);
static bool isRunning = true;
void Start ( ) {
MainThread.IsBackground = true; //closes the thread when unity closes(need to manually
//close it when in the editor)
MainThread.Priority = System.Threading.ThreadPriority.Highest;
MainThread.Start();
print("Thread started");
}
void Update ( ) {
if ( Input.GetKeyDown ("0") ) i=0;
if ( Input.GetKeyDown ("1") ) i=1;
}
static void main ( ) {
Infinity:
if(!isRunning) return;
if(i == 0) goto i0; else
if(i == 1) goto i1; else
goto Infinity;
//Things to jumpto
i0:
print("print 0");
goto Infinity;
i1:
print("print 1");
goto i0; //Just did this to see if it will alow me to jump up the code(it does)
}
void OnApplicationQuit ( ) {
isRunning=false;
MainThread.Abort();
}
But what's the point of that background thread? Don't you have any practical example of what you want to do? Your background thread will eat up 100% of one of your CPU cores.
Why do you use Unity at all if you're not using the engine?
I'm using it to receive data (client side) across the network, because the thread runs faster than the Update method, which would be too slow for hosting many players. The thread doesn't seem to eat up of any of my processor performance either.
Of course it's fine to use a seperate thread of networking. However you should be familiar with multi threading. Still using goto like this is prone to become a mess if the code grows.
Also Unity has built-in networking solutions (high and low level). Of course you can ship your own but you have to deal with all problems that come from this decision.
Your answer
