Too subjective and argumentative
Weirdest coroutine crash ever
Hey guys ! really dont want to post here but hey I dont know any further.
Im having this DungeonManager who iterates over all enemies to do thier stuff.
If an enemy can shoot at the player he does so and confirms his action.
If he cant shoot he proceeds to move to a position from where he can shoot at the player.
Both action work perfectly fine as long as there is only one enemy.
If there are two everything still works as long as at least one shoots at the player.
If two enemy want to perform the move action unity crashes and here comes the really weird thing.
The crash then occurs in the following coroutine:
Now the movement is tile based and the "int[] path" parameter contains the tile numbers from start to destination. for each step i get the tiles position, rotate the character, and proceed to move him in a while loop to its destination. after each step I Log it to the console. Now only if both enemies need to move the first enemy crashes in the while loop before reaching the last step in its path. (Eg. the path is 2 tiles, I get the first step logged, the character moves to the last tile and crashes before the last log) That feels like an infinite while loop but
1. its works if the 2nd enemy doesnt needs to move.
2. even if i choose to run the while loop for a set amount of times (like with an int i < X, i++) it still crashes.
Now what is even weirder if the DungeonManagers ConfirmActionFinished method (gets called when an enemy finished his action) calls his own action (index) over and over again, No crash occurs even if the secound enemy needs to move aswell. Its like if the next action should be called the loop crashes and doesnt even reaches the point of calling another action, but if its own action will be called the loop doesnt crashes, terminates fine and moves on.
Dunno how to explain this, its just really weird, the coroutine crashes if after the coroutine another enemy would move and it doesnt crashes if not. as if the coroutine would know whats going to happen afterwards. well thanks for everyone reading/helping !
Answer by Bunny83 · Sep 23, 2020 at 09:01 PM
First of all why do you use such dangerous recursive method calls. Not just your IterateDungeonActions which calls itself but also your calling of ConfirmActionFinished from the coroutine which you start from inside IterateDungeonActions. So you have two potential infinite recursions going on. Specifically if the path length is 0 you will directly call MovementFinished from within the StartCoroutine call because you have no yield in between.
Your code is a prime example for spaghetti code, because it's almost impossible to follow the control flow. Your self recursion can directly be replaced by a loop. Loops are way easier to read and to follow as the exit condition is usually defined more clearly. Having systems calling each other all the time is also not a great structure. It's difficult to identiry the actual entry point and where the execution will end (like I said, typical spaghetti). You probably should rethink about your structure.
Infinite recursion is usually not an issue when done inside a coroutine as long as you ALWAYS have a yield instruction that is executed. It will actually break the recursion and essentially unrolls it into an iterative process. Of course this doesn't solve any conceptional logic issues you may have with all your conditions.
First of all thanks for trying to help ! Now IterateDungeonActions was a loop but I changed it up to see if it was the problem. Ive been putting quiet some logs and the crash happens in the while loop in the $$anonymous$$ovement Coroutine... also the recursive call cant be infinite because of the if() condition, each next call is with index+1 so eventually it will break. and even if i recall it without + 1 -> it just makes the same character attack inifinite times without crashing. I want one enemy do its action at a time then notify that hes done so the next one can do his action. I agree that my code isnt that well structured tho.
This is the old IterateDungeonAction:
Here are no recursive calls same result. It is working fine with one enemy or as long only one needs to move. also ive benn throwing some yield return nulls inbetween that every path has a yield instruction, still same issue.
First of all do not post code as images. $$anonymous$$arkdown can highlight code just fine. Just select all your code and press the 101/010 button. The crash can not be in the while loop. What makes you think that? Keep in $$anonymous$$d if you send you main thread into an infinite loop no debug.log statement executed this frame will show up in the console. Those are accumulated and processed at the end of the frame. If you never end your frame you won't see any update of the console.
I would highly recommend to attach the visual studio debugger and place some break points and iterate through your code. You may have trapped your code somewhere else. There's still code that isn't included in your question. Specifically UnblockCurrentTile, GetTileByNumber, $$anonymous$$ovementFinished and SwitchTurns.
Debugging is something you have to learn to do yourself. We simply do not have an overview over you project. We only see what you show us and that's simply not enough to judge or even follow the control flow.
I also assume by "crash" you mean hang and not crash, right?
Ah alright sorry never posted here before. Alright good point, if the Debug Logs are accumulated and processed at the end of the frame, they dont show up. Okay yea then its not the while loop, would have been weird because it is perfectly fine. Thanks for your time ! you are right shareing the hole project would be to much and thats not the right place to do so. I am pretty confident that the other $$anonymous$$ethod calls should be fine so I thought maybe someone knows a quick fix. yea Unity "freezes" or hangs up, not a real crash therefore it probably is an infinite loop of some kind. well thanks again for your time, and lets hope I find the prob with the Debugger :)