Как Color.Lerp между несколькими цветами?


12

Мне было довольно сложно найти решение этой проблемы в документах Unity.

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

наконец, вы можете использовать Лерп

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
Цветные полосы можно использовать для той же цели, но с большей свободой над цветом
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.