2
\$\begingroup\$

First of all I know about coroutines and how to use them (they're awesome).

A friend of mine was telling me about the way the he implemented his saving system in a game he was working on, after asking him what he was using I found out that he is using system.threading and not coroutines to save data.

I know that Unity isn't thread safe but apparently he has had no issues with saving which leads me to wonder if it is ok to use normal threads as long as you're only reading data and no pre-existing data is modified in the gameworld? would this affect the game at all (other than some moving objects being slightly ahead of where they should be because of the time it took to get to that object and save it)?

\$\endgroup\$
  • \$\begingroup\$ Look at this answers.unity3d.com/questions/908054/… \$\endgroup\$ – Savlon Jan 19 '16 at 12:14
  • \$\begingroup\$ I read that before asking this question and it only really talks about generating new terrain (manipulating data) what i want to know is if i can get away with just reading unity objects as long as i don't change any values from the other thread... \$\endgroup\$ – user3797758 Jan 19 '16 at 12:21
  • \$\begingroup\$ What data types are you intending on using in these other threads? \$\endgroup\$ – Savlon Jan 19 '16 at 12:26
  • 3
    \$\begingroup\$ Possible duplicate of How to not freeze the main thread on unity? \$\endgroup\$ – DMGregory Jan 19 '16 at 18:07
1
\$\begingroup\$

Saving in another thread while the game keeps running is dangerous. When the gamestate changes while the savegame file gets written, you will write a mixed gamestate consisting partly of the old state and partly of the new state. This can cause all kinds of weird and impossible to reproduce bugs when that savegame is loaded.

For example, consider you have a script which destroys one game-object and instantiates another in its place. Now consider what happens if the saving takes place exactly between these two operations. There are two possible outcomes: Either both will exist when the savegame is loaded or neither will. Either case might break the game in a way that the player can not continue. You have created the worst nightmare of every gamer: a broken savegame.

The deviousness of such problems is that they will appear completely random. Your friend's savegame system might work perfectly fine in 1000 tests, but at the 1001st time it might run into such a race-condition and screw up. And then never again until after release when the user-reviews of your game are suddenly full of people whining about their corrupted savegames and your testers fall into despair trying to reproduce the problem.

If you want to save in a separate thread, you need to write the complete gamestate to an in-memory data structure first and then start the thread to save that structure while your game keeps running with the original gamestate.

\$\endgroup\$
  • \$\begingroup\$ I understand that this would happen (In my friends case the new thread is created when the game is basically idle) but what i want to know is what would the game itself crash as a result of running a read only threaded operation (such as saving), would it crash if the game is changing a variable and the other thread wants to read that variable at the same time? \$\endgroup\$ – user3797758 Jan 19 '16 at 15:51
  • \$\begingroup\$ @user3797758 A crash of the main thread is unlikely, but the saving thread could crash under some conditions. Still, it's a very bad idea to have the saving-thread access the actively changed data, as I already explained. \$\endgroup\$ – Philipp Jan 19 '16 at 17:21
  • \$\begingroup\$ @Phillipp Under what conditions? \$\endgroup\$ – user3797758 Jan 19 '16 at 18:01
  • \$\begingroup\$ @user3797758 For example, when a complex data-structure is changed while the thread is reading it, it might get a null reference where there used to be a proper reference before leading to a null reference exception. For example: if (foo.ref != null) { foo.ref.getBar() }. foo.ref might have a value during the check but then gets set to null by the main thread before foo.ref.getBar() gets called. \$\endgroup\$ – Philipp Jan 19 '16 at 18:04
  • \$\begingroup\$ @user3797758 And before you ask: yes, there are solutions for this, but they are easy to forget and also come with their own set of problems (like deadlocks). \$\endgroup\$ – Philipp Jan 19 '16 at 18:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.