简体   繁体   中英

How can I simplify the script using the flags? and how can I make the fade in/out continue from the current point to the interrupted direction?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class FadingManager : MonoBehaviour
{
    public CanvasGroup canvasGroup;
    public float fadeTime = 5f;
    public bool fadeAutomatically = false;

    private YieldInstruction fadeInstruction = new YieldInstruction();
    private bool fadeIn = true;
    private bool fadeOut = false;

    private void Start()
    {

    }

    private void Update()
    {
        if (fadeAutomatically == false)
        {
            if (Input.GetKeyDown(KeyCode.O))
            {
                StartCoroutine(FadeOut(canvasGroup));
            }

            if (Input.GetKeyDown(KeyCode.I))
            {
                StartCoroutine(FadeIn(canvasGroup));
            }
        }

        if (fadeAutomatically)
        {
            if (fadeIn)
            {
                StartCoroutine(FadeIn(canvasGroup));

                fadeIn = false;
            }

            if (fadeOut)
            {
                StartCoroutine(FadeOut(canvasGroup));

                fadeOut = false;
            }
        }
    }

    IEnumerator FadeIn(CanvasGroup canvasGroup)
    {
        float elapsedTime = 0.0f;
        while (elapsedTime < fadeTime)
        {
            yield return fadeInstruction;
            elapsedTime += Time.deltaTime;
            canvasGroup.alpha = Mathf.Clamp01(elapsedTime / fadeTime);
        }

        fadeOut = true;
    }

    IEnumerator FadeOut(CanvasGroup canvasGroup)
    {
        float elapsedTime = 0.0f;
        while (elapsedTime < fadeTime)
        {
            yield return fadeInstruction;
            elapsedTime += Time.deltaTime;
            canvasGroup.alpha = 1.0f - Mathf.Clamp01(elapsedTime / fadeTime);
        }

        fadeIn = true;
    }
}

What is working so far :

The keys I and O are working when starting the game when pressing the keys it's fading in or out. The automatic fade-in out is working when the flag fadeAutomatically is true at the start.

What is not working and what should be simplified:

When running the game and pressing for example on the I key while it's fading IN if I press on the O key the fade OUT will interrupt the fade IN process same if pressing O and then I before the fading finish. I want somehow to make that if I pressed on the O key it's fading out and in the middle, I press the I key then from the current fading point it will change direction and will fade IN and if in the middle I press on O it will change direction and will fade out from the current fading point.

If I change the flag fadeAutomatically to true in the middle for example after pressed the I key to fade in and then in the middle I changed the flag to true it will not fade automatically like it is if the flag is true when starting the game. It will mess things.

To simplify the whole flags logic. It's working in general but I'm not sure if this is the way to use so many flags. but that's just to make the code looks better first I need to fix the problems.

Instead of having two routines basically doing the same convert it into a single one and just pass in different fading directions.

Than do eg

IEnumerator Fade(CanvasGroup canvasGroup, bool isIn, bool autoSwitch)
{
    // Store the current fading direction
    _currentDirection = isIn;

    // Determine start and end value depending on the fading direction
    var startValue = isIn ? 0 : 1;
    var targetValue = isIn ? 1 : 0;

    // Get the so far elapsed time according to the current alpha
    // It is the fadeTime multiplied by the already added or removed alpha
    var elapsedTime = fadeTime * (isIn ? canvasGroup.alpha : (1 - canvasGroup.alpha));
    while (elapsedTime <= fadeTime)
    {
        // Use Maths.Lerp to linear interpolate between the start and end value
        canvasGroup.alpha = Maths.Lerp(startValue, targetValue, elapsedTime / fadeTime);

        // For "skipping" one single frame you can simply return null
        yield return null;

        elapsedTime += Time.deltaTime;
    }

    // To be sure to end with clean values
    canvasGroup.alpha = targetValue;

    // Should we automatically switch the direction?
    if(autoSwitch) _nextDirection = !isIn;

    // Reset the current routine (see below)
    // Not sure if this is really necessary, I believe it will reset anyway 
    // as soon as the routine has finished .. but just to be sure
    _currentRoutine = null;
}

Then in Update you could do something like

// Stores the currently running routine to be able to stop/cancel it
private Coroutine _currentRoutine;
// Stores the current direction
private bool _currentDirection;
// Used for the automatic switch to determine the next direction
private bool _nextDirection;

private void StartFade(bool isIn, bool autoSwitch)
{
    // Another routine running already?
    if(_currentRoutine != null) 
    {
        // Different direction?
        if(_currentDirection != isIn)
        {
            // Interrupt the current routine
            StopCoroutine (_currentRoutine);

            // And start a new one
            _currentRoutine = StartCoroutine (Fade(canvasGroup, isIn, autoSwitch));
        }
    }
    else
    {
        // Otherwise directly start the first routine
        _currentRoutine = StartCoroutine (Fade(canvasGroup, isIn, autoSwitch));
    }
}

private void Update()
{
    if (!fadeAutomatically)
    {
        if (Input.GetKeyDown(KeyCode.O))
        {
            StartFade(false);
        }

        if (Input.GetKeyDown(KeyCode.I))
        {
            StartFade(true);
        }
    }
    else // fadeAutomatically
    {
        StartFade (_nextDirection);
    }
}

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