• Advertisement

Unity not saving to Json file anymore?

Recommended Posts

Hey Community,

I have a question about C# and Unity.

For my options menu I wrote a script with C#, that worked fine for a while.

My problem is to let unity write a .Json file into the LocalLow folder. At first everything went fine and there occurred no errors, but now the file is only generated completely empty. I didn't change anything in the script and Visual Studio doesn't show any errors to me, so I have no clue what is wrong.

As I'm only a beginner, I hope anyone of you guys can find what I messed up and give me some advices.

Code for the GameSettings

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameSettings
{
    //all variables assigned to their class. 
    public bool fullscreen;
    public float musicvolume;
    public float audiovolume;
    public int difficulty;
    public bool subtitles;
    public int Language;
    public int vsync;
    public int texturequality;
    public int resolution;
    public float gamma;
    public int antialiasing;
    public bool autosave;
}

Code for the SettingManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;

public class SettingManager : MonoBehaviour
{
    //all variables assigned to their class. 
    public Slider musicvolumeslider;
    public Toggle fullscreenToggle;
    public Slider audiovolumeSlider;
    public Dropdown difficultyDropdown;
    public Toggle subtitlesToggle;
    public Dropdown languageDropdown;
    public Dropdown vsyncDropdown;
    public Dropdown texturequalityDropdown;
    public Slider gammaSlider;
    public Dropdown antialiasingDropdown;
    public Toggle autosaveToggle;
    public Dropdown resolutionDropdown;
    public Button closeButton;

    public AudioSource musicSource;
    public Resolution[] resolutions;
    public GameSettings gameSettings;

    void OnEnable()
    {
        DontDestroyOnLoad(gameObject);
        musicvolumeslider.onValueChanged.AddListener(delegate { OnMusicVolumeChange(); });
        fullscreenToggle.onValueChanged.AddListener(delegate { OnFullscreenToggle(); });
        audiovolumeSlider.onValueChanged.AddListener(delegate { OnAudioVolumeChange(); });
        difficultyDropdown.onValueChanged.AddListener(delegate { OnDifficultyChange(); });
        subtitlesToggle.onValueChanged.AddListener(delegate { OnSubtitlesChange(); });
        languageDropdown.onValueChanged.AddListener(delegate { OnLanguageChange(); });
        vsyncDropdown.onValueChanged.AddListener(delegate { OnVSyncChange(); });
        texturequalityDropdown.onValueChanged.AddListener(delegate { OnTextureQualityChange(); });
        gammaSlider.onValueChanged.AddListener(delegate { OnGammaChange(); });
        autosaveToggle.onValueChanged.AddListener(delegate { OnAutosaveToggle(); });
        antialiasingDropdown.onValueChanged.AddListener(delegate { OnAAChange(); });
        resolutionDropdown.onValueChanged.AddListener(delegate { OnResolutionChange(); });
        closeButton.onClick.AddListener(delegate { OnCloseButtonClick(); });

        musicSource = GameObject.FindGameObjectWithTag("music").GetComponent<AudioSource>();
        gameSettings = new GameSettings();
        resolutions = Screen.resolutions;
        foreach (Resolution resolution in resolutions)
        {
            resolutionDropdown.options.Add(new Dropdown.OptionData(resolution.ToString()));
        }
        LoadSettings();
    }

    public void OnMusicVolumeChange()
    {
        musicSource.volume = gameSettings.musicvolume = musicvolumeslider.value;
    }
    public void OnResolutionChange()
    {
        Screen.SetResolution(resolutions[resolutionDropdown.value].width, resolutions[resolutionDropdown.value].height, Screen.fullScreen);
        gameSettings.resolution = resolutionDropdown.value;
    }
    public void OnFullscreenToggle()
    {
        gameSettings.fullscreen = Screen.fullScreen = fullscreenToggle.isOn;
    }
    public void OnAudioVolumeChange()
    {
        AudioListener.volume = gameSettings.audiovolume = audiovolumeSlider.value;
    }
    public void OnDifficultyChange()
    {
        //Not Implemented Yet
    }
    public void OnSubtitlesChange()
    {
        //Not Implemented Yet
    }
    public void OnLanguageChange()
    {
        if (languageDropdown.value == 0)
            LocalizationService.Instance.Localization = "English";
        if (languageDropdown.value == 1)
            LocalizationService.Instance.Localization = "German";
        if (languageDropdown.value == 2)
            LocalizationService.Instance.Localization = "French";
        if (languageDropdown.value == 3)
            LocalizationService.Instance.Localization = "Russian";
        if (languageDropdown.value == 4)
            LocalizationService.Instance.Localization = "Italian";
        if (languageDropdown.value == 5)
            LocalizationService.Instance.Localization = "Chinese";
    }
    public void OnVSyncChange()
    {
        QualitySettings.vSyncCount = gameSettings.vsync = vsyncDropdown.value;
    }
    public void OnTextureQualityChange()
    {
        QualitySettings.masterTextureLimit = gameSettings.texturequality = texturequalityDropdown.value;
    }
    public void OnGammaChange()
    {
        //Not Implemented Yet
    }
    public void OnAAChange()
    {
        QualitySettings.antiAliasing = (int)Mathf.Pow(2, antialiasingDropdown.value);
        gameSettings.antialiasing = antialiasingDropdown.value;
    }
    public void OnAutosaveToggle()
    {
        //Not Implemented Yet
    }
    public void OnCloseButtonClick()
    {
        SaveSettings();
    }
    public void SaveSettings()
    {
        string jsonData = JsonUtility.ToJson(gameSettings, true);
        File.WriteAllText(Application.persistentDataPath + "/gamesettings.json", jsonData);
    }
    public void LoadSettings()
    {
        gameSettings = JsonUtility.FromJson<GameSettings>(File.ReadAllText(Application.persistentDataPath + "/gamesettings.json"));
        audiovolumeSlider.value = gameSettings.audiovolume;
        antialiasingDropdown.value = gameSettings.antialiasing;
        gammaSlider.value = gameSettings.gamma;
        texturequalityDropdown.value = gameSettings.texturequality;
        vsyncDropdown.value = gameSettings.vsync;
        languageDropdown.value = gameSettings.Language;
        subtitlesToggle.isOn = gameSettings.subtitles;
        Screen.fullScreen = gameSettings.fullscreen;
        difficultyDropdown.value = gameSettings.difficulty;
        resolutionDropdown.value = gameSettings.resolution;
        autosaveToggle.isOn = gameSettings.autosave;
        musicvolumeslider.value = gameSettings.musicvolume;

        resolutionDropdown.RefreshShownValue();

    }
}

Hoping for fast help,

SanguineTunic

Share this post


Link to post
Share on other sites
Advertisement

Generally, it's best to only post the code that you think is relevant. In this case, that's probably only these lines:

        string jsonData = JsonUtility.ToJson(gameSettings, true);
        File.WriteAllText(Application.persistentDataPath + "/gamesettings.json", jsonData);

First, you should use the Visual Studio debugger, or maybe a Debug.Log call, to see if anything is going into that jsonData string. If not, it implies that your GameSettings class isn't serialisable. The docs forToJson say that it "it must be a MonoBehaviour, ScriptableObject, or plain class/struct with the Serializable attribute applied. " I don't see that as being true in your case. You probably need to add that Serializable attribute.

 

Share this post


Link to post
Share on other sites

Hmm, I tested the save section with a debug.Log and it clearly is called when clicking on the apply button.

I don't get what is wrong. It worked like a charm at first! So, thanks for your fast reply. I hope there is a solution to my problem anywhere, as what you mentioned about the missing Serializable attribute didn't help.

 

Share this post


Link to post
Share on other sites

The point of my logging suggest line isn't to see whether it's being called - the point is to log the content of jsonData and see what is being stored in there.

And if you've added the Serializable property, show us what you have now, so that someone might be able to test it themselves.

Share this post


Link to post
Share on other sites

Oh, Sorry. Misunderstood that. This is what comes out when I log the content:

<string jsonData = JsonUtility.ToJson(gameSettings, true)>
UnityEngine.Debug:Log(Object)
SettingManager:SaveSettings() (at Assets/Menu/Main Scripts/SettingManager.cs:130)
SettingManager:OnCloseButtonClick() (at Assets/Menu/Main Scripts/SettingManager.cs:126)
SettingManager:<OnEnable>m__C() (at Assets/Menu/Main Scripts/SettingManager.cs:43)
UnityEngine.EventSystems.EventSystem:Update()

 

Share this post


Link to post
Share on other sites

I now found one possible cause, after starting the game in built mode with development mode active.

When saving it says:

Quote

IsolatedStorageException: Could not find part of the path "C:\users\Sanguine\AppData\LocalLow\SanguineTunic\ProjectName\gamesettings.json"

I don't get why... The path is exactly the same as it should be.

Maybe one of you can find the mistake I made.

Share this post


Link to post
Share on other sites

I don't know what you've done with that log line, but you should be able to print the actual content of the string (whereas what you've got there is the line of code, strangely) and see if there's actually any JSON in it. Better still, put a breakpoint in the debugger on that line, and use the debugger to see what is in there.

No idea about the IsolatedStorageException - that might be something worth asking on the Unity forums about.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Advertisement
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By mark_braga
      Currently, our framework only supports loading binary shader code. The way we do it in Visual Studio is through custom build tool per shader file. Now we also want to support shader recompilation when a user presses some key. This is tricky since now we don't have access to the source files. So I was thinking, if there is some way to export all the commands from the custom build tool to a text file, then we can just load that text file and execute all commands inside and then just do the regular shader loading as we do it right now.
      Example custom build tool command for a shader which has vertex, pixel, and geometry shader stages:
      fxc %(Identity) /E VSMain /T vs_5_0 $(HLSLCompileFlags) /Fo %(Identity)\..\Binary\%(Filename).vert.bin fxc %(Identity) /E PSMain /T ps_5_0 $(HLSLCompileFlags) /Fo %(Identity)\..\Binary\%(Filename).frag.bin fxc %(Identity) /E GSMain /T gs_5_0 $(HLSLCompileFlags) /Fo %(Identity)\..\Binary\%(Filename).geom.bin So here is the process-
      - Run custom build rules for the shader files
      - In post-build event of the project, collect all these custom build tool commands and dump them to a text file
      - Now if user wants to recompile, just load this text file and execute all commands inside
      How would I get access to these custom build tool commands in the post-build event?
    • By MarcusAseth
      I'm not sure if this is the right place for this question, but I'll give it shot
      Using Visual Studio Code, I have the task.json set up to launch a batch file that is set up like follow:
      @echo off call "Z:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x86 set INC_PROJECT_PATH="Z:\Asus\Documenti\VS Code\Projects\Packman Clone 1" set INC_SDL_PATH="Z:\Dependencies\SDL2-2.0.5\SLD2" set SOURCE1_PATH="Z:\Asus\Documenti\VS Code\Projects\Packman Clone 1\source\*.cpp" set SOURCE2_PATH="Z:\Asus\Documenti\VS Code\Projects\Packman Clone 1\Engine\*.cpp" set LIB_SDL_PATH="Z:\Dependencies\SDL2-2.0.5\lib\x86" set OUTPUT_PATH="Z:\Asus\Documenti\VS Code\Projects\Packman Clone 1\Debug\Pacman.exe" cl /std:c++latest /W4 /ZI ^ /I %INC_SDL_PATH% /I %INC_PROJECT_PATH% ^ /EHsc %SOURCE1_PATH% %SOURCE2_PATH% ^ /link /SUBSYSTEM:CONSOLE ^ /LIBPATH:%LIB_SDL_PATH% SDL2main.lib SDL2.lib ^ /out:%OUTPUT_PATH% I'm not totally sure about what it's doing and I'm piecing it togeter as I go (trial and error + google), so if I got it right, the *.cpp at the end of those paths,  it means that every time I build it will build all the .cpp that it finds in those 2 paths.
      And that doesn't sounds good, so I was wondering, there is a way to tell it to re-compile only the files that have changed?  
    • By Josheir
      SFML is portable on windows Linux and Mac.  So a game created on Windows to be ported to Mac must be compiled on that computer using portable C++ code?
      Another problem/question that is more specific:
      I am writing a game using Windows C++ and SFML.  Using a resource for the image seems to be possible, but I will have to alter the code when porting because this 'belongs to' Window's Visual Studio C++?  
      The other option is to keep the images in a folder that would be viewable and loadable.  This I think would run on Linux and Macintosh.  It just doesn't seem to be to professional.  Any advice?
      Thank you,
      Josheir
    • By mister345
      Hi guys, so I have about 200 files isolated in their own folder [physics code] in my Visual Studio project that I never touch. They might as well be a separate library, I just keep em as source files in case I need to look at them or step through them, but I will never actually edit them, so there's no need to ever build them.
      However, when I need to rebuild the entire solution because I changed the other files, all of these 200 files get rebuilt too and it takes a really long time.
      If I click on their properties -> exclude from build, then rebuild, it's no good because then all the previous built objects get deleted automatically, so the build will fail.
      So how do I make the built versions of the 200+ files in the physics directory stay where they are so I never have to rebuild them, but
      do a normal rebuild for everything else? Any easy answers to this? The simpler the better, as I am a noob at Visual Studio settings. Thanks.
    • By jonwil
      I am writing a level editor using Visual C++ and the win32 API. I have the game engine going working fine with Direct3D 11 (its not an off-the-shelf engine, its custom)
      The plan for the editor is to have something like this:

      The blue bit is going to be a standard win32 menu bar, the yellow bit will be a standard win32 status bar, the red bit will contain things like a list of objects to insert into the level (its contents will change depending on what the user is doing) and the purple bit will be a window that will be rendered into by the rendering code. I know how to do Direct3D11 rendering into a window that is the parent window and is the only thing the app is drawing (the engine runs a loop that lets the windows message loop run and process its messages before running the engine code and doing rendering) but I can't find anything out there on how you do Direct3D graphics (11 or otherwise) into a child window and how you handle things like resizing and painting and things. Its definitely possible since so many level editors and things do it but I dont know how they pull it off. (and Google isn't showing anything useful either)
      Are there any examples out there of how you can create a win32 custom control/child window, set up a IDirect3D11Device to draw onto that window and then have that window play nice with all the other windows (the main parent window and the other child windows) whilst still triggering a once-per-frame render call to allow me to draw my stuff in there.
  • Advertisement