Objektum mozgatás Unity-ben
Nem lenne játék a játék mozgó objektumok nélkül. Azt hihetnénk, hogy ez egy nagyon egyszerű dolog: csak arrébb kell tenni az adott objektumot minden képkockában. A gyakorlat egy kicsit más, több mozgatási módszer is létezik. Ez a leírás minimális programozási ismereteket feltételez, de a kezdők is el fognak tudni igazodni a szkriptekben.
Az alapok
Van egy objektumunk és egy 2D-s felületen, az X tengelyen szeretnénk jobbra/balra mozogni a nyíl gombokkal:
using UnityEngine; public class PlayerController : MonoBehaviour { Rigidbody rb; public float speed = 10.0f; void Start () { rb = GetComponent(); } void Update () { if (Input.GetKey(KeyCode.RightArrow)) { rb.velocity = transform.right * speed; } } }
Így mozog, ha megnyomjuk a jobbra nyilat:
Valami nincs rendben! Ha jobbra akarunk menni, miért indul el balra egy idő után a golyó? Ennek az az oka, hogy a golyó vektorai együtt forognak az objektummal. Egy idő után a golyó átfordul, és a jobbra irányszámunkra máris balt jelent.
Rögzíthetjük a golyót, hogy ne forogjon, ha befagyasztjuk a forgását:
rb.freezeRotation = true;
Miután a sebességet 2.0f-re változtattuk, és a fenti sort hozzáadtuk, ilyesmi eredményt kapunk:
Ez már jobban néz ki, de még mindig javíthatunk rajta.
Balra is szeretnénk menni, ehhez kicsit módosítani kell a kódon:
using UnityEngine; public class PlayerController : MonoBehaviour { Rigidbody rb; public float speed = 2.0f; void Start () { rb = GetComponent(); rb.freezeRotation = true; } void Update () { if (Input.GetKey(KeyCode.RightArrow)) { rb.velocity = transform.right * speed; } if (Input.GetKey(KeyCode.LeftArrow)) { rb.velocity = -transform.right * speed; } } }
Mivel nincs transform.left funkció, ezért a transform.right funckiót kell tükrözni, azzal hogy elé teszünk egy mínusz jelet.
A módosítások után már tudunk jobbra és balra is mozogni a golyóval. Amennyiben további dimenziókat szeretnénk hozzáadni a mozgáshoz, akkor a Z tengelyen történő elmozdulást kell kezelnünk, hogy a talaj mentén tudjunk közlekedni.
Az előre történő mozgáshoz a következő sort kell használnunk:
rb.velocity = new Vector3(0, 0, 1) * speed;
Ez azt eredményezi, mint a fenti példa, de egy 3D-s vektort hív ehhez segítségül.
A teljes kód:
using UnityEngine; public class PlayerController : MonoBehaviour { Rigidbody rb; public float speed = 2.0f; void Start () { rb = GetComponent(); rb.freezeRotation = true; } void Update () { if (Input.GetKey(KeyCode.RightArrow)) { rb.velocity = transform.right * speed; } if (Input.GetKey(KeyCode.LeftArrow)) { rb.velocity = -transform.right * speed; } if (Input.GetKey(KeyCode.UpArrow)) { rb.velocity = new Vector3(0, 0, 1) * speed; } if (Input.GetKey(KeyCode.DownArrow)) { rb.velocity = new Vector3(0, 0, -1) * speed; } } }
A második módszer
Létezik alternatív megoldás is arra, hogy a golyót mozgassuk. Eddig a transform funkciókat használtuk, ami nem ad túl realisztikus mozgást. Az Input.GetAxis() használatával lehetőségünk van realisztikusabban mozgtani az objektumokat, mivel a nyers, “tedd odébb” parancsok helyett fizikai erővel hatunk az objektumokra, így idézve elő a mozgást.
using UnityEngine; public class PlayerController : MonoBehaviour { Rigidbody rb; public float speed = 2.0f; void Start () { rb = GetComponent(); } void Update () { float moveHorizontal = Input.GetAxis("Horizontal"); float moveVertical = Input.GetAxis("Vertical"); rb.AddForce(new Vector3(moveHorizontal, 0.0f, moveVertical) * speed); } }
A mozgatás RigidBody alapú, így ha módosítjuk a tömeget, a súrlódást, az hatással lesz a mozgatási képességre is.
A harmadik módszer
Egy másik lehetőség, hogy sebességet adunk a golyónak a fel/le nyilakkal, és forgatjuk a balra/jobbra nyilakkal:
using UnityEngine; public class PlayerController : MonoBehaviour { public float movementSpeed = 5.0f; public float rotationSpeed = 200.0f; void Update () { transform.Rotate(0, Input.GetAxis("Horizontal") * Time.deltaTime * rotationSpeed, 0); transform.Translate(0, 0, Input.GetAxis("Vertical") * Time.deltaTime * movementSpeed); } }
Két lehetséges megoldást kombináltunk, így kaptuk meg a harmadikat. A transform funciókat és a GetAxis()-t használtuk, amely kiszámíthatóbb mozgást tesz lehetővé, ezért ez jól használható például versenyzős játékok esetében.
A Unity-nek van egy beépített karaktervezérlője is, erre is érdemes egy pillantást vetnünk:
A kód, amellyel WASD gombokkal tudunk mozogni:
using UnityEngine; public class PlayerController : MonoBehaviour { CharacterController characterController; public float movementSpeed = 5.0f; private Vector3 moveDirection = Vector3.zero; void Start() { characterController = GetComponent(); } void Update () { if (characterController.isGrounded) { moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("Vertical")); moveDirection = moveDirection * movementSpeed; } //Gravity moveDirection.y -= 10f * Time.deltaTime; characterController.Move(moveDirection * Time.deltaTime); } }
Ebben a megoldásban nem használjuk a RigidBody-t, így a gravitációt magunknak kell megírnunk.
Összegzés
A helyzettől függ, hogy melyik megoldást érdemes alkalmaznunk. Olyan esetben, amikor valaminek X idő alatt pontosan Y távolságot kell megtennie, kerüljük a fizikai erőkkel történő mozgatást, és inkább a transform paraméterek módosításával mozgassunk. A realisztikusabb mozgáshoz, amelyben a fizikát is alkalmazni akarjuk, az AddForce funcióval érdemes dolgoznunk.
Természetesen ezek nem kőbe vésett szabályok, lehetnek egy játékban olyan események is, amikor az AddForce alapú mozgatás a normál, míg bizonyos eseményeknél a velocity-vel kell operálni.
Forrás: Noob Programmer
Skeldar
Hagyjon egy választ
Want to join the discussion?Feel free to contribute!