Odpowiedzi:
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)
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.
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 .
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ć.
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. :)
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);
}
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.