#Save and Load
1 messages ยท Page 1 of 1 (latest)
What's the next step you're wanting to do?
this is the class
as i said, i have no idea how to work with files
so maybe you could help me with that
Give me some minutes, I'll create a simple example, just gotta boot my PC first ๐
sure
i have to store 3 variables:
bool musicIsToggled
bool effectsIsToggled
float masterVolume
or at least thats what i imagine it like
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
whats the point of OptionsData.cs
this
i think i got it
is it for this line?
why not just make 1 class
just options data
wouldnt it work
also i have this different script for my slider + another one for fullscreen, i suppose i should put them all into the optionsUI script?
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
that's just a naming convention that i use, prefixing private members with m_
I'd put them into the OptionsUI script, yes
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
look at this
its reffering to this
@fallen anvil could you help because i cant build because of this error?
Hey
You gotta read the comments I left throughout the code
yeah i read about replacing Aplication.dataPath with persitentDataPath
The code I've written was an example of how you could approach stuff like saving options.
Yes, do that, and then you can just delete the AssetDatabase line
That was purely so you can visualize your save file existing in the Editor
well i copy pasted it ๐ฌ
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
alright
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
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?
Yes, definitely, JSON is a pretty readable text format und can be freely edited, to avoid this you could convert the Json into Binary or apply some Encryption, but if it's a Singleplayer Game and the player wants to cheat this way, let him do it! Only matters if it's online or including real money purchases that are cheatable from that
Encryption sounds harder then it actually is! ๐
i hope
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
https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding?view=net-8.0
You want to use one of the encoding formats that you see fit, and then utilize GetBytes and GetString in the code, although i would recommend to implement this only after you understood the thing and are certain that it works as intended. It's quite valuable to be able to see the SaveData in plain Json throughout the Development
i built it but it doesnt work
it doesnt save the data between sessions
how did you send this as a unity package?
so i can send you the scripts
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
Are you sure?
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
i found the file
But the saving should definitely work
Do the contents look alright?
Start the Build, change some settings, and check the file again, see if it updates correctly
no it doesnt
it doesnt update
Ok, I think it's because where the Options.Save is called (I think I put it in OnDestroy?)
yep
In the Options class
in optionsUi
In every SetXYZ method
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
You are not using the Options class at all?
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?
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
Yes, exactly, you don't have anything to save within SaveColors ๐
Yes! But where do you do it?
here perhaps
That is the code I've written, that will save the OptionsData
obviously no since youre asking
Where is the code you have written to change the OptionsData
its in start tho
this sets the values to the value from the previous session i think
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?
in my mind im supposed to do something like OptionsData.masterVolume = slider.value;
but that doesnt work
You aren't, you don't want to talk with the OptionsData directly, you want to use Options as a middle men
This looks correct, no issues there
but i dont have Set methods only Get
In the package I've sent, there was a SetVolume_Master() method afaik?!
You can easily create your own Set methods by following the example
i removed it cuz i already had a script for my slider
Aaaaah
So you removed the ability to change the OptionsData via your Options
And are wondering why the data doesn't change
๐
im supposed to have something like this in the methods right?
Options.SetFullScreen(...)
Options.SetVolume(...)
Options.SetMusicState(...)
etc
And the Options class will pass the values to the OptionsData it's holding
Yes, exactly! You don't need to put Options. tho because you are already in the Options class
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
oh yeah
this is it
only thing thats worrying me is the master volume "script" being in start
we'll see i guess
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
slider.value = GetMasterVolume
toggle.value = GetFullscreen
etc
thats where the stuff for my slider was at at the beggining
The master volume doesn't work because you do AudioManager.Instance.ChangeMasterVolume(slider.value) probably.
You want AudioManager.Instance.ChangeMasterVolume(Options.GetMasterVolume())
i had a slider script and it was in start
https://docs.unity3d.com/Manual/AssetPackagesCreate.html
Send me the Package if you like, will be home soon
you dont get it, thats not where i load the master volume value, its just that the code that operates the slider is in start
alright
I don't get it? ๐
My example was really simple, and you changed stuff without actually understanding the code and then wondering why it doesn't work..
i think
because i had to move all my scripts for the options into one script
im sorry if i offended you
thats not what i meant to do
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
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!
There it is.
I even tested it in a Build and it's definitely working, everything else is up to your part of the implementation ๐
omg why did i use normal buttons for toggling my music and effects
i just realized now that i looked at your code
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
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
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
im fucking confused
not just by this, by everything
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
@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?
Hey.
As I already said yesterday, those are the spots where you want to apply the Options to the things that care about them
which one are you replying to
which ss
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
why are the commented
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
After all, this is supposed to be an example, not a solution!
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
you mean when i build it?
I mean, don't use Screen.fullScreen, use Screen.SetResolution
ok
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
should value here be changed to _optionsData.masterVolume for example?
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
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
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
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
@fallen anvil which option do you think is better?
well, you need to change the button of the color to what you want it to be
button.targetGraphic.color = ...
its not a button anymore, its toggle