Unity błąd przy zapisie danych

0

Próbuje zrobić zapis ustawień w unity ale mam taki błąd

SerializationException: End of Stream encountered before parsing was completed.
System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run () (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize (System.Runtime.Remoting.Messaging.HeaderHandler handler, System.Runtime.Serialization.Formatters.Binary.__BinaryParser serParser, System.Boolean fCheck, System.Boolean isCrossAppDomain, System.Runtime.Remoting.Messaging.IMethodCallMessage methodCallMessage) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler, System.Boolean fCheck, System.Boolean isCrossAppDomain, System.Runtime.Remoting.Messaging.IMethodCallMessage methodCallMessage) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler, System.Boolean fCheck, System.Runtime.Remoting.Messaging.IMethodCallMessage methodCallMessage) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler, System.Boolean fCheck) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
Settings.Load () (at Assets/Scripts/Settings/Settings.cs:54)
Settings.Start () (at Assets/Scripts/Settings/Settings.cs:24)

A to mój kod

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;


public class Settings : MonoBehaviour
{

    public Slider musicSlider;
    public Slider soundsSlider;
    public GameObject music;
    float musicVolume;
    float soundsVolume;
    AudioSource source;

    // Start is called before the first frame update
    void Start()
    {
       source = music.GetComponent<AudioSource>();
       Load();
    }
 
    // Update is called once per frame
    void Update()
    {
        
    }

    public void save()
    {
        musicVolume = musicSlider.value;
        source.volume = musicVolume;

        BinaryFormatter binaryFormatter = new BinaryFormatter();
        FileStream saveSettings = File.Create(Application.persistentDataPath + "/Settings.txt");
        Settings settings = new Settings();

        settings.musicVolume = musicVolume;
        settings.soundsVolume = soundsVolume;

        binaryFormatter.Serialize(saveSettings, settings);
        saveSettings.Close();
    }
    public void Load()
    {
        if(File.Exists(Application.persistentDataPath + "/Settings.s"))
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            FileStream saveSettings = File.Open(Application.persistentDataPath + "/Settings.txt", FileMode.Open);
            Settings settings = (Settings)binaryFormatter.Deserialize(saveSettings);
            saveSettings.Close();

            musicVolume = settings.musicVolume;
            soundsVolume = settings.soundsVolume;

            musicSlider.value = musicVolume;
            soundsSlider.value = soundsVolume;
            
        }
    }
}
[Serializable]
class SEttings
{
    float musicVolume;
    float soundsVolume;
}

1

Load() nie sprawdza, czy istnieje plik Settings.txt, tylko Settings.s, a cała reszta raczej używa txt...
Zrób sobie np. odpowiednie property z getterem zwracającym ścieżkę do pliku i wszędzie podawaj to property, zamiast składanego stringa.

0

@Spine: A i jak klikam Przycisk wywolujący save mam taki błąd
SerializationException: Type 'Settings' in Assembly 'Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers (System.RuntimeType type) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.FormatterServices+<>c__DisplayClass9_0.<GetSerializableMembers>b__0 (System.Runtime.Serialization.MemberHolder _) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Collections.Concurrent.ConcurrentDictionary2[TKey,TValue].GetOrAdd (TKey key, System.Func2[T,TResult] valueFactory) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.FormatterServices.GetSerializableMembers (System.Type type, System.Runtime.Serialization.StreamingContext context) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo () (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize (System.Object obj, System.Runtime.Serialization.ISurrogateSelector surrogateSelector, System.Runtime.Serialization.StreamingContext context, System.Runtime.Serialization.Formatters.Binary.SerObjectInfoInit serObjectInfoInit, System.Runtime.Serialization.IFormatterConverter converter, System.Runtime.Serialization.Formatters.Binary.ObjectWriter objectWriter, System.Runtime.Serialization.SerializationBinder binder) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize (System.Object obj, System.Runtime.Serialization.ISurrogateSelector surrogateSelector, System.Runtime.Serialization.StreamingContext context, System.Runtime.Serialization.Formatters.Binary.SerObjectInfoInit serObjectInfoInit, System.Runtime.Serialization.IFormatterConverter converter, System.Runtime.Serialization.Formatters.Binary.ObjectWriter objectWriter, System.Runtime.Serialization.SerializationBinder binder) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize (System.Object graph, System.Runtime.Remoting.Messaging.Header[] inHeaders, System.Runtime.Serialization.Formatters.Binary.__BinaryWriter serWriter, System.Boolean fCheck) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph, System.Runtime.Remoting.Messaging.Header[] headers, System.Boolean fCheck) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph, System.Runtime.Remoting.Messaging.Header[] headers) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph) (at <eae584ce26bc40229c1b1aa476bfa589>:0)
Settings.save () (at Assets/Scripts/Settings/Settings.cs:45)
UnityEngine.Events.InvokableCall.Invoke () (at <31d5d65b32ec483292e13e8ae4100b93>:0)
UnityEngine.Events.UnityEvent.Invoke () (at <31d5d65b32ec483292e13e8ae4100b93>:0)
UnityEngine.UI.Button.Press () (at C:/Program Files/Unity/Hub/Editor/2020.2.6f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/UI/Core/Button.cs:68)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/Program Files/Unity/Hub/Editor/2020.2.6f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/UI/Core/Button.cs:110)
UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/Program Files/Unity/Hub/Editor/2020.2.6f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/EventSystem/ExecuteEvents.cs:50)
UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1] functor) (at C:/Program Files/Unity/Hub/Editor/2020.2.6f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/EventSystem/ExecuteEvents.cs:262)
UnityEngine.EventSystems.EventSystem:Update() (at C:/Program Files/Unity/Hub/Editor/2020.2.6f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/EventSystem/EventSystem.cs:385)

0
  1. Klasa Settings dziedziczy po MonoBehaviour i tworzysz ją używając new. Unity sam sobie tworzy instancje skryptów podpiętych pod obiekty, nie tworzy się ich samemu za pomocą new...

Zrób sobie prostą klasę UserData z atrybutem System.Serializable oraz publicznymi polami:

public static UserData current;

public float musicVolume;
public float soundsVolume;

Jeśli pola nie będą publiczne, to nie będą serializowane, więc i tak nic byś nie zapisał...

Zrób drugą klasę, np. UserDataManager, która będzie będzie zarządzać instancją klasy UserData. Ona może dziedziczyć po MonoBehaviour i być dołączona do jakiegoś obiektu na scenie.
W UserDataManager ładujesz dane: przypisujesz wczytaną z pliku instancję UserData do pola UserData.current. Jeśli plik nie istniał to tworzysz nową instancję UserData.current = new UserData();. Zapisywanie danych do pliku to serializacja obiektu z pola UserData.current.

  1. Do zapisu ustawień, a także innych danych w małej grze najlepiej użyj PlayerPrefs:

https://docs.unity3d.com/ScriptReference/PlayerPrefs.SetFloat.html
https://docs.unity3d.com/ScriptReference/PlayerPrefs.GetFloat.html
https://docs.unity3d.com/ScriptReference/PlayerPrefs.Save.html

Wtedy nic nie musisz serializować. Łatwiej Ci będzie ;)

1

@Spine: Dzięki za pomoc próbowałem to zrobić w pliku bo po prostu wyszukałem w Internecie jak zapisać ustawienia. A PlayerPrefs jest o wiele prostsze :)

0

@ImpossibleYTPL: Serializacja przyda się, kiedy będziesz chciał zapisywać bardziej skomplikowane dane, np. listy kupionych przedmiotów. Chociaż na siłę można to upchnąć jako string do PlayerPrefs...

1 użytkowników online, w tym zalogowanych: 0, gości: 1