A lineáris interpoláció egy alapvető eszköz, a játékfejlesztő programozói szerszámosládánkban.
Működése és használata nagyon egyszerű bármilyen elrettentő is a neve.
Feladata, hogy kettő adatot vegyítsen egy arányszám szerint.
A lineáris interpoláció rövidítésére a Lerp szót használjuk.
Color.Lerp
Ezt legegyszerűbben úgy lehet elképzelni, mintha kétféle festéket kevernénk össze, megadva azt, hogy milyen arányban használunk melyikből.
Például ha piros és kék színt keverünk 0.8-as arányban. Az azt jelenti, hogy
pirosból veszünk 0.2 részt,
kékből veszünk 0.8 részt.
Ezt meg is tudjuk tenni Unity-ben is a Color.Lerp
függvénnyel.
[SerializeField] Color colorA, colorB;
[SerializeField, Range(-1,2)] float t = 1f;
[SerializeField] Material material;
void Update()
{
material.color = Color.Lerp(colorA, colorB, t);
}
A lerp függvényeknek mindig 3 bemenetük és egy kimentük van:
A visszatérés (kiment) típusa mindig megegyezik az első két paraméter (bemenet) típusával.
A harmadik t nevű paraméter mindig egy float típusú szám, ami megadja milyen arányban keverjük az első 2 paramétert.
Unity Lerp függvények
Többféle típus objektumai közt tudunk lineárisan interpolálni.
Lásd a következő interaktív példát, ahol a és b (Vector2 típusú) pontok közt lehet lineárisan interpolálni:
Ezen kívül a Unity-ben tudsz még interpolálni float számok, Vector3
-ak és Quaternion
-ok közt is:
float fResult = Mathf.Lerp(fa, fb, t);
Color cResult = Color.Lerp(ca, cb, t);
Vector2 v2Result = Vector2.Lerp(v2a, v2b, t);
Vector3 v3Result = Vector3.Lerp(v2a, v2b, t);
Quaternion qResult = Quaternion.Lerp(qa, qb, t);
LerpUnclamped
Megfigyelheted, hogy nem csak akkor kapod vissza az első (a) értéket, ha 0-t adsz t-nek, de akkor is, ha bármi nulla alatti értéket. Ugyanígy 1 és minden efeletti t a második (b) értéket adja vissza.
Példa: Lineáris interpoláció számok közt: Mathf.Lerp
Ha azt a levágást nem szeretnénk, hanem, hogy folytatódjon a függvény a 0 és 1 értéken kívül is akkor a LerpUnclamped
függvényt használjuk. Minden eddig bemutatott Lerp
függvénynek LerpUnclamped
megfelelője:
float fResult = Mathf.LerpUnclamped(fa, fb, t);
Color cResult = Color.LerpUnclamped(ca, cb, t);
Vector2 v2Result = Vector2.LerpUnclamped(v2a, v2b, t);
Vector3 v3Result = Vector3.LerpUnclamped(v2a, v2b, t);
Quaternion qResult = Quaternion.LerpUnclamped(qa, qb, t);
InverseLerp
Ha nem az 0-val szeretnénk jelölni a kezdőpontot és nem a 1-gyel a végpontot, akkor használhatjuk az Lineáris interpoláció inverse függvényét, hogy vele kiszámoljuk a Lert t paraméterét.
t = Mathf.InverseLerp(aInput, bInput, inputValue);
Color resultColor = Color.Lerp(aColorOutput, bColorOutput, t);
Simított (nem lineáris) interpoláció
Az interpoláció tehát csak annyit jelent, hogy átmenetet képzünk egyik adatból a másikba.
Lerp esetén az átmenet mindig tökéletesen egyenletes lesz innen a “lineáris” szó. Ennek megvan az a hátránya, hogy elég szögletessé tudja tenni az átmenetet. Ez gyakran nem probléma, sőt kifejezetten elvárt, ám megoldandó feladattól függően előfordulhat, hogy nem egyenletes, ámde a végeken simább átmenetet szeretnénk elérni. Szerencsére nem csak lineárisan lehet interpolálni.
A Unity Mathf.SmoothLerp függvénye segít elsimítani a görbe kezdeti és végpontját.
SmoothLerp függvény csak számokra létezik, hogyha egyéb adattípusokkal akarjuk használni, akkor kombinálni kell azok Lerp függvényével a következőképp:
lerpObj.position = Vector3.Lerp(p1, p2, t);
float t2 = Mathf.SmoothStep(0, 1, t);
smoothObj.position = Vector3.Lerp(p3, p4, t2);
Körkörös interpoláció
Ha szögek közt szeretnénk lineárisan interpolálni, akkor ne a Mathf.Lerp
-et használjuk, hanem a Mathf.LerpAngle
függvényt. Ekkor a legrövidebb utat fogja megtalálni az adott szöghöz még akkor is ha ehhez visszafelé kell haladni.
3D-s elforgatásokat reprezentálhatunk euler szögekkel Vector3
és Quaternion
-nal is (Forgatás), ezért mindkét osztály tartalmaz gömbön értelmezett “Spehrical” Lerp-et, vagyis Slerp-et, ami egyenletesen szögsebességgel forgat egyik rotációból a másikba.
A Quaternion-nak van Lerp
és Slerp
függvénye is, a különbséget az alábbi ábra érzékelteti: