Wie Color.Lerp zwischen mehreren Farben?


12

Ich fand es ziemlich schwierig, in den Unity-Dokumenten eine Lösung dafür zu finden.

Color.Lerp(Color a, Color b, float t) ist eine Funktion, die eine Farbe gemäß einem Schritt t allmählich ändert, um den endgültigen Wert der Farbe b zu erhalten.

Wie kann ich nacheinander zwischen mehreren Farben wechseln?

Antworten:


13

Sei _colors ein Array von Farben, sei LENGHT die Anzahl der Farben im Array, sei t der Gleitkommawert 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); 

Endlich können Sie Lerp verwenden

Color.Lerp(oldColor, newColor, newT)

+1 - großartige Antwort - erfordert keine Schleifen oder speziellen Verzweigungen und bezieht sich ganz allgemein auf N Farben.
Jpaver

Wenn der Wert 1 erreicht wird, ist die Farbe die allerletzte Farbe im Array?
G3tinmybelly

G3tinmybelly du hast recht. Das t == 1 wird nicht richtig verwaltet. Also können wir vorher hinzufügen: if (t == 1) return Arr [N-1]
dnk drone.vs.drones

10

Ein Ansatz, der mit mehreren Farbübergängen verwendet werden kann, ist die Verwendung eines Verlaufs .

Durch Offenlegen einer öffentlichen Variablen dieses Typs kann ein Entwickler im Inspektor den Verlaufseditor starten, um einen Verlauf mit einer beliebigen Anzahl von Farben zu entwerfen. In diesem Editor können Sie die Unity-Farbwähler verwenden, die Platzierung der Farb- / Alphatasten fein abstimmen und Farbverläufe speichern / laden.

Bildbeschreibung hier eingeben

Nach dem Gradient.Evaluate()Entwerfen akzeptiert die Methode einen Gleitkommawert im Bereich 0-1, um die entsprechende Farbe zurückzugeben.

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

Leider ist die API zum programmgesteuerten Erstellen eines Verlaufs nicht so elegant .


1
ColorBands können für das gleiche Ziel verwendet werden, aber mit mehr Freiheit über Farbe
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;
        }
    }
}

Das ist also der Code, mit dem ich zwischen meinen drei Farben hin- und herschlenderte. Ich hoffe, ich kann jedem von Nutzen sein, der sich dafür entscheidet, danach zu suchen.


0

Ich habe das Gefühl, dass es eine bessere Lösung geben könnte. Der einzige Grund, warum ich sehen würde, von Farbe zu Farbe zu wechseln, ist, wenn Sie den Farbton kontinuierlich ändern möchten ... http://en.wikipedia.org/wiki/Hue

So konvertieren Sie HSV in RGB: http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV

Hiermit können Sie HSV-Farben verwenden, einfach den Farbton ändern und dann in RGB konvertieren. Außerdem besteht bei Color.Lerp das Problem der Inkonsistenz. Wenn Sie von orange nach gelb und dann nach grün wechseln, werden Sie feststellen, dass die Farbe sehr schnell nach gelb wechselt und sich langsam verlangsamt, wenn sie sich gelb nähert. Sobald sie gelb übergeht und nach grün wechselt, wird sie wieder schneller. So verlangsamt sich der Farbwechsel an jedem Punkt, zu dem Sie lerpen. Ich denke, eine Änderung des Farbtons wäre viel effektiver - und würde auf lange Sicht eine bessere Wirkung erzielen. :)


0

Wie wäre es, wenn du deine eigene Version schreibst, die nutzt Color.Lerp()?

Eine sehr einfache Version, die drei Farben hat und die zweite genau in die Mitte legt, könnte so aussehen:

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

Da Sie nicht angegeben haben, in was Sie die Farbe ändern möchten, werde ich ein vages Beispiel mit einer nach dieser Methode erstellten Farbe geben.

Es geht darum, eine Sammlung der Farben und eine Gesamtdauer (wie in dem von mir angegebenen Beispiel) oder eine Dauer zwischen den einzelnen Farben zu haben (das liegt bei Ihnen).

Ich persönlich interpoliere keine Dinge auf Update , von denen ich weiß, dass ich nicht ständig interpoliere (Kamera ist eine Ausnahme), daher verwende ich Coroutinen, um das zu handhaben.

In diesem Beispiel dividiere ich die im Inspector angegebene Dauer durch die Anzahl der Farben, und dann lerpiere ich die tatsächliche Iteratorfarbe zur nächsten Iteratorfarbe, und die Dauer entspricht der zuvor gespleißten Dauer. Hier ist das Beispiel:

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

Ich hoffe es hilft.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.