Як Color.Lerp між декількома кольорами?


12

Мені було важко знайти рішення для цього в документах Єдності.

Color.Lerp(Color a, Color b, float t) це функція, яка поступово змінює колір відповідно до кроку t, надаючи йому остаточне значення кольору b.

Як я перебуваю між різними кольорами один за одним?

Відповіді:


13

Нехай _colors - це масив кольорів, LENGHT - кількість кольорів у масиві, нехай t - значення поплавця 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); 

нарешті ви можете використовувати Lerp

Color.Lerp(oldColor, newColor, newT)

+1 - чудова відповідь - не вимагає ніяких циклічних чи спеціальних гілок і є загальним для N кольорів.
jpaver

Коли значення 1 потрапляє, колір буде самим останнім кольором у масиві?
G3tinmybelly

G3tinmybelly ти маєш рацію. T == 1 керується неправильно. Тож ми можемо додати раніше: якщо (t == 1) повернути Arr [N-1]
dnk drone.vs.drones

10

Один із підходів, який можна застосувати за допомогою декількох кольорових переходів, полягає у використанні градієнта .

Викриваючи загальнодоступну змінну цього типу, розробник використовує Інспектор, щоб запустити редактор градієнтів, щоб створити градієнт, що містить будь-яку кількість кольорів. Цей редактор дозволяє використовувати підбірники єдності кольорів, точну настройку клавіш кольорів / альфа та збереження / завантаження градієнтів.

введіть тут опис зображення

Після розробки Gradient.Evaluate()метод прийме поплавок у діапазоні 0-1, щоб повернути відповідний колір.

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

На жаль, API для програмного побудови градієнта не настільки елегантний .


1
ColorBands можна використовувати для тієї ж мети, але з більшою свободою над кольором
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;
        }
    }
}

Отже, це код, який я в кінцевому підсумку використовував для лерпування між трьома моїми кольорами, сподіваюсь, я буду корисним для всіх, хто вирішить це шукати.


0

Я відчуваю, що може бути краще рішення. Єдина причина, яку я бачив би, щоб переглядати колір від кольору, це якщо ви хотіли постійно змінювати відтінок ... http://en.wikipedia.org/wiki/Hue

Ось як конвертувати HSV у RGB: http://en.wikipedia.org/wiki/HSL_and_HSV#From_HSV

За допомогою цього ви можете використовувати кольори HSV, просто змінити відтінок, а потім перетворити на RGB. Крім того, з Color.Lerp у вас є проблема непослідовності. Якщо ви почнете від оранжевого до жовтого, то до зеленого, ви побачите, що колір дуже швидко починає переходити в жовтий, а потім починає сповільнюватися, коли наближається до жовтого, потім знову прискорюється, коли він переходить у жовтий та переходить у зелений. Таким чином, це повільно змінюватиме колір у кожній точці, про яку ви лерпуєте. Я думаю, що змінити відтінок було б набагато ефективніше - і в перспективі дасть кращий ефект. :)


0

Як ви пишете свою власну версію, яка використовує Color.Lerp()?

Дуже проста версія, яка має 3 кольори, а другий розміщується прямо посередині, може виглядати так:

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

Оскільки ви не сказали, на що хочете змінити колір, я наведу розпливчастий приклад із кольором, створеним методом.

Сенс у тому, щоб мати колекцію кольорів та загальну тривалість (як у прикладі, яку я надаю) або тривалість між кожним (це залежить від вас).

Я особисто не інтерполюю речі в оновленнях, про які я знаю, що не буду постійно інтерполювати (камера є винятком), тому для цього я використовую супроводи.

У цьому прикладі я поділяю тривалість, задану інспектором, на кількість кольорів, а потім я ліпрую фактичний колір ітератора на наступний колір ітератора, і тривалість буде тривалістю, яка раніше була спланована. Ось зразок:

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

Сподіваюся, це допомагає.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.