#Save and Load

1 messages ยท Page 1 of 1 (latest)

warm cobalt
#

this is my current options script

fallen anvil
#

What's the next step you're wanting to do?

warm cobalt
#

this is the class

warm cobalt
#

so maybe you could help me with that

fallen anvil
#

Give me some minutes, I'll create a simple example, just gotta boot my PC first ๐Ÿ™‚

warm cobalt
#

sure

#

i have to store 3 variables:
bool musicIsToggled
bool effectsIsToggled
float masterVolume

#

or at least thats what i imagine it like

fallen anvil
#

sorry, took me a few minutes

#

it's not suited towards your use case, it's just a kinda generic example of how you could approach this.
probably best to import this into a fresh project just to test it out, should be easy to understand

warm cobalt
#

whats the point of OptionsData.cs

#

i think i got it

#

is it for this line?

#

why not just make 1 class

#

just options data

#

wouldnt it work

warm cobalt
#

also whats up with all the underscores

#

and m_

warm cobalt
#

also i have this different script for my slider + another one for fullscreen, i suppose i should put them all into the optionsUI script?

fallen anvil
# warm cobalt why not just make 1 class

OptionsData is the thing that's getting Serialized in Json, it's only responsibility is to hold the actual Values you're using throughout your different options.
It's also a matter of separation/organization, you don't want one big class that holds, modifies and saves data, but instead have a single class with the Data and another one that's working with it

fallen anvil
fallen anvil
warm cobalt
#
using UnityEngine;
using UnityEngine.UI;

public class OptionsUI : MonoBehaviour
{
    [SerializeField] private Slider slider;
    [SerializeField] private Image EffectsButtonImage;
    [SerializeField] private Image MusicButtonImage;


    private void Awake()
    {     
        EffectsButtonImage.color = Color.green;
        MusicButtonImage.color = Color.green;

        
        if (AudioManager.Instance.effectsSource.mute == true)
        {
            EffectsButtonImage.color = Color.red;
        }

        if ( AudioManager.Instance.musicSource.mute == true)
        {
            MusicButtonImage.color = Color.red;
        }
        
    }

    void Start()
    {
        AudioManager.Instance.ChangeMasterVolume(slider.value);
        slider.onValueChanged.AddListener(val => AudioManager.Instance.ChangeMasterVolume(val));
    }


    public void ToggleMusic()
    {
        ChangeColor(MusicButtonImage);

        AudioManager.Instance.ToggleMusic();
    }
    public void ToggleEffects()
    {
        ChangeColor(EffectsButtonImage);

        AudioManager.Instance.ToggleEffects();
    }
    private void ChangeColor(Image buttonImage)
    {
        if (buttonImage.color == Color.green)
        {
            buttonImage.color = Color.red;
        }
        else if (buttonImage.color == Color.red)
        {
            buttonImage.color = Color.green;
        }
    }

    public void SetFullScreen(bool isFullScreen)
    {
        Screen.fullScreen = isFullScreen;
    }
}

#

this is my OptinsUI script now after everything

#

i made these three additional values

#

and these methods

#

also instead of m_optionsData i called my variable just _optionsData

#

what am i supposed to do now

#

ig somehow link the variables from the optionsData class to my optionsUI script?

#

i really dont get all of this

#

perhaps something like this? its in Start, in OptionsUI script

warm cobalt
#

look at this

#

its reffering to this

#

@fallen anvil could you help because i cant build because of this error?

fallen anvil
#

Hey

fallen anvil
warm cobalt
#

yeah i read about replacing Aplication.dataPath with persitentDataPath

fallen anvil
#

The code I've written was an example of how you could approach stuff like saving options.

fallen anvil
#

That was purely so you can visualize your save file existing in the Editor

warm cobalt
fallen anvil
#

AssetDatabase refreshes the actual Contents under your "[Project]/Assets" Folder in the Editor

#

Which is where Application.dataPath stores stuff when using within the Editor

warm cobalt
#

alright

fallen anvil
#

A build doesn't need it, it's part of the UnityEditor namespace and any APIs from that namespace can't be included inside actual builds.

If you're on Windows, when using persistentDataPath, you'll find the Files under AppData/LocalLow/YourCompany/YourProduct

warm cobalt
#

if i were to use this system for saving items in the players inventory for example, could the player go into the game files, edit the file and give himself items?

fallen anvil
#

Encryption sounds harder then it actually is! ๐Ÿ™‚

warm cobalt
#

i hope

fallen anvil
#

It shouldn't be more then 2-4 lines if code I think

#

After you got the jsonString from JsonUtility.ToJson you apply some kind of encoding/encryption to it before writing to file

#

And the other way around, when you get the contents from the file, you revert that encryption before passing the result to JsonUtility.FromJson

#

It could even be enough to just convert it into an array of bytes and back, no need for a real encryption

warm cobalt
#

it doesnt save the data between sessions

warm cobalt
#

so i can send you the scripts

fallen anvil
#

I'm not on my PC right now, inside one of the Context menus at the top of the Editor, you have an "Export" option

fallen anvil
#

Did you check AppData folder for the file?

#

Feel free to send me a Unitypackage, but it'll take some time until I'm back home and can take a look into it

warm cobalt
#

i found the file

fallen anvil
#

But the saving should definitely work

fallen anvil
warm cobalt
#

these arent even the settings set in the editor, idk where its getting it from

fallen anvil
# warm cobalt

Start the Build, change some settings, and check the file again, see if it updates correctly

fallen anvil
#

Ok, I think it's because where the Options.Save is called (I think I put it in OnDestroy?)

warm cobalt
#

yep

fallen anvil
#

In the Options class

warm cobalt
#

in optionsUi

fallen anvil
#

Just add a .Save after the changes

#

Like

SetVolume(...)
{
    // ...
    Save();
}
#

And additionally, you can create a Constructor for the OptionsData to apply sane default values

OptionsData()
{
  Volume = XYZ;
  IsFullScreen = XYZ;
}

etc

warm cobalt
fallen anvil
warm cobalt
#

i made a Save method

#

down below

fallen anvil
#

You save it, but you never change any values of it

#

SetFullscreen should hook into the Options class, which would then change the OptionsData and call Save

#

For example, in your ChangeColor, what do you expect to be saved there?

warm cobalt
#

actually i dont think i need to save anything in change color since i have this in awake

#

i just need to save the state of the effects and music source

fallen anvil
#

Yes, exactly, you don't have anything to save within SaveColors ๐Ÿ˜„

fallen anvil
warm cobalt
fallen anvil
#

That is the code I've written, that will save the OptionsData

warm cobalt
#

obviously no since youre asking

fallen anvil
#

Where is the code you have written to change the OptionsData

warm cobalt
#

its in start tho

#

this sets the values to the value from the previous session i think

fallen anvil
# warm cobalt

That's where you're getting the values, but where are you changing them according to your UI

#

If your slider changes, for example

#

You want to call ```
Options.SetMasterVolume(...);
Options.Save();

#

And do you call Options.Load() before accessing it?

warm cobalt
#

yes

warm cobalt
#

but that doesnt work

fallen anvil
fallen anvil
warm cobalt
fallen anvil
#

You can easily create your own Set methods by following the example

warm cobalt
fallen anvil
#

Aaaaah

#

So you removed the ability to change the OptionsData via your Options

#

And are wondering why the data doesn't change

#

๐Ÿ˜ƒ

warm cobalt
fallen anvil
warm cobalt
fallen anvil
#

And the Options class will pass the values to the OptionsData it's holding

fallen anvil
#

And after that line, put a .Save

warm cobalt
fallen anvil
#

Yes, exactly! You don't need to put Options. tho because you are already in the Options class

fallen anvil
# warm cobalt

You can remove the Save method inside your UI if it's still there

#

You only have to Set the values in options when something changes and it'll be saved automatically because Options itself does the call to the internal Save method

fallen anvil
#

Next thing is, actually setting the stuff via your UI

#

And then it should work fine

warm cobalt
#

this is it

#

only thing thats worrying me is the master volume "script" being in start

#

we'll see i guess

fallen anvil
# warm cobalt

Still not really the preferred architecture, but at least it should work

#

Also, in your Start

#

You want to already apply the settings for fullscreen and all the other stuff

#

Why are you setting Options.SetMasterVolume(slider.value) on start?

#

You want to do slider.value = Options.GetMasterVolume, not the other way around

#

Since your UI should reflect the Options and not vice versa

warm cobalt
#

i have good news and bad news

#

it seems to be changing some stuff in the files

fallen anvil
#

slider.value = GetMasterVolume

toggle.value = GetFullscreen

etc

warm cobalt
#

and the master volume doesnt work

#

like it doesnt save

warm cobalt
fallen anvil
#

The master volume doesn't work because you do AudioManager.Instance.ChangeMasterVolume(slider.value) probably.

You want AudioManager.Instance.ChangeMasterVolume(Options.GetMasterVolume())

warm cobalt
#

i had a slider script and it was in start

fallen anvil
warm cobalt
#

alright

fallen anvil
warm cobalt
#

because i had to move all my scripts for the options into one script

warm cobalt
#

thats not what i meant to do

fallen anvil
#

It's ok, you didn't! Don't worry

#

If you Load the Options, you still need to apply the values to the related UI elements

#

As in

Options.Load();
slider.value = Options...
fullscreenToggle.value = Options...

etc

#

IDK if you did that, but it doesn't look it

warm cobalt
#

i gotta go anyways, ill be back in 2-3 hours

fallen anvil
#

Oki, you'll have a working UnityPackage when you come back ๐Ÿ˜„
And then you should really study the code and try to fully understand what is doing what and why!

fallen anvil
warm cobalt
#

i just realized now that i looked at your code

fallen anvil
#

idk, but i've done the same thing in the past ๐Ÿ˜„

#

it's just easier to modify when using a Toggle, you can replace the Checkmark with a blank Image and color that one

warm cobalt
#

yeah

#

i have a bunch of buttons so im just gonna replace the green one with a red one

#

what do the comments here mean

fallen anvil
#

the comments are where you're supposed to apply your changes to your AudioManager and/or the Screen

#

it wasn't included in the package and i didn't want to create a placeholder one so i've just written those comments

#

i'll be afk for some minutes, but feel free to ask any further questions

warm cobalt
#

im fucking confused

warm cobalt
warm cobalt
#

alright, heres the plan, im gonna wait till i have 1 -2 hours of free time and im gonna implement your scripts since i dont have a lot of time rn

#

i wanna do this as a whole yk

#

not split it up into different parts cuz then im gonna lose focus and its gonna be bad

#

i made a copy of my project currently just to be sure

warm cobalt
#

@fallen anvil what are the comments here for?

#

also does this mean that once i start working on my game in unity i should uncomment this and let it run once then comment it again?

fallen anvil
#

Hey.

As I already said yesterday, those are the spots where you want to apply the Options to the things that care about them

warm cobalt
#

which ss

fallen anvil
#

Both Screenshots are basically doing the same thing.
Applying Options to whoever wants to know about them.
The only difference is that one method applies all option to everything that needs them (at start of your game when loading the Options for the first time) while the other ones only apply the option that's related.

#

As example

#

When you call SetVolume, you set the Value of the OptionsData and you apply that Value to your AudioManager.
It would be preferred to use some kind of Callbacks/Events so the AudioManager could query it's needed Values by itself whenever the Options change, but I tried to keep this Example as simple as possible

warm cobalt
#

why are the commented

fallen anvil
#

Check yesterday's last message of mine

#

There wasn't an AudioManager in the Package you sent, and I didn't want to write a Placeholder one

#

If those lines weren't commented, you'd simply get Compile Errors because the Type doesn't exist

warm cobalt
#

oh yeah mb i didnt even realize i asked the same question yesterday

#

lmao

fallen anvil
#

After all, this is supposed to be an example, not a solution!

warm cobalt
#

alright i got it now

#

sure

fallen anvil
#

Also, quick sidenote.
Idk if it works for you, but in my attempts to use Screen.fullScreen it didn't work as one would expect and I would recommend to use Screen.SetResolution instead.

That one takes in the resolution, the fullScreenMode and the refreshRate as arguments and, from my experiments, will actually change the Window as you'd expect it to happen

https://docs.unity3d.com/ScriptReference/Screen.SetResolution.html

warm cobalt
#

you mean when i build it?

fallen anvil
#

I mean, don't use Screen.fullScreen, use Screen.SetResolution

warm cobalt
#

ok

fallen anvil
#

it's not mandatory, you can use whatever you like, but i think that one is more straightforward.
It's of course hard to test anything Screen related in the Editor, that should be done in a Build

warm cobalt
#

should value here be changed to _optionsData.masterVolume for example?

fallen anvil
#

Oh sorry, stupid me

#

Yes

#

You want to use the Values from OptionsData there

warm cobalt
#

because this is called on the start of every session and you load up the values from the file, right?

#

from the file to the script

fallen anvil
#

It won't actually load the values, they already got loaded in the Load method.
It will apply those loaded values to all the related Objects, hence the name ApplyAllOptions.
But yes, it's called once at the start of every session!

#

Basically, the Load method will load the OptionsData from a file and apply it to the Objects

warm cobalt
#

here if i turn the prettyPrint bool to false will it be harder to read and therefore harder to manipulate the settings through the file?

#

the second one which u said was used to make the text readable

warm cobalt
#

alright so it does save and load the settings but

#

it doesnt save and load the state of the buttons

#

for example

#

ill use the music button as an example

#

at the start its green and the music is on

#

then u turn the music off and now its red

#

then u exit the game

#

then u open it back up

#

now the button is green again but the music is still off

#

do i have to make a different variable in the optionsdata class for that?

#

or i could probably do a check if the musicSource is muted and set the state of the toggle button based on that

warm cobalt
#

@fallen anvil which option do you think is better?

fallen anvil
#

well, you need to change the button of the color to what you want it to be

#

button.targetGraphic.color = ...

warm cobalt