Jump to content
Unity Insider Forum

Mein Scriptable Object löscht gespeicherte Daten nach einiger Zeit


Singular

Recommended Posts

Hallo zusammen,

mein Spiel neigt sich so langsam dem Ende und ich bin bald fertig *freu* aber ich muss noch ein paar Level zusammen klicken. Um jetzt nicht pro Level 100 Vektoren setzen zu müssen oder alles händisch zu machen habe ich mir einen eigenen LevelEditor gebastelt. In dem Level Edito kann ich kurz zusammengefasst meine Blöcke setzen die dann von der Position auf einem Grid gesetzt werden:

 

image.thumb.png.252a2d1ba9a3185228adfa8fb4a7b874.pngSo ungefähr sieht das ganze aus. Die Blöcke oben habe ich durch einfaches klicken gesetzt. Unten habe ich ein paar andere einstellungen Farbe usw.

 

Ich weiß nicht ob man es noch erkennen kann der Wichtige Button ist der in der Mitte. Der soll die Positionen der Blöcke in einem SO abspeichern.

Das Funktioniert auf wunderbar. Wenn ich direkt danach mein SO nehme und in meine GameScene wechsle und dort das SO einsetze kann ich das gerade gebaute Level auch spielen.

Jetzt kann es aber zwei verschiedene Dinge geben die alles gepeicherten Daten in meinem SO löscht. Entweder ich beende das Spiel weil ich das Level ausprobiert habe. Direkt danach ist alles weg, oder ich klicke eine zweites Level zusammen. Dann werden die Daten von dem Level davor gelöscht... (Also Level 1 wird gelöscht obwohl ich gerade Level 2 abgespeichert habe. Level 2 ist dann auch da in einem anderen SO)

Es gibt in meinem Code nur eine einzige Stelle an denen solche Daten gelöscht werden das ist bei meinem Editor wenn das Level überschrieben werden soll (selbst wenn ich diese Zeilen auskomentiere werden die Daten gelöscht)

 

Ich habe im Editorskript nur ein SO abgelegt. Das wechsle ich durch sobald ich das nächste Level anfange.

Weiß jemand woran das liegen könnte? Sind SOs so Fehleranlällig, dass ich sie am besten direkt in Json oder in Text umwandeln sollte...?

Hier der Code für den Editor:

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

public class LevelEditorManager : MonoBehaviour
{
    [Header("Speicherort")]
    public LevelObject saveSpot;

    [Header("Voreinstellungen")]
    public Camera cam;
    public GameObject block;
    public Material[] mat;

    private int matColor = 0;
    private int lifes = 0;

    public List<Vector2> plannedPositions;
    public List<GameObject> plannedBlocks;
    public List<int> plannedMat;
    public List<int> plannedLifes;
    public bool doubleclick = false;

    [Header("UI")]
    public Text lifetext;
    public Image matImage;

    private void Start()
    {
        UIsinc();
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0)) //Prüft Kontinuierlich wo auf dem Bildschirm geklickt wird
        {
            Ray ray = cam.ScreenPointToRay(Input.mousePosition);

            Vector3 v3 = ray.origin;

            Vector2 v2;
            v2.x = berechneX(v3.x);     //Berechent die Koordinate X an der der Block gesetzt werden soll
            v2.y = berechneY(v3.y);     //Berechent die Koordinate Y an der der Block gesetzt werden soll

            if (CheckPosition(v2))      //CheckPosition überprüft ob an der Stelle schon ein Block sitzt
            {                           //Wenn ja, wird der Block gelöscht ansonten geht es hier weiter:
                GameObject b = Instantiate(block, v2, Quaternion.identity); //setzt den Block an der berechneten Stelle

                b.GetComponent<Block>().mat = mat[matColor];       //übergibt dem Block die eingestellte Farbe
                plannedPositions.Add(v2);                          //speichert den Vektor des Blocks
                plannedBlocks.Add(b);                              //speichert den Block (wird später nicht mit abgespeichert
                plannedMat.Add(matColor);                          // speichert die Farbe als int
                plannedLifes.Add(lifes);                           //speichert die leben des Blocks ab
            }
        }
    }

    public void UIsinc()        //Aktualisiert die UI
    {
        lifetext.text = (lifes +1).ToString();
        matImage.material = mat[matColor];
    }

    private float berechneX(float x) //berechnet das Grid für die X koordinate
    private float berechneY(float y) //berechnet das Grid für die Y koordinate

    public void lifePlusMinus(int i) //einstellung der Leben für den Block

    public void MatPlusMinus(int i)  //einstellung der Farbe für den Block

    private bool CheckPosition(Vector2 v2)
    {
        if(v2.x == 88 || v2.y == 88)  //Prüft ob der Spieler außerhalb des Spielfed geklickt hat
        {
            return false;       //Es wird kein neuer Block gesetzt
        }

        for(int i = 0; i < plannedPositions.Count; i++)
        {
            if(v2 == plannedPositions[i])
            {
                plannedPositions.RemoveAt(i);       //löscht die Position des gepeicherten Blocks
                Destroy(plannedBlocks[i]);          //Zerstört das Objekt
                plannedBlocks.RemoveAt(i);          //löscht den Block aus der Liste
                plannedLifes.RemoveAt(i);           //löscht die Leben aus der Liste
                plannedMat.RemoveAt(i);             //löscht die Farbe aus der Liste

                return false;       //Es wird kein neuer Block gesetzt
            }
        }
        return true;
    }

    public void Save()
    {
            bool g = false;                            
            if (saveSpot.blockPos.Count > 0 && doubleclick)     //Es gibt bereits einen Speicherstand & Das war der zweite Klick auf den Button
            {
                Debug.LogWarning("Spielstand wird überschrieben!");
                saveSpot.blockPos.Clear();              //löscht die Alten Daten
                saveSpot.blockMat.Clear();              //löscht die Alten Daten
                saveSpot.blockLifes.Clear();            //löscht die Alten Daten

                g = true;               //Jetzt können die Daten gespeichert werden
            }
            else if (saveSpot.blockLifes.Count > 0 && !doubleclick)     //Es gibt bereits einen Spielstand & Das war der erste Klick auf den Button
            {
                Debug.LogWarning("Soll überschrieben werden?");
                StartCoroutine(Doppelklick());          //zählt einen Timer. In dieser Zeit muss nochmal geklickt werden damit gespeichert wird
            }
            else
            {
                g = true;
            }

            if (g)
            {
                //Speichert die zuvor geplanten Daten in dem Scriptable Object ab    

                for (int i = 0; i < plannedPositions.Count; i++)
                {
                    saveSpot.blockPos.Add(plannedPositions[i]);
                    saveSpot.blockLifes.Add(plannedLifes[i]);
                    saveSpot.blockMat.Add(plannedMat[i]);
                }

                Debug.Log("POSITIONEN GESPEICHERT!!!");
            }
          
    }

    IEnumerator Doppelklick()
    {
        doubleclick = true;
        yield return new WaitForSecondsRealtime(1);
        doubleclick = false;
    }
}

 

 

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Verstehe ich das richtig, dass du ein SO benutzen willst, um Laufzeit-Daten abzuspeichern? Da kann ich ganz kurz und knapp sagen, warum das nicht geht: Weil's nicht geht. Die ScriptableObject-Klasse hat exakt null Funktionalität dafür.

Wenn ich das falsch verstanden habe, sag gerne Bescheid, dann wird's vermutlich schon interessanter :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wobei... 🤔

Eine Frage habe ich da noch... Warum nicht?

Das tue ich doch die ganze Zeit. Dinge, die während der Laufzeit passieren, speichere ich in einem SO. Beispiel wären da die Punkte meines Spielers. Die werden (zur Laufzeit) in einem SO abgelegt damit ich diese die Szenen hinweg über speichern und abrufen kann. Aber nicht nur Szenenübergreifend sondern sogar Spielübergreifend. Ich habe extra, damit ich die Punkte im SO zurück setzen kann einen Button eingebaut, damit diese Punkte wieder zurück gesezt werden um "ein neues Spiel zu starten". Die Punkte kommen auch aus der Laufzeit und werden immer von Spiel zu Spiel, von Neustart zu Neustart übernommen und gespeichert.

Dann wäre meine Frage, WELCHE Daten können während der Laufzeit nicht gespeichert werden? liegt es an der größe, (Vektoren fressen wohl mehr speicher als ein int) oder ist das eher gut glück welche Daten drin liegen und welche nicht?

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 3 Stunden schrieb Singular:

Eine Frage habe ich da noch... Warum nicht?

Das tue ich doch die ganze Zeit.

Ja... im Editor.

Wenn du den Play Mode startest, dann wird die geöffnete Szene entladen und wieder komplett neu geladen. Verlässt du den Play Mode, passiert dasselbe. Alle Änderungen an der Szene werden verworfen und sie wird neu von der Platte geladen. Ist ja auch sehr wichtig, sonst müsstest du nach jedem Testlauf per Hand alles auf Ausgangsposition zurücksetzen. Alle anderen Assets allerdings haben das nicht. Wenn du ein Material oder eine Textur änderst, die in den Assets liegt, dann sind die Änderungen persistent. Kannst du ja einfach ausprobieren, wenn du willst. Und deine ScriptableObjects liegen halt auch als Assets im Assets-Ordner. Dieses ganze Konzept vom Assets-Ordner gibt es aber im Build nicht mehr. ScriptableObjects sind keine einzelnen Dateien mehr, sondern nur noch Objekte, die zur Laufzeit aus den SharedAssets geladen werden.

vor 3 Stunden schrieb Singular:

Dann wäre meine Frage, WELCHE Daten können während der Laufzeit nicht gespeichert werden?

Keine. Du kannst alles und jeden speichern. Nur helfen dir ScriptableObjects dabei halt nicht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...