I have a script that start a coroutine with postprocessing effect.
I want that for example when I press on the S key it will save the coroutine at the current point it is while the coroutine is running and then later sometime in the game if I will press on the L key it will load the coroutine from the point it was saved and that the coroutine will continue it’s work from the current point. Not just saving static but to continue the coroutine from the saved point when loading it back.
This is my coroutine script with the postprocessing effect changing the FocalLength value.
I want to save the coroutine and focalLength states and when loading to make the coroutine to continue with the focalLength value from the saved point.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.PostProcessing;
public class DepthOfField : MonoBehaviour
{
public UnityEngine.GameObject player;
public PostProcessingProfile postProcessingProfile;
public bool dephOfFieldFinished = false;
public LockSystem playerLockMode;
private Animator playerAnimator;
private float clipLength;
private Coroutine depthOfFieldRoutineRef;
// Start is called before the first frame update
void Start()
{
if (depthOfFieldRoutineRef != null)
{
StopCoroutine(depthOfFieldRoutineRef);
}
playerAnimator = player.GetComponent<Animator>();
AnimationClip[] clips = playerAnimator.runtimeAnimatorController.animationClips;
foreach (AnimationClip clip in clips)
{
clipLength = clip.length;
}
DepthOfFieldInit(clipLength);
// Don't forget to set depthOfFieldRoutineRef to null again at the end of routine!
}
public void DepthOfFieldInit(float duration)
{
var depthOfField = postProcessingProfile.depthOfField.settings;
depthOfField.focalLength = 300;
StartCoroutine(changeValueOverTime(depthOfField.focalLength, 1, duration));
postProcessingProfile.depthOfField.settings = depthOfField;
}
public IEnumerator changeValueOverTime(float fromVal, float toVal, float duration)
{
playerLockMode.PlayerLockState(true, true);
float counter = 0f;
while (counter < duration)
{
var dof = postProcessingProfile.depthOfField.settings;
counter += Time.deltaTime;
float val = Mathf.Lerp(fromVal, toVal, counter / duration);
dof.focalLength = val;
postProcessingProfile.depthOfField.settings = dof;
yield return null;
}
playerAnimator.enabled = false;
dephOfFieldFinished = true;
depthOfFieldRoutineRef = null;
}
}
I want to save and load from a format binary file. But the problem is how to get and save the states and then load them and make them continue ?
The coroutine and the save/load are entirely separate issues. Focus on save/load of the focalLength and any other data first. Once that is solid, then take on the separate issue of starting your coroutine with supplied current state information. Treating both entirely separate issues as one problem only leads to confusion.
So for save/load, figure out where you want it saved. There’s lots of info on using PlayerPrefs for example.
I forgot to add it to my question. But I already have a saving/loading system I created that save the staes ot a binary format file. And I’m using it already in other parts in my game. Now I added it also to this script too look at the bottom for the new struct and save/load methods :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.PostProcessing;
public class DepthOfField : MonoBehaviour
{
public UnityEngine.GameObject player;
public PostProcessingProfile postProcessingProfile;
public bool dephOfFieldFinished = false;
public LockSystem playerLockMode;
private Animator playerAnimator;
private float clipLength;
private Coroutine depthOfFieldRoutineRef;
private DepthOfFieldModel.Settings depthOfField;
// Start is called before the first frame update
void Start()
{
if (depthOfFieldRoutineRef != null)
{
StopCoroutine(depthOfFieldRoutineRef);
}
playerAnimator = player.GetComponent<Animator>();
AnimationClip[] clips = playerAnimator.runtimeAnimatorController.animationClips;
foreach (AnimationClip clip in clips)
{
clipLength = clip.length;
}
DepthOfFieldInit(clipLength);
// Don't forget to set depthOfFieldRoutineRef to null again at the end of routine!
}
public void DepthOfFieldInit(float duration)
{
depthOfField = postProcessingProfile.depthOfField.settings;
depthOfField.focalLength = 300;
StartCoroutine(changeValueOverTime(depthOfField.focalLength, 1, duration));
postProcessingProfile.depthOfField.settings = depthOfField;
}
public IEnumerator changeValueOverTime(float fromVal, float toVal, float duration)
{
playerLockMode.PlayerLockState(true, true);
float counter = 0f;
while (counter < duration)
{
var dof = postProcessingProfile.depthOfField.settings;
counter += Time.deltaTime;
float val = Mathf.Lerp(fromVal, toVal, counter / duration);
dof.focalLength = val;
postProcessingProfile.depthOfField.settings = dof;
yield return null;
}
playerAnimator.enabled = false;
dephOfFieldFinished = true;
depthOfFieldRoutineRef = null;
}
public struct DepthField
{
public float focalLength;
}
public void Save()
{
DepthField state = new DepthField();
state.focalLength = depthOfField.focalLength;
SaveGame.Save("depthoffieldstate", state);
}
public void Load()
{
DepthField state = SaveGame.Load<DepthField>("depthoffieldstate");
depthOfField.focalLength = state.focalLength;
}
}
So now I can save the focalLength value and load it. I will call the Save method like I did in other scripts.
My problem is how to get the current coroutine state ? And save it and load it like I did with the focalLength value.
I can save any type of state in this line :
SaveGame.Save("depthoffieldstate", state);
It can be a bool or int float or gameobject info or transform info.