Page 1 of 1

Which Savers should I attach?

Posted: Wed Oct 30, 2024 8:04 am
by 2linescrossed
Hello!
Currently getting into the weeds of using the savers to store object positions and values, but I've been pretty unsuccessful so far. Got a few of my prefabs attached with Spawned Object savers, but when I load the scene, basically nothing is saved. Some of the game logic works or happens differently (ie normally dialogue plays before the game starts, doesnt happen on a loaded file)- but so far, absolutely none of the object's values or positions are saved, and it's effectively a bit of a scuffed 'new game' in its current state. I don't have any savers on some objects including managers so I assume that's the problem, but should it be the Active saver as the default for most non-persistent managers?

Do objects like spawned-in prefabs need multiple savers, or just one? I think I'm missing something big since basically nothing besides the scene and the Dialogue System variables are saved.

Re: Which Savers should I attach?

Posted: Wed Oct 30, 2024 8:12 am
by 2linescrossed
Oh, and just asking in advance, but would the savers still work fine with IEnumerators and Coroutines? The core of my game's logic is based in them, but I don't know how feasible it is to store one of those 'in motion', since even when it's the player's turn, the game logic is still in the midst of a coroutine.

Re: Which Savers should I attach?

Posted: Wed Oct 30, 2024 8:52 am
by Tony Li
Hi,

It sounds like you have the basics working: a Save System component and its JsonDataSerializer and SavedGameDataStorer prerequisites, as well as a DialogueSystemSaver.

A nice thing about the save system is that we can look at each saver individually. Pick one that isn't working (e.g., a PositionSaver) and let's check it out. Make sure your savers have unique Key values.

For spawned objects, please see page 11 of Save_System_Manual.pdf located in Assets\Plugins\Pixel Crushers\Common\ Documentation.

Unlike most other save systems that just save and restore variable values, the Dialogue System's save system is designed to support restoring processes "in motion." You'll need to write a custom saver. (See How To: Write Custom Savers.) In the ApplyData() method, restart your coroutine.

Re: Which Savers should I attach?

Posted: Wed Oct 30, 2024 6:39 pm
by 2linescrossed
Hmm, so if I'm interpreting what you're implying right - you're saying that I don't need to put savers on everything, because the 'states' of an object (ie, active/enabled/disabled etc) is separate from the actual values on an object, and things are screwing up because of the managers not retaining values yet?
I'm guessing that the save system would normally save everything in a scene, barring the 'states', so changed variables and whatnot should be intact?
If I'm wrong, my original question was, 'which of the savers should I be attaching so that these values are being saved at all'.

As for the coroutine saving, I assume for the custom saver, I should try and store what state the game is in. Part of what may be happening right now seems to be that it goes into the pre-game coroutine and thus resets everything, so I'd have to check a enum and set the coroutine to be retained to be the right one through finding that out?

Re: Which Savers should I attach?

Posted: Wed Oct 30, 2024 7:40 pm
by Tony Li
Hi,

For your first question, the save system only saves what the savers record. For example, if the only saver in a scene is a single Position Saver, then for that scene the save system will only save the position of Position Saver's GameObject and no other data.

For your second question, yes. Your saver should record whatever data it needs to be able to restart processes such as coroutines. For example, say you have a Bomb script like this:

Code: Select all

using System.Collections;
using UnityEngine;

public class Bomb : MonoBehaviour
{
    public float fuseDuration = 5;
    
    public float TimeLeft {get; private set;}
    
    private void Start()
    {
        StartCountdown(fuseDuration);
    }
    
    public void StartCountdown(float duration)
    {
        StartCoroutine(Countdown(duration));
    }
    
    private IEnumerator Countdown(float duration)
    {
        TimeLeft = duration;
        while (TimeLeft > 0)
        {
            yield return null;
            TimeLeft -= Time.deltaTime;
        }
        Debug.Log("BOOM!!!");
    }
}
Then you could write a saver like this:

Code: Select all

using UnityEngine;
using PixelCrushers;

[RequireComponent(typeof(Bomb))]
public class BombSaver : Saver
{
    public override string RecordData()
    {
        float timeLeft = GetComponent<Bomb>().TimeLeft;
        return timeLeft.ToString();
    }
    
    public override void ApplyData(string s)
    {
        float timeLeft = float.Parse(s);
        GetComponent<Bomb>().StartCountdown(timeLeft);
    }
}