Come colorare: passare tra più colori?


12

Ho trovato piuttosto difficile trovare una soluzione a questo nei documenti di Unity.

Color.Lerp(Color a, Color b, float t) è una funzione che cambia gradualmente un colore secondo un passaggio t, dandogli il valore finale del Colore b.

Come faccio a scorrere tra più colori uno dopo l'altro?

Risposte:


13

Lascia che _colors sia una matrice di colori lascia che LENGHT sia il numero di colori nella matrice che t sia il valore float 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 puoi usare Lerp

Color.Lerp(oldColor, newColor, newT)

+1 - ottima risposta - non richiede alcun ciclo o rami speciali ed è completamente generale per N colori.
jpaver,

Quando viene colpito il valore 1, il colore sarà l'ultimo colore dell'array?
G3tinmybelly,

G3tinmybelly hai ragione. T == 1 non è gestito correttamente. Quindi possiamo aggiungere prima: if (t == 1) return Arr [N-1]
dnk drone.vs.drones

10

Un approccio che può essere adottato con più transizioni di colore è sfruttare un gradiente .

Esponendo una variabile pubblica di questo tipo uno sviluppatore usa l'ispettore per avviare l'Editor sfumature per progettare una sfumatura contenente un numero qualsiasi di colori. Questo editor ti consente di utilizzare i selettori di colore dell'unità, di mettere a punto il posizionamento dei tasti color / alpha e di salvare / caricare i gradienti.

inserisci qui la descrizione dell'immagine

Una volta progettato, il Gradient.Evaluate()metodo accetterà un float nell'intervallo 0-1 per restituire il colore appropriato.

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

Sfortunatamente l'API per la creazione programmatica di un gradiente non è così elegante .


1
Le bande colorate possono essere utilizzate per lo stesso obiettivo ma con maggiore libertà sul colore
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;
        }
    }
}

Quindi questo è il codice che ho finito per usare tra i miei tre colori, spero di essere utile a chiunque decida di cercarlo.


0

Sento che potrebbe esserci una soluzione migliore. L'unico motivo per cui vorrei passare da un colore all'altro è se volevi cambiare continuamente la tonalità ... http://it.wikipedia.org/wiki/Hue

Ecco come convertire HSV in RGB: http://it.wikipedia.org/wiki/HSL_and_HSV#From_HSV

Con questo puoi usare i colori HSV, cambiare semplicemente la tonalità, quindi convertire in RGB. Inoltre, con Color.Lerp, hai il problema dell'incoerenza. Se passi dall'arancione al giallo, quindi al verde, scoprirai che il colore inizia a diventare giallo molto rapidamente, quindi inizia a rallentare mentre si avvicina al giallo, quindi accelera nuovamente quando passa giallo e diventa verde. Quindi rallenterà il cambio di colore in ogni punto in cui ti stai muovendo. Penso che cambiare la tonalità sarebbe molto più efficace e, a lungo termine, darà un effetto migliore. :)


0

Che ne dici di scrivere la tua versione, che sfrutta Color.Lerp()?

Una versione molto semplice che prende 3 colori e mette la seconda proprio nel mezzo potrebbe apparire così:

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

0

Dato che non hai detto in cosa volevi cambiare colore, darò un vago esempio con un colore creato con il metodo.

Il punto è avere una collezione di colori e una durata totale (come nell'esempio che fornirò) o una durata tra ciascuno (dipende da te).

Personalmente non interpolo cose su Update che so che non interpolerò costantemente (la Camera è un'eccezione), quindi uso le coroutine per gestirlo.

In questo esempio divido la durata indicata su inspector per la quantità di colori e quindi Lerp il colore dell'iteratore effettivo al colore dell'iteratore successivo e la durata sarà della durata precedentemente combinata. Ecco l'esempio:

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.
    }
}

Spero che sia d'aiuto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.