¿Cómo colorear el color entre varios colores?

12

Me ha resultado bastante difícil encontrar una solución a esto en los documentos de Unity.

Color.Lerp(Color a, Color b, float t) es una función que cambia gradualmente un color de acuerdo con un paso t, dándole el valor final del Color b.

¿Cómo cambio entre varios colores uno tras otro?

Zee
fuente

Respuestas:

13

Deje que _colors sea ​​una matriz de colores, deje que LONGITUD sea ​​el número de colores en la matriz, t sea ​​el valor flotante 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 puedes usar Lerp

Color.Lerp(oldColor, newColor, newT)
dnk drone.vs.drones
fuente
+1 - gran respuesta - no requiere ningún bucle o ramas especiales, y es completamente general para N colores.
jpaver
Cuando se alcanza el valor 1, ¿será el color el último color de la matriz?
G3tinmybelly
G3tinmybelly tienes razón. El t == 1 no se gestiona correctamente. Por lo tanto, podemos agregar antes: if (t == 1) return Arr [N-1]
dnk drone.vs.drones
10

Un enfoque que se puede tomar con múltiples transiciones de color es aprovechar un degradado .

Al exponer una variable pública de este tipo, un desarrollador puede usar el Inspector para iniciar el Editor de degradado para diseñar un degradado que contenga cualquier cantidad de colores. Este editor le permite utilizar los selectores de color de la unidad, la colocación de las teclas de color / alfa y los gradientes de guardar / cargar.

ingrese la descripción de la imagen aquí

Una vez diseñado, el Gradient.Evaluate()método aceptará un flotador en el rango de 0-1 para devolver el color apropiado.

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);
    }
}

Desafortunadamente, la API para construir un gradiente mediante programación no es tan elegante .

Kelly Thomas
fuente
1
ColorBands se puede usar para el mismo objetivo pero con más libertad sobre el color
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;
        }
    }
}

Así que este es el código que terminé usando para saltar entre tres colores míos, espero que sea útil para cualquiera que decida buscar esto.

Zee
fuente
0

Siento que puede haber una mejor solución. La única razón por la que vería pasar de un color a otro es si quisieras cambiar continuamente el tono ... http://en.wikipedia.org/wiki/Hue

Aquí se explica cómo convertir HSV a RGB: http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV

Con esto puede usar colores HSV, simplemente cambie el tono y luego convierta a RGB. Además, con Color.Lerp, tienes el problema de la inconsistencia. Si pasas de naranja a amarillo, luego a verde, verás que el color comienza a ir a amarillo muy rápidamente, luego comienza a disminuir a medida que se acerca al amarillo, luego se acelera nuevamente una vez que pasa el amarillo y pasa al verde. Por lo tanto, ralentizará el cambio de color en cada punto al que esté yendo. Creo que cambiar el tono sería mucho más efectivo y, a la larga, dará un mejor efecto. :)

Superperrito
fuente
0

¿Qué tal si escribes tu propia versión, que aprovecha Color.Lerp()?

Una versión muy simple que toma 3 colores y coloca el segundo en el medio podría verse así:

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);
}
Pijama Panda
fuente
0

Como no dijiste a qué querías cambiar el color, daré un ejemplo vago con un color creado en el método.

El punto es tener una colección de colores y una duración total (como en el ejemplo que proporcionaré) o una duración entre cada uno (depende de usted).

Personalmente, no interpolo cosas en la actualización que sé que no voy a interpolar constantemente (la cámara es una excepción), por lo que uso corutinas para manejar eso.

En este ejemplo, divido la duración dada en el inspector por la cantidad de colores, y luego cambio el color real del iterador al siguiente color del iterador, y la duración será de la duración previamente empalmada. Aquí está la muestra:

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 eso ayude.

LifGwaethrakindo
fuente