Search Unity

I have a question!

Discussion in 'Scripting' started by Stophy22, Jan 14, 2022.

  1. Stophy22

    Stophy22

    Joined:
    Mar 17, 2019
    Posts:
    5
    Hi I've recently started creating a game with a close friend of mine and I've run into a little problem. I'm not really looking for a solution to the problem, unless its something very simple. Coding is very difficult to understand (for me) more-so of what I am asking for is a "where to look" kind of thing.

    What I am trying to do is the following:

    In my game there are 3 scenes. Title. Loading. and Game.

    In Title you have 2 menus, both with buttons. One menu is MainMenu and the other menu is OptionsMenu. In MainMenu you can Start Game, Load Game, Reset Game, Options, and Quit. Options opens up the OptionsMenu that has 3 sliders (Master Volume, Sounds, Music), 2 toggles (fullscreen and Vsync), 2 buttons to cycle through resolutions, an apply button, and a return button.

    The main issue I am having is when you are in the Title Scene everything works except Load Game. I think this is because it's trying to do something to another scene that isn't loaded, like set the characters position and such.

    With the way the game works the Start Game button loads the next scene (loading) which then loads the next scene (game). In the game scene you can save by interacting with an object I have placed in this scene. This is how I want the saving to work and how I've seen it work in games I've appreciated. In Hollow Knight you interact with benches. In Dark Souls its bonfires. Etc.

    This save physically stores data then encrypts it; a few bools and his position. When go to main menu to load the game with Load Game I think it tries to load the game but since its in a different scene it just doesn't work.

    The main question(s) I am asking I guess is

    1. Is there a way to load data after you have loaded a scene via a button from a different scene.

    2. With everything I described above would you have any suggestions as to go about a fix that would solve the issue.


    One thing I've thought of is having my title menu and stuff in the game scene, but I feel like I shouldn't do this. Essentially the Save/Load/Quit/Delete system I am looking to create is one samiliar to how Hollow Knight, Zelda, Dark Souls, etc. do their save and loading.

    TitleScreen->(has buttons)->StartGame->(this creates a profile)->Enter the game->(you can play on that profile)->Quit the game->(you can now be on the title screen)->LoadGame->(select the profile and play from where you left off).

    I know my code is working mainly because if I add the load button to the Game scene then it does exactly that. Loads players position and state. I guess it goes back to the first question, how do I load data from a scene that doesn't know what that data is?

    The one suspicion I have is creating a function that recognizes if the Game scene was started with StartGame or LoadGame and telling the Game scene to call on the data if it was with LoadGame and to call on no data if it was StartGame. The problem with this is I don't really have a scene creation scrypt... and with the amount of work I've done it would be hard to figure out how to even create that?

    If all of this is gibberish and I'm going about this in the complete wrong way I am sorry, I am trying to ask for help rather than go searching for things I don't know what I should be searching for.
     
  2. Stophy22

    Stophy22

    Joined:
    Mar 17, 2019
    Posts:
    5
    I should also mention that I made the reset button in the Game scene preforms the LoadGame() function and his position resets to the only save point I have, and it does in fact load his data.

    So I guess the initial problem of how do I load that data from the title scene is the greatest issue I am having.
     
  3. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    I honestly dont even know what you mean by loading something that is in a different scene. Unless that scene too is loaded, you dont have access to its objects. So even if you loaded the player position, for example, you wouldnt be able to set it. So your setup confuses me a bit.

    Generally how i would set this up:
    • Start Game would be a "New Game" option. If you have different save slots, decide which one to use and then load the game scene. Otherwise (only one savegame possible) delete all saved data and load the game scene.
    • Load Game would be the "Continue" option. If you have different save slots, decide which one to use and load the game scene. Otherwise just load the game scene.
    • Reset Game would be internal functionality for deleting the save game. Would be the same as New Game, or deleting each save slot in case there is more than one. Not sure what this does otherwise.
    If you need to pass information between the menu scene and the game scene, there is a few different options for doing so. We are only talking about small pieces of data tho. For example an integer idenfitying the save slot to load. You could assign this value to a static variable, or save it to PlayerPrefs to name two examples.

    When you load your game scene, the scene itself is responsible for everything supposed to happen now. So you would for example have some SetupManager which, in Awake(), first checks the necessary data decided upon in the menu scene. So it would, for example, check which load slot was selected, or if only one exists, whether the player wants to load or start new. This is just one number, or a bool.
    Based on this the scene then loads the appropriate data and sets itself up properly, for example by using the loaded character position and teleporting the character there.

    The above is just a rough outline and i am actually not very experienced with using different scenes (or even loading a lot of things) since i mostly dabble in procedural generation. There is however hundreds of video tutorials or guides out there on how to setup different scenes, menus, loading, and so on. I would highly recommend checking out what others did and then deciding on which parts you can keep for your game, and which you need to adjut or do differently.
    The wheel has already been invented after all. You usually just need to do minor adjustments ;)

    Edit: Also you wrote you encrypt the data you save. This is usually not necessary. Unless you store your save games on a server, people will alter it if they so desire.
     
  4. Stophy22

    Stophy22

    Joined:
    Mar 17, 2019
    Posts:
    5

    Thanks for the response, I think what you described with start game, load game, and reset game is exactly what I am looking for. I'll look at that SetupManager you talked about because I think that is what I need. I want to add profile slots and what not I just haven't set it up. The issue I think I am having is the Load button is on the Title scene so by having it on the title scene it can't do LoadPlayer() correctly, because its not in the same scene. When I use Loadplayer() from the Game scene it works correctly and I guess that's why I am asking how you access data from different scenes. If the code for loadplayer() is essentially the same for startgame() which is just switching the scene, what tells the scene to load a save rather than starting up as it normally does, I guess is the issue.

    But you might have answered my question by mentioning the SetupManager.

    I know the wheel has been invented already as I think I look at about "50" different wheels a day while working on this and I try to decide which one is the best hehe, looking things up is invaluable as a resource, I guess I've just hit a bit of a wall with this idea and how my mind works. Regardless your words and thoughts have been very helpful.

    I encrypted the data because when I looked up, "how to create a save and load system in unity" a lot of people suggested encrypting the data. I didn't really understand the point but its nice to get some more insight on it, thank you.

    The underlying issue is just my low knowledge point for coding and making things work. But I appreciate your response and feedback!
     
  5. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    Just to clarify: the SetupManager, LoadManager or however you might call it, was something i made up for the explanation. There is no such Unity object. You need to implement it. It was intended to describe a scene-specific centralized loading sheme, which looks up a tiny amount of information (like the save slot) provided by the menu scene and handles the initialization for the game scene afterwards.
    You could also do the same in a more decentralized way, where each object would load its own data using the same approach. Meaning the player itself would check which savegame was selected, and then load the corresponding position for its own initialization itself. Any other object would do the same.

    There is also completely different approaches. You could, for example, also do the actual loading in the menu scene. You would then, however, need an object to store this information in. "Loading" would thus mean to simply put all the data from a file into some Unity object with the same attributes (playerPosition, playerLevel, dayTime, ..). This object would be marked as DontDestroyOnLoad, making it persist when you switch scenes. Objects would then access this object in some way to gather their own state.
    I'm personally not a big fan of the DontDestroyOnLoad approach tho, since you now need to handle and pay attention to this object. It simply feels less robust and more of a hassle in my mind, but maybe that's just me.

    Anyways, the point is there is tons of different ways to approach this. Which is why i was suggesting to look at what others did, and then choose which seems to fit your game design the best :)
     
  6. Stophy22

    Stophy22

    Joined:
    Mar 17, 2019
    Posts:
    5

    Thanks I kinda understood that it didn't exist and that it probably had to be a script I would attach to an empty game object, but the idea itself is a nice thought because it is one I did not have myself.

    I guess the greatest challenge I will have would be trying to understand how to read the file and load it. I understand how to save something now, relatively. But when I started out saving was a mess, in my mind. I thought saving just worked by snapshotting the game in its state and then whatever but actually storing values and stuff was kinda nuts to realize.

    I had to figure out all the things that would need to be saved like playerPosition, Money, Exp, IF he has the ability to double jump or whatever other movement altering effects someone would have.

    Thankfully saving does make sense now to me on a material level. Loading doesn't however...

    My load and save things seem to do identical things at least in code, one writes data and the other calls that data into existence from a place. But as to where that place is or how to assign that place a value so its loaded and to store different values is a little beyond me. I know where the data is loaded, just on the Application.persistentDataPath + "/name of file".

    I shall watch more videos and develope a greater understanding though because my knowledge seems to be the issue here not what I am trying to do. Thank you for the time you've been immensely helpful. If you're curious about the code it's almost identical to the code used in this video
    I guess the problem I ran into is he never tries to load his code from another scene, its always from the same scene and mine does fine on the same scene but getting it to work from a different scene was the issue I ran into following that.
     
  7. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,605
    If loading from another scene is all you struggle with, then dont do that. Let's instead build on what you can do. This goes in the direction of what i first suggested, but i hope it's a bit easier to understand.
    Remember, in programming one important concept is called "divide and conquer". If there is a complex problem you cannot solve, split it into smaller problems. Repeat this process until you arrive at problems small enough to solve (or easily google). Solving all the small problems, solves the big problem.

    With that in mind, let's rethink your saving and loading problem, while building on what you feel comfortable with.
    Make it so that the game scene is responsible for loading its own data. You said you feel comfortable with saving. Loading is basically the same thing in reverse, and should happen right at the beginning of the scene. So for example, in the Awake() of each script that needs to load data (like the Player).

    Let's assume you only have one savegame. So the game scene would automatically always just load this savegame. Would you have problems implementing the above, if the scene is responsible for its own loading? From what you wrote, it seems that should be within your abilities. And for what you want, that's 90% of the way there.
    So right now, whatever you do, the savegame will be loaded.

    What you want now is a way to alter this behavior just a tiny bit to allow for starting a new game instead. For that we need one single piece of information from the main menu, that is whether the user pressed "New Game" or "LoadGame". Since this is a binary choice, we can simply store a bool value. Since we are talking about very little information, you might as well store it to PlayerPrefs or simply set a public static variable to the desired value.
    Let's call this value loadGame, and the main menu would set it properly depending on which option was chosen.

    The game scene loading mechanism(s) would now simply need to read this value before doing anything. If it's true, it loads like before. If it's false we instead want to start a new game and do what's necessary for that. What this means can differ from game to game. Some games might be fine with just "doing nothing", since that would mean not loading data, thus initializing the objects with default values, ie starting a new game. For other games it might be necessary to delete the previous save data.
    Overall i'd say deleting the old data is never a bad thing when starting a new game. This can, and probably should, even be done from the main menu when "New Game" is selected. Just make sure that the loading part in the game scene also works when no savegame was found, and that the default values loaded instead result in a new game. Since you need to start somehow and dont have a savegame when you first launch the game, this is usually the default behavior.

    And that's basically all you need, right?
    If you need multiple savegames, we are one other variable away from that goal. Simply add an integer indicating which save slot was chosen. Your scene will then load the data from that slot, or start a new game if none is available.

    I hope this makes the topic less daunting by only adding one new problem at a time and keeping it simple.
    Hope it helps :)
     
    Stophy22 likes this.
  8. Stophy22

    Stophy22

    Joined:
    Mar 17, 2019
    Posts:
    5
    Explaining it like that definitely helps. I think I will try to do exactly as you said. Once I have it working I think I will then try to implement the profiles I want. Thanks for the help I appreciate it.

    I'll keep this in mind when I encounter other problems of this nature and try to split them into smaller problems to try and solve. I guess the first small problem I have is how to store the profile as a variable upon button click. Then I'll need to figure out how to call upon variable.

    Thank you once again, I'll do my best.
     
    Yoreki likes this.