Como Color.Lerp entre várias cores?

12

Achei bastante difícil encontrar uma solução para isso nos documentos do Unity.

Color.Lerp(Color a, Color b, float t) é uma função que muda gradualmente uma cor de acordo com a etapa t, fornecendo o valor final da cor b.

Como faço para ler entre várias cores, uma após a outra?

Zee
fonte

Respostas:

13

Seja _colors uma matriz de cores, LENGHT seja o número de cores na matriz, seja t o valor flutuante 0..1

float scaledTime = t * (float) (LENGHT - 1);
Color oldColor = _colors[(int) scaledTime];
Color newColor = _colors[(int) (scaledTime + 1f)];
float newT = scaledTime - Mathf.Round(scaledTime); 

finalmente você pode usar o Lerp

Color.Lerp(oldColor, newColor, newT)
dnk drone.vs.drones
fonte
+1 - ótima resposta - não requer nenhum loop ou ramificações especiais e é completamente geral para N cores.
jpaver
Quando o valor 1 for atingido, a cor será a última cor na matriz?
G3tinmybelly
G3tinmybelly você está certo. O t == 1 não é gerenciado corretamente. Portanto, podemos adicionar antes: if (t == 1) retornar Arr [N-1]
dnk drone.vs.drones
10

Uma abordagem que pode ser adotada com várias transições de cores é alavancar um gradiente .

Ao expor uma variável pública desse tipo, um desenvolvedor pode usar o Inspector para iniciar o Editor de gradiente para criar um gradiente que contenha qualquer número de cores. Este editor permite usar os seletores de cores de unidade, ajustar o posicionamento das teclas de cores / alfa e salvar / carregar gradientes.

insira a descrição da imagem aqui

Uma vez projetado, o Gradient.Evaluate()método aceitará um flutuador no intervalo de 0 a 1 para retornar a cor apropriada.

using UnityEngine;

public class GradientTest : MonoBehaviour
{
    public Gradient myGradient;
    public float strobeDuration = 2f;

    public void Update() {
        float t = Mathf.PingPong(Time.time / strobeDuration, 1f);
        Camera.main.backgroundColor = myGradient.Evaluate(t);
    }
}

Infelizmente, a API para criar programaticamente um gradiente não é tão elegante .

Kelly Thomas
fonte
1
ColorBands pode ser usado para o mesmo objetivo, mas com mais liberdade sobre a cor
SteakOverflow
1
public float every;   //The public variable "every" refers to "Lerp the color every X"
float colorstep;
Color[] colors = new Color[4]; //Insert how many colors you want to lerp between here, hard coded to 4
int i;
Color lerpedColor = Color.red;  //This should optimally be the color you are going to begin with

void Start () {

    //In here, set the array colors you are going to use, optimally, repeat the first color in the end to keep transitions smooth

    colors [0] = Color.red;
    colors [1] = Color.yellow;    
    colors [2] = Color.cyan;
    colors [3] = Color.red;

}


// Update is called once per frame
void Update () {

    if (colorstep < every) { //As long as the step is less than "every"
        lerpedColor = Color.Lerp (colors[i], colors[i+1], colorstep);
        this.GetComponent<Camera> ().backgroundColor = lerpedColor;
        colorstep +=0.025f;  //The lower this is, the smoother the transition, set it yourself
    } else { //Once the step equals the time we want to wait for the color, increment to lerp to the next color

        colorstep = 0;

        if (i < (colors.Length - 2)){ //Keep incrementing until i + 1 equals the Lengh
        i++;
        }
        else { //and then reset to zero
            i=0;
        }
    }
}

Portanto, este é o código que acabei usando para lerp entre três cores minhas, espero que seja útil para quem decidir procurar por isso.

Zee
fonte
0

Sinto que pode haver uma solução melhor. A única razão pela qual eu veria ler de cor em cor é se você estava querendo mudar continuamente o matiz ... http://en.wikipedia.org/wiki/Hue

Veja como converter HSV para RGB: http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV

Com isso, você pode usar cores HSV, basta alterar a tonalidade e converter para RGB. Além disso, com o Color.Lerp, você tem o problema de inconsistência. Se você ler de laranja para amarelo e depois para verde, verá que a cor começa a amarelar muito rapidamente, depois começa a desacelerar à medida que se aproxima do amarelo e depois acelera novamente quando passa amarelo e fica verde. Assim, a cor mudará lentamente em todos os pontos em que você está lendo. Eu acho que mudar o tom seria muito mais eficaz - e, a longo prazo, dará um efeito melhor. :)

Superdoggy
fonte
0

Que tal você escrever sua própria versão, que aproveita Color.Lerp()?

Uma versão muito simples, que pega 3 cores e coloca a segunda no meio, pode ficar assim:

Color Lerp3(Color a, Color b, Color c, float t)
{
    if (t < 0.5f) // 0.0 to 0.5 goes to a -> b
        return Color.Lerp(a, b, t / 0.5f);
    else // 0.5 to 1.0 goes to b -> c
        return Color.Lerp(b, c, (t - 0.5f) / 0.5f);
}
Panda Pajama
fonte
0

Como você não disse para o que queria mudar de cor, darei um exemplo vago com uma cor criada no método.

O ponto é ter uma coleção das cores e uma duração total (como no exemplo que fornecerei) ou uma duração entre cada uma (isso é com você).

Pessoalmente, não interpolo as coisas no Update que sei que não interpolarei constantemente (a câmera é uma exceção); portanto, uso corotinas para lidar com isso.

Neste exemplo, divido a duração fornecida no inspetor pela quantidade de cores e, em seguida, escrevo a cor real do iterador para a próxima cor do iterador, e a duração será a duração emendada anteriormente. Aqui está a amostra:

public class ColorLerping : MonoBehaviour
{
    public Color sampleColor; /// Just for debugging purposes.
    public float lerpDuration;
    public Color[] colors;

    void Awake()
    {
        StartCoroutine(LerpColors());
    }

    private IEnumerator LerpColors()
    {
        if(colors.Length > 0)
        {
            /// Split the time between the color quantities.
            float dividedDuration = lerpDuration / colors.Lenght;

            for(int i = 0; i < colors.Length - 1; i++)
            {
                float t = 0.0f;

                while(t < (1.0f + Mathf.Epsilon))
                {
                    sampleColor = Color.Lerp(colors[i], colors[i + 1], t);
                    t += Time.deltaTime / dividedDuration;
                    yield return null;
                }

                // Since it is posible that t does not reach 1.0, force it at the end.
                sampleColor = Color.Lerp(colors[i], colors[i + 1], 1.0f);
            }

        }
        else yield return null; /// Do nothing if there are no colors.
    }
}

Espero que ajude.

LifGwaethrakindo
fonte