简体   繁体   English

试图在RenderSettings.ambientskycolor之间束缚的Unity无法正常工作?

[英]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. 好的,我试图通过3种状态来控制,每种状态具有不同的环境光颜色。 One of the states needs to alpha lerp in the alpha of a different material. 其中一个州需要将另一种材料的Alpha约束。

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 : 这将比在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. 我不确定100%是否确实像您想要实现的那样,但是我的目标是向您展示如何使用协程而不是Update方法中的所有那些标志和检查。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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