Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Saving scene in Play Mode but only during the instance the game is running?

Discussion in 'Scripting' started by Dale-Nation, Jan 8, 2015.

  1. Dale-Nation

    Dale-Nation

    Joined:
    Dec 22, 2014
    Posts:
    13
    Hello,

    In my game, my player is going to have to transfer between the same scenes quite frequently. However, there are buttons he presses that causes things to open. For example, let's say I have two scenes. The player starts in scene one. There is a button and a locked door. He presses the button and it unlocks the door. He goes through the door to the second scene. But he decides he wants to go back to the first scene. He does, but the door is closed again, because the game instance did not save that the door's "Allow Player To Click" component was enabled! How can I do this without using PlayerPrefs or variables stored on a GameObject that I don't destroy? How can I just have the scene "remain as it is" when I leave it and when I return to it?
     
  2. TheSniperFan

    TheSniperFan

    Joined:
    Jul 18, 2013
    Posts:
    712
    Option 1 aka "The dirty hack"
    You create one scene that contains nothing but the items you want to preserve. All of them must be marked using DontDestroyOnLoad. Then you load the first level. The 'item-scene' must not contain anything else and the levels must not contain any items. From here on, their state is permanent.
    While it should work, it's a fairly dirty hack that causes other pains. Firstly, working with the items will become uncomfortable, because their world space coordinates in the item-scene must be equal to where they should be in the actual scene. Secondly you'll always have all items loaded, even those from other scenes. This could cause a variety of problems.

    Option 2 aka "An actually good solution"
    Just save the item-data in PlayerPrefs and clear the save data on every launch. For Unity 4 I can recommend the Unity Serializer to you. For Unity 5 you can use my fork, unityserializer-ng. They're complete solutions for saving and loading your games.
    Since I assume that you're using Unity 4, I'll point you towards this feature: Room Management.

    Sounds just about right, doesn't it? ;)
     
    cl9-2 likes this.
  3. Dale-Nation

    Dale-Nation

    Joined:
    Dec 22, 2014
    Posts:
    13

    Seems good, but I'm not really understanding the instructions. I installed the package and I've created a "Save Game Manager" object in my first scene by using the wizard. Now I'm rather unsure of what to do.
     
  4. TheSniperFan

    TheSniperFan

    Joined:
    Jul 18, 2013
    Posts:
    712
    First checkout the first part of the tutorial video. It's about saving Angry Birds in less than 2 minutes.
    For your game, you want to use the "Room Manager". The instructions are here.

    For a simple test setup, follow these instructions:

    1. Create two scenes ("Scene 1" and "Scene 2") and do the following in scene 1
    2. Create an empty GameObject called "Room Manager"
    3. Attach a "Store Information" script to it
    4. Attach the scripts "Room" and "RoomDataSaveGameStorage" to it
    5. Create a plane and a cube
    6. Make sure the plane is underneath the cube
    7. Add a rigidbody to the cube
    If you click play, the cube should fall down, onto the plane.

    Storing objects:
    1. Open the Wizard (Window/Unity Serializer/Wizard)
    2. Select an object you want to store and click "Store information"
    3. Do this for all objects (in this case: the cube)
    Loading:
    Use RoomManager.LoadRoom() instead of using Application.LoadLevel(). Everything else should work by itself.

    Let's say you have two scenes. Here is a script to test it. (Make sure the scenes are added to your build settings)

    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class SwitchLevelTest : MonoBehaviour {
    4.     private static SwitchLevelTest instance;
    5.  
    6.     void Awake() {
    7.         if (instance)
    8.             Destroy(gameObject);
    9.         else {
    10.             instance = this;
    11.             DontDestroyOnLoad(gameObject);
    12.         }
    13.     }
    14.  
    15.     void Update() {
    16.         if (Input.GetKeyDown(KeyCode.Alpha1))
    17.             RoomManager.LoadRoom("Scene 1");
    18.         if (Input.GetKeyDown(KeyCode.Alpha2))
    19.             RoomManager.LoadRoom("Scene 2");
    20.     }
    21. }
    Just attach this code to an empty object in the scene (and don't save it).
     
  5. Dale-Nation

    Dale-Nation

    Joined:
    Dec 22, 2014
    Posts:
    13
    Hey, it worked!

    Thanks!