[HOWTO] How To: Save Enviro - Sky and Weather

Announcements, support questions, and discussion for Quest Machine.
Post Reply
User avatar
Tony Li
Posts: 22131
Joined: Thu Jul 18, 2013 1:27 pm

[HOWTO] How To: Save Enviro - Sky and Weather

Post by Tony Li »

You can use the package below to save Henrik Haupt's Enviro - Sky and Weather with the Pixel Crushers Save System. The package contains the script shown below and a test scene.

PixelCrushers_EnviroSaver_2020-07-21.unitypackage

EnviroSaver.cs

Code: Select all

using System;
using PixelCrushers;

/// <summary>
/// Pixel Crushers Save System saver for Hendrik Haupt's Enviro.
/// </summary>
public class EnviroSaver : Saver
{
    [Serializable]
    public class Data
    {
        public float timeOfDay;
        public int days;
        public int years;
    }

    private Data m_data = new Data();

    public override string RecordData()
    {
        m_data.timeOfDay = EnviroSkyMgr.instance.GetTimeOfDay();
        m_data.days = EnviroSkyMgr.instance.Time.Days;
        m_data.years = EnviroSkyMgr.instance.Time.Years;
        return SaveSystem.Serialize(m_data);
    }

    public override void ApplyData(string s)
    {
        if (string.IsNullOrEmpty(s)) return;
        m_data = SaveSystem.Deserialize<Data>(s, m_data);
        if (m_data == null)
        {
            m_data = new Data();
        }
        else
        {
            EnviroSkyMgr.instance.SetTimeOfDay(m_data.timeOfDay);
            EnviroSkyMgr.instance.Time.Days = m_data.days;
            EnviroSkyMgr.instance.Time.Years = m_data.years;
        }
    }

}
alsoknownas-stefan
Posts: 29
Joined: Fri Jul 17, 2020 9:19 am

Re: How To: Save Enviro - Sky and Weather

Post by alsoknownas-stefan »

Cool, I was looking for a weather/day/night system that could hook into Dialogue System. :D

Does this require any work on the Enviro side?
User avatar
Tony Li
Posts: 22131
Joined: Thu Jul 18, 2013 1:27 pm

Re: How To: Save Enviro - Sky and Weather

Post by Tony Li »

Only untick the Enviro manager's Don't Destroy On Load checkbox. No other Enviro changes needed.

If you're using the Dialogue System, it also includes Unistorm integration in case you'd prefer to use Unistorm instead of Enviro.
alsoknownas-stefan
Posts: 29
Joined: Fri Jul 17, 2020 9:19 am

Re: How To: Save Enviro - Sky and Weather

Post by alsoknownas-stefan »

Hi Tony,

It has been a while, hope you are doing fine.

I am having trouble integrating Enviro. I got your example to work, time becomes what it was on the moment of saving when loading (scene transitions also work fine). I am trying to do the same for the weather. I am having no luck. It seems that the weather is being overwritten with the startWeatherPreset when loading the game/when Enviro Sky Manager enters the scene. My small lizard brain came up with a few ideas (using ChangeWeatherInstant(); changing startWeatherPreset and currentActiveWeatherPreset on load), but alas on load it still jumps to the starting weather...
Do you have any ideas? Code:



using System;
using PixelCrushers;

/// <summary>
/// Pixel Crushers Save System saver for Hendrik Haupt's Enviro.
/// </summary>
public class EnviroSaver : Saver
{
[Serializable]
public class Data
{
public float timeOfDay;
public int days;
public int years;
public EnviroWeatherPreset weather;
}

private Data m_data = new Data();

public override string RecordData()
{
m_data.timeOfDay = EnviroSkyMgr.instance.GetTimeOfDay();
m_data.days = EnviroSkyMgr.instance.Time.Days;
m_data.years = EnviroSkyMgr.instance.Time.Years;
m_data.weather = EnviroSkyMgr.instance.Weather.currentActiveWeatherPreset;
return SaveSystem.Serialize(m_data);
}

public override void ApplyData(string s)
{
if (string.IsNullOrEmpty(s)) return;
m_data = SaveSystem.Deserialize<Data>(s, m_data);
if (m_data == null)
{
m_data = new Data();
}
else
{
EnviroSkyMgr.instance.SetTimeOfDay(m_data.timeOfDay);
EnviroSkyMgr.instance.Time.Days = m_data.days;
EnviroSkyMgr.instance.Time.Years = m_data.years;
EnviroSkyLite.instance.Weather.startWeatherPreset = m_data.weather;
EnviroSky.instance.Weather.startWeatherPreset = m_data.weather;
EnviroSkyMgr.instance.Weather.currentActiveWeatherPreset = m_data.weather;
EnviroSkyMgr.instance.ChangeWeatherInstant(m_data.weather);

}
}

}
User avatar
Tony Li
Posts: 22131
Joined: Thu Jul 18, 2013 1:27 pm

Re: How To: Save Enviro - Sky and Weather

Post by Tony Li »

Hi,

I haven't had a chance to test it, but maybe Enviro takes a frame or two to initialize the weather. If that's the case, you can try setting the Save System component's 'Frames To Wait Before Apply Data' to a higher value such as 2 or 3. Or you can make ApplyData() kick off a coroutine that waits a few frames before calling ChangeWeatherInstant().

Alternatively, you can implement ApplyDataImmediate() to change the presets before Enviro sets up the scene's weather. ApplyDataImmediate() will be called as soon as the scene has finished loading.
alsoknownas-stefan
Posts: 29
Joined: Fri Jul 17, 2020 9:19 am

Re: How To: Save Enviro - Sky and Weather

Post by alsoknownas-stefan »

Hi Tony,

You never cease to amaze me. It works. :D

I set the Save System component's 'Frames To Wait Before Apply Data' to 3. I made a small change to my EnviroSaver script and now it works perfectly, using save and load functions and during scene transitions. Thank you again!

Final script of the custom saver for Enviro:

using System;
using PixelCrushers;

/// <summary>
/// Pixel Crushers Save System saver for Hendrik Haupt's Enviro.
/// </summary>
public class EnviroSaver : Saver
{
[Serializable]
public class Data
{
public float timeOfDay;
public int days;
public int years;
public EnviroWeatherPreset weather;
}

private Data m_data = new Data();

public override string RecordData()
{
m_data.timeOfDay = EnviroSkyMgr.instance.GetTimeOfDay();
m_data.days = EnviroSkyMgr.instance.Time.Days;
m_data.years = EnviroSkyMgr.instance.Time.Years;
m_data.weather = EnviroSkyMgr.instance.Weather.currentActiveWeatherPreset;
return SaveSystem.Serialize(m_data);
}

public override void ApplyData(string s)
{
if (string.IsNullOrEmpty(s)) return;
m_data = SaveSystem.Deserialize<Data>(s, m_data);
if (m_data == null)
{
m_data = new Data();
}
else
{
EnviroSkyMgr.instance.SetTimeOfDay(m_data.timeOfDay);
EnviroSkyMgr.instance.Time.Days = m_data.days;
EnviroSkyMgr.instance.Time.Years = m_data.years;
EnviroSkyMgr.instance.ChangeWeatherInstant(m_data.weather);

}
}

}
User avatar
Tony Li
Posts: 22131
Joined: Thu Jul 18, 2013 1:27 pm

Re: How To: Save Enviro - Sky and Weather

Post by Tony Li »

Thank you for sharing!

BTW, you can retain code formatting in your posts by wrapping it in code tags. Select the code text and click the </> button.
MeishinTale
Posts: 6
Joined: Tue Mar 23, 2021 9:37 am

Re: [HOWTO] How To: Save Enviro - Sky and Weather

Post by MeishinTale »

Hiho, thanks for this implementation !

Added temperature, snow and wetness in case weather was in transition during the save.
Changed Weather saving variable to a string since saving the entire WeatherPreset is heavier for no gain.
Also added a coroutine cf previous,

EnviroSaver.cs

Code: Select all

using System.Collections;
using UnityEngine;
using System;
using PixelCrushers;

public class EnviroSaver : Saver
{
    public bool LoadWetness = true, LoadSnow = true;
    public bool LoadSeasons = true, LoadWeather = true, LoadTemperature = true;

    [Serializable]
    public class Data
    {
        public float timeOfDay;
        public int days;
        public int years;
        public int season;
        public string weather;
        public float wetAmount;
        public float snowAmount;
        public float temp;
    }

    private Data m_data = new Data();

    public override string RecordData()
    {
        m_data.timeOfDay = EnviroSkyMgr.instance.GetTimeOfDay();
        m_data.days = EnviroSkyMgr.instance.Time.Days;
        m_data.years = EnviroSkyMgr.instance.Time.Years;

        m_data.weather = EnviroSky.instance.Weather.currentActiveWeatherPreset?.Name;
        m_data.season = (int)EnviroSky.instance.Seasons.currentSeasons;
        m_data.snowAmount = EnviroSky.instance.Weather.curSnowStrength;
        m_data.wetAmount = EnviroSky.instance.Weather.curWetness;
        m_data.temp = EnviroSky.instance.Weather.currentTemperature;

        return SaveSystem.Serialize(m_data);
    }

    public override void ApplyData(string s)
    {
        if (string.IsNullOrEmpty(s)) return;
        m_data = SaveSystem.Deserialize<Data>(s, m_data);
        if (m_data == null)
            m_data = new Data();
        else
            StartCoroutine(WaitAndLoad());
    }

    private IEnumerator WaitAndLoad()
    {
        // Wait for next frame
        yield return null;

        load();
    }

    private void load()
    {
        EnviroSkyMgr.instance.SetTimeOfDay(m_data.timeOfDay);
        EnviroSkyMgr.instance.Time.Days = m_data.days;
        EnviroSkyMgr.instance.Time.Years = m_data.years;
        // Weather
        if (LoadWeather) loadWeather();
        
        if (LoadSeasons) EnviroSkyMgr.instance.Seasons.currentSeasons = (EnviroSeasons.Seasons)m_data.season;
        
        if (LoadSnow) EnviroSkyMgr.instance.Weather.curSnowStrength = m_data.snowAmount;
        
        if (LoadWetness) EnviroSkyMgr.instance.Weather.curWetness = m_data.wetAmount;
        
        if (LoadTemperature) EnviroSkyMgr.instance.Weather.currentTemperature = m_data.temp;

    }

    private void loadWeather()
    {
        int index = EnviroSkyMgr.instance.Weather.weatherPresets.IndexWhere(x => x.Name == m_data.weather);
        if (index > -1)
            EnviroSkyMgr.instance.ChangeWeatherInstant(index);
        else
            Debug.LogError(string.Format("Weather {0} from saved is not in enviro presets' list", m_data.weather));
    }
}

User avatar
Tony Li
Posts: 22131
Joined: Thu Jul 18, 2013 1:27 pm

Re: [HOWTO] How To: Save Enviro - Sky and Weather

Post by Tony Li »

Thanks for sharing!
CruttMutt
Posts: 41
Joined: Wed May 06, 2020 9:44 am

Re: [HOWTO] How To: Save Enviro - Sky and Weather

Post by CruttMutt »

Thank you everyone here! You are all amazing :o <3
Post Reply