Függvények a matematikában és programozásban
A programozásban a függvényeket nem véletlenül hívjuk úgy, mint a megfelelő matematikai fogalmat. Szoros logikai kapcsolat van a kettő közt.
Egy függvény mindig egy megfelelő bemenet alapján generál egy kimenetet.
Ha a bemenet és a kimenet is egy szám (int /float), akkor 2D síkon ábrázolni tudjuk őket a következőképp:
Ezek az ábrák, jelennek meg legtöbbek fejében, mikor függvényekről beszélünk, de érdemes kiemelni, hogy ez csak egy vizualizáció, ami csak egy számot egy másik számmá alakító függvények esetén alkalmazható.
Ilyenekből eddig csak elég egyszerűeket tanultunk, mint például az abszolútérték vagy az előjel függvény. Ezeken kívül még sok egyéb is van belőlük a Mathf könyvtárban, de mi magunk is írhatunk újakat.
Programozott függvények használata és korlátai
Egy függvényt mindig arra, használunk, hogy egy vagy több ismert mennyiségből előállítsunk valami új mennyiséget, amit még nem ismerünk.
Például ha ismerjük két test pozícióját, de nem ismerjük ezek távolságát, akkor a Vector3.Distance() függvény használatával létrehozhatjuk az ismeretlen adatot.
Sok esetben viszont, a két mennyiség (kimenet, bemenet) közt túl speciális a kapcsolat, túlzottan a mi egyedi helyzetünkhöz szabott a probléma, ahhoz hogy bármi kész megoldás legyen rá.
Ekkor megírhatjuk a megfelelő függvényt mi magunk is, de sok esetben ez a megoldás sem ideális.
Pár példa ilyen problémákra:
- Egy ellenfél sebessége függ attól, milyen távol van a játékostól.
- A játékos ellenállása a sebzésnek függ attól, hogy legutóbb mikor sebeztek.
- Egy automata fegyver lövési sebessége függ attól, milyen fejlesztési szinten van.
- A játékos mozgási sebessége függ attól, mennyi az aktuális állóképessége (staminája).
Ezekre a típusú problémákra igaz, hogy:
- A kapcsolat a két mennyiség (kimenet, bemenet) közt gyakran bonyolult, nehezen írható le programkóddal.
- Még nem tudjuk előre, hogy pontosan mit is szeretnénk. Gyakori finomhangolást igényel a függvény beállítása akár játék közben is.
- A függvény beállítását nem egy programozó végzi, hanem egy kódoláshoz nem értő Game Designer.
Ekkor hívhatjuk segítségül az AnimationCurve-öket.
AnimationCurve
Az AnimationCurve lényegében egy editor felületről vizuálisan beállítható függvény, ami egy görbe alapján egy float mennyiségből egy másik float mennyiséget képez.
Nevével ellentmondó módon nem kell feltétlenül animációra használni. Szigorúan véve csak akkor lehet animációról beszélni, ha valamit az idő függvényében módosítunk. Ezzel szemben a fenti példákon láthattuk, hogy bármi egyéb mennyiségtől is függővé tudunk tenni akármit.
Vegyük például, hogy egy fényforrás világosságát tesszük függővé attól, hogy, milyen távol van egy tárgytól.
Ehhez felvehetünk egy AnimationCurve típusú [SerializeField] változót és beállíthatjuk a kapcsolatot.
A következő példánkban attól függ egy fénypont intenzitása, milyen távol van egy megadható céltól, mindez egy AnimationCurve-ön beállított görbe szerint.
[SerializeField] Light light;
[SerializeField] Transform target;
[SerializeField] AnimationCurve intensityOverDistance;
void Update()
{
float distance = Vector3.Distance(transform.position, target.position);
light.intensity = intensityOverDistance.Evaluate(distance);
}
Ez után a következőképp fog kinézni a komponens inspector felülete:
A megfelelő mezőre kattintva beállítható az animációs görbe.
Ehhez megjelenik egy dialógus ablak, amin tetszőleges számú kontrollpont segítségével felépíthető egy tetszőleges függvény:
Jelen esetben a fényintenzitás és távolság közti függvény. (Persze az, hogy mire használom fel az AnimationCurve-öt, az csak a kódtól függ.) A videon látszik az eredmény. A fehér fénypont világításának erőssége függ a piros kristálytól való távolságától a fenti görbe értékei szerint.
Értéket lekérni egy AnimationCurve-től az Evaluate metódussal lehet a fenti kód szerint. Ezzel a paraméterben kapott x koordinátához olvassuk le a megfelelő y értéket.
AnimationCurve szerkeztése
Egy AnimationCurve görbe kontoroll-pontokból áll, amik leírják az alakját.
Ha duplán kattintunk a görbén új kontroll pontot helyezhetünk le. Jobb gombbal férünk hozzá a menühöz, ahol törölni tudjuk azt. Ebben a menüben a ponthoz köthető minden beállítást elérünk.
Ha a ball egérgombbal megfogjuk a pontot mozgathatjuk, a legutóbb megfogott kontroll pont meredekségéhez is hozzáférünk.
A legelső és legutolsó görbeponton állíthatjuk be hogy ballra és jobbra miként folytatódjon a görbénk.
AnimationCurve-öket jellemzően finomhangolásra használunk fel. Különlegesen rugalmas eszköz, ezért nagy segítség ahhoz, hogy egy játék tényleg a lehető legpontosabban hasonlítson a tervezőinek elképzeléséhez.
A Gradiens típus
Egy gradiens színátmenetet jelent. Ez is egy beépített szerializálható típus a Unity-n belül.
[SerializeField] Gradient myGradient;
Ezt a gradienst be lehet állítani a Unity Editor Inspector felületén és az adat a szokásos módon mentésre kerül.
Az AnimationCurve-höz hasonlóan itt is lehetőség van tetszőleges számú kontrolpontot hozzáadni a skálához, ahol az egyes pontok színeket reprezentálnak. A kontrolpontok közti színeket lineáris interpolációval határozza meg a Unity.
Egy másik független része is van a gradiensnek, ami az opacitást (átlátszatlanságot / alfa csatornát) tartalmazza. A gradiens beállító ablakban ( lenti ábrán balra) a színátmenet alatt találhatók a szín kontrolpontok, felette pedig az opacitás kontrolpontok.
Ezután ebből a gradiensből lehet mintavételezni 0 és 1 között az Evalueate
metódussal, ahol a 0 a bal oldala a gradiensnek és az 1 a jobb oldala.
A metódus ezt a 0 és 1 közti értéket várja bemenetnek, a kimenete pedig egy Color típusú adat.
Color centerColor = myGradient.Evaluate(0.5f);