简体   繁体   中英

Unity trying to lerp between RenderSettings.ambientskycolor not working?

Ok Im trying to lerp through 3 states where each has a different ambient light color. One of the states needs to alpha lerp in the alpha of a different material.

I have everything set up accordingly yet when I trigger the transition (using space), I dont get a smooth lerp but instead rapid flickering and then it eventually gets to the final color.

EDITED code (still not fully there):

  public Color[] skyColors = new Color[3];

    // added this just to see the result also in the inspector
    public Color currentAmbientcolor;

    public enum WeatherType
    {
        ClearSky,
        Clouds,
        RainStorm
    }
    public WeatherType currentWeather;

    // how long should lerping take
    // I find that easier to configure than using
    // speed - if you don't like it you can use timePassed += Tie.deltaTime * speed again
    public float LerpDuration = 1.0f;

    public Material rainMat;

    public bool isLerpingWeather;
    public bool isLerpingRain;

    // You can store those already in the beginning
    // makes it a bit better performance
    private Color rainFaidedOut;
    private Color rainFaidedIn;

    private void Awake()
    {
        rainFaidedOut = new Color(rainMat.color.r, rainMat.color.g, rainMat.color.b, 0);
        rainFaidedIn = new Color(rainMat.color.r, rainMat.color.g, rainMat.color.b, 1);

        StartCoroutine(GetWeather());
    }

    void SetWeather(string weatherval)
    {
        print("VAL: " + weatherval);
        if (weatherval.ToLower().Contains("cloud"))
        {
            currentWeather = WeatherType.Clouds;
        }
        else if (weatherval.ToLower().Contains("rain") || weatherval.ToLower().Contains("storm") || weatherval.ToLower().Contains("mist"))
        {
            currentWeather = WeatherType.RainStorm;
        }
        else
        {
            currentWeather = WeatherType.ClearSky;
        }

        //weather = WeatherType.ClearSky;
        UpdateWeather();

    }
    void UpdateWeather()
    {
        //check for change

        if (!isLerpingWeather)
        {
            if (currentWeather != WeatherType.RainStorm) rainMat.color = rainFaidedOut;

            switch (currentWeather)
            {
                case WeatherType.RainStorm:

                    RenderSettings.ambientSkyColor = skyColors[2];
                    break;

                case WeatherType.ClearSky:

                    RenderSettings.ambientSkyColor = skyColors[0];
                    break;

                case WeatherType.Clouds:

                    RenderSettings.ambientSkyColor = skyColors[1];
                    break;

                default:
                    break;
            }
        }

    }

    IEnumerator GetWeather()
    {


        //LA = [34.05, -118.24]
        //https://openweathermap.org/weather-conditions
        string url;

        WWW www = new WWW(url);
        yield return www;
        if (www.error == null)
        {

            var N = JSON.Parse(www.text);

            string weatherid = N["weather"][0]["description"];

            print(weatherid);
            SetWeather(weatherid);
        }
        else
        {
            Debug.Log("ERROR: " + www.error);

        }

    }

    private IEnumerator CycleWeather()
    {
        if (isLerpingWeather) yield break;

        isLerpingWeather = true;

        // get target color
        var currentIndex = (int)currentWeather;
        var newIndex = (currentIndex + 1) % skyColors.Length;
        var targetColor = skyColors[newIndex];
        currentWeather = (WeatherType)newIndex;

        // Here I just guessed you want that the rainMat is already
        // set to invisible when the weather has changed
        // except for RainStorm
        if (currentWeather != WeatherType.RainStorm) rainMat.color = rainFaidedOut;

        // get current color
        var currentColor = RenderSettings.ambientSkyColor;

        var timePassed = 0f;
        do
        {
            RenderSettings.ambientSkyColor = Color.Lerp(currentColor, targetColor, timePassed / LerpDuration);

            // added this just to see it in the inspector
            currentAmbientcolor = RenderSettings.ambientSkyColor;

            timePassed += Time.deltaTime;

            yield return null;
        } while (timePassed < LerpDuration);

        // just to be sure there is no over/under shooting set the target value in the end
        RenderSettings.ambientSkyColor = targetColor;

        // added this just to see it in the inspector
        currentAmbientcolor = RenderSettings.ambientSkyColor;

        isLerpingWeather = false;

        // after the currentWeather has changed start the LerpingRain routine
        // for the two cases where you want it
        // since you already have set the RenderSettings.ambientSkyColor = targetColor;
        // there is reason to do so every frame again
        if (currentWeather != WeatherType.RainStorm) StartCoroutine(LerpingRain());
    }

    private IEnumerator LerpingRain()
    {
        // skip if already lerping rain to avoid parallel routines
        if (isLerpingRain) yield break;
        // also skip if currently lerping wheather to avoid parallel routines
        if (isLerpingWeather) yield break;


        // set flag to be sure no other routine will be running
        isLerpingRain = true;

        var timePassed = 0f;
        do
        {
            rainMat.color = Color.Lerp(rainFaidedOut, rainFaidedIn, timePassed / LerpDuration);

            timePassed += Time.deltaTime;

            yield return null;
        } while (timePassed < LerpDuration);

        rainMat.color = rainFaidedIn;

        isLerpingRain = false;
    }

    // Now only used to get the input
    private void Update()
    {

        currentAmbientcolor = RenderSettings.ambientSkyColor;
        //UpdateWeather();
        // You want GetKeyDown here to execute this only once instead of every frame!
        if (Input.GetKey("space") && !isLerpingWeather)
        {
            print("changing weather");

            // Interrupt current routines
            StopAllCoroutines();
            StartCoroutine(CycleWeather());
        }
    }

Is there something Im missing?

I recommend to use a Coroutine instead. It would make it way easier to controll than doing everything in Update :

I had to invent your used data types and values a bit but I think it should come close to what you are using:

public class LerpExample : MonoBehaviour
{
    public Color[] skyColors = new Color[3];

    // added this just to see the result also in the inspector
    public Color currentAmbientcolor;

    public enum WeatherType
    {
        ClearSky,
        Clouds,
        RainStorm
    }
    public WeatherType currentWeather;

    // how long should lerping take
    // I find that easier to configure than using
    // speed - if you don't like it you can use timePassed += Tie.deltaTime * speed again
    public float LerpDuration = 1.0f;

    public Material rainMat;

    public bool isLerpingWeather;
    public bool isLerpingRain;

    // You can store those already in the beginning
    // makes it a bit better performance
    private Color rainFaidedOut;
    private Color rainFaidedIn;

    private void Awake()
    {
        rainFaidedOut = new Color(rainMat.color.r, rainMat.color.g, rainMat.color.b, 0);
        rainFaidedIn = new Color(rainMat.color.r, rainMat.color.g, rainMat.color.b, 1);
    }

    private IEnumerator CycleWeather()
    {
        if (isLerpingWeather) yield break;

        isLerpingWeather = true;

        // get target color
        var currentIndex = (int)currentWeather;
        var newIndex = (currentIndex + 1) % skyColors.Length;
        var targetColor = skyColors[newIndex];
        currentWeather = (WeatherType)newIndex;

        // Here I just guessed you want that the rainMat is already
        // set to invisible when the weather has changed
        // except for RainStorm
        if (currentWeather != WeatherType.RainStorm) rainMat.color = rainFaidedOut;

        // get current color
        var currentColor = RenderSettings.ambientSkyColor;

        var timePassed = 0f;
        do
        {
            RenderSettings.ambientSkyColor = Color.Lerp(currentColor, targetColor, timePassed / LerpDuration);

            // added this just to see it in the inspector
            currentAmbientcolor = RenderSettings.ambientSkyColor;

            timePassed += Time.deltaTime;

            yield return null;
        } while (timePassed < LerpDuration);

        // just to be sure there is no over/under shooting set the target value in the end
        RenderSettings.ambientSkyColor = targetColor;

        // added this just to see it in the inspector
        currentAmbientcolor = RenderSettings.ambientSkyColor;

        isLerpingWeather = false;

        // after the currentWeather has changed start the LerpingRain routine
        // for the two cases where you want it
        // since you already have set the RenderSettings.ambientSkyColor = targetColor;
        // there is reason to do so every frame again
        if (currentWeather != WeatherType.RainStorm) StartCoroutine(LerpingRain());
    }

    private IEnumerator LerpingRain()
    {
        // skip if already lerping rain to avoid parallel routines
        if (isLerpingRain) yield break;
        // also skip if currently lerping wheather to avoid parallel routines
        if (isLerpingWeather) yield break;


        // set flag to be sure no other routine will be running
        isLerpingRain = true;

        var timePassed = 0f;
        do
        {
            rainMat.color = Color.Lerp(rainFaidedOut, rainFaidedIn, timePassed / LerpDuration);

            timePassed += Time.deltaTime;

            yield return null;
        } while (timePassed < LerpDuration);

        rainMat.color = rainFaidedIn;

        isLerpingRain = false;
    }

    // Now only used to get the input
    private void Update()
    {
        // You want GetKeyDown here to execute this only once instead of every frame!
        if (Input.GetKey("space") && !isLerpingWeather)
        {
            print("changing weather");

            // Interrupt current routines
            StopAllCoroutines();
            StartCoroutine(CycleWeather());
        }
    }
}

The cube is for simulating the rain Material fade. The Sphere has a normal white material and is for visualizing the ambient color fade.

在此处输入图片说明

I'm not 100% sure if this behaves exactly like what you wanted to achieve but my goal was to show you how to use Coroutines instead of all those flags and checks inside the Update method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM