Jak Color.Lerp między wieloma kolorami?

12

Trudno mi znaleźć rozwiązanie tego problemu w dokumentach Unity.

Color.Lerp(Color a, Color b, float t) to funkcja, która stopniowo zmienia kolor zgodnie z krokiem t, nadając mu końcową wartość koloru b.

Jak mam Lerp między wieloma kolorami jeden po drugim?

Zee
źródło

Odpowiedzi:

13

Niech _colors będzie tablicą kolorów, niech LENGHT będzie liczbą kolorów w tablicy niech t będzie wartością zmiennoprzecinkową 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); 

wreszcie możesz użyć Lerp

Color.Lerp(oldColor, newColor, newT)
dnk drone.vs.drones
źródło
+1 - świetna odpowiedź - nie wymaga żadnych pętli ani specjalnych gałęzi i jest całkowicie ogólna dla N kolorów.
jpaver
Czy po uzyskaniu wartości 1 kolor będzie ostatnim kolorem w tablicy?
G3tinmybelly
G3tinmybelly masz rację. T == 1 nie jest poprawnie zarządzany. Możemy więc dodać wcześniej: if (t == 1) zwróć Arr [N-1]
dnk drone.vs.drones
10

Jednym z podejść, które można zastosować przy wielu przejściach kolorów, jest wykorzystanie gradientu .

Udostępniając publiczną zmienną tego typu, programista używa Inspektora do uruchomienia Edytora gradientów w celu zaprojektowania gradientu zawierającego dowolną liczbę kolorów. Ten edytor pozwala na korzystanie z selektorów kolorów jedności, dokładnego dostrojenia umiejscowienia klawiszy kolorów / alfa i zapisywania / ładowania gradientów.

wprowadź opis zdjęcia tutaj

Po zaprojektowaniu Gradient.Evaluate()metoda zaakceptuje liczbę zmiennoprzecinkową w zakresie 0-1, aby zwrócić odpowiedni kolor.

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

Niestety interfejs API do programowego budowania gradientu nie jest tak elegancki .

Kelly Thomas
źródło
1
ColorBands można wykorzystać do tego samego celu, ale z większą swobodą w kwestii koloru
SteakOverflow 24.08.16
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;
        }
    }
}

Więc to jest kod, którego ostatecznie użyłem do lerpu między trzema kolorami, mam nadzieję, że przyda się każdemu, kto zdecyduje się tego poszukać.

Zee
źródło
0

Wydaje mi się, że może być lepsze rozwiązanie. Jedynym powodem, dla którego chciałbym przejść od koloru do koloru jest to, że chcesz ciągle zmieniać odcień ... http://en.wikipedia.org/wiki/Hue

Oto jak przekonwertować HSV na RGB: http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV

Dzięki temu możesz używać kolorów HSV, po prostu zmienić odcień, a następnie przekonwertować na RGB. Poza tym z Color.Lerp masz problem z niespójnością. Jeśli zmienisz kolor z pomarańczowego na żółty, a następnie na zielony, przekonasz się, że kolor zaczyna bardzo szybko zmieniać kolor na żółty, a następnie zaczyna zwalniać, gdy zbliża się do żółtego, a następnie przyspiesza ponownie, gdy przechodzi w żółty i przechodzi w zielony. Spowolni więc zmianę koloru w każdym punkcie, do którego się dążysz. Myślę, że zmiana odcienia byłaby o wiele bardziej skuteczna - i na dłuższą metę da lepszy efekt. :)

Superdog
źródło
0

A może napiszesz własną wersję, która wykorzystuje Color.Lerp()?

Bardzo prosta wersja, która przyjmuje 3 kolory i umieszcza drugą pośrodku, mogłaby wyglądać następująco:

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 Piżama
źródło
0

Ponieważ nie powiedziałeś, na co chcesz zmienić kolor, podam niejasny przykład z kolorem stworzonym w metodzie.

Chodzi o to, aby mieć kolekcję kolorów i całkowity czas trwania (jak w przykładzie, który przedstawię) lub czas trwania między nimi (to zależy od ciebie).

Ja osobiście nie interpoluję rzeczy w aktualizacji , o których wiem, że nie będę ciągle interpolować (wyjątek stanowi kamera), więc używam do tego celu coroutines.

W tym przykładzie dzielę czas trwania podany na inspektorze przez liczbę kolorów, a następnie I Lerp rzeczywisty kolor iteratora do następnego koloru iteratora, a czas trwania będzie miał długość poprzednio połączoną. Oto próbka:

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

Mam nadzieję, że to pomoże.

LifGwaethrakindo
źródło