BerickCook has expressed the idea correctly. Leave the calculations where they are if they work properly now.
If you can do the calculation before and you are sure you will not need them mid-game, then do it before. Else do it after loading.
If the calculation during the game is unnoticeable you could do it there. If at some point the complexity evolves and the calculations become too heavy start optimizing.
But one thing: if your calculations are implemented to run mid game you can always force them to be performed during loading anyway.
There are numerous solutions:
- calculate/load the paths during level creation/loading
- use a second thread to calculate the paths
- optimize your algorithms
- use an interruptible system if you have no access to threading.
I have seen and used the last option in a mass market game. Simply make sure you properly save all the data needed for the calculation to resume, and check regularly for remaining time/operations during the calculation.
Depending on your case, the interruptible system could give preliminary and partial solutions that can be used event before the calculation has ended.
Edit: answering @Keeper
The "interruptible algorithm" was useful only because of the constraints we had. Basically we palliated to the lack of multithreading.
At one point we had a game where the AI had to compute large amounts of moves based on multiple dictionaries. During this calculation all animations would stop because the dictionaries were expanded with more data and the dataset holding the data was changed and less efficient when the game was adapted for multiplayer (where the AI had to interact even for the player's moves). We had only one thread available for the game loop (the imperative being the multi-platform code must run on all supported platforms).
At this point it was decided to break the calculation algorithm so we could interrupt it. Therefore we couldn't just use the recursive system that was in place as variables could not be saved. The functions were replaced with objects which simply held all the necessary variables and pointers to parent and child objects.
I don't remember the full implementation but each object had a way to:
- save the status of its current computations
- interrupt either at the end of a loop or during a loop (when a child object interrupts)
- exit when time's out
- resume where it stopped either restarting a loop at the right index or calling the child object currently being at the top of its children stack.
- clean everything if the computation is interrupted
- give the best partial result.
Only the most expensive operations were broken into separate objects and it took some time to find the right places where we could stop the calculations, but in the end it works very well.
We lost performance, but perceived performance was much better for the user as animations ran smoothly on all platforms, all platforms could then use the larger dictionaries without suffering from choppy animations or freezes. Also this allowed us to run multiple instances in parallel when we needed it later.
Of course now on the iPhone and iPad the game doesn't need this, using a second thread would be ideal. But I suspect the code is still there.