Dnešním ultimátním cílem bude postavit překážkovou dráhou s pohyblivými prvky.
Vytvořte si klasický scénář – kapsulový hráč s first-person kamerou na ploše. Vaše hierarchie hierarchie nechť vypadá následovně:
Podoba by poté měla být příbližně následující:
Hráče potřebujeme nyní rozhýbat – vytvoříme dva skripty:
PlayerMovement.cs
– ovládání hráče pomocí šipek nebo WASDCameraMovement.cs
– hýbání kamery pomocí pohybů myšiObsahy těchto souborů nebudou překvapivé – není to nic, co jsme tu dosud neviděli.
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
float Speed = 5f;
private void Update()
{
if (Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.W))
{
this.transform.position += Speed * Time.deltaTime * new Vector3(
Camera.main.transform.forward.x,
0,
Camera.main.transform.forward.z
);
}
if (Input.GetKey(KeyCode.DownArrow) || Input.GetKey(KeyCode.S))
{
this.transform.position -= Speed * Time.deltaTime * new Vector3(
Camera.main.transform.forward.x,
0,
Camera.main.transform.forward.z
);
}
if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A))
{
this.transform.position -= Speed * Time.deltaTime * new Vector3(
Camera.main.transform.right.x,
0,
Camera.main.transform.right.z
);
}
if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))
{
this.transform.position += Speed * Time.deltaTime * new Vector3(
Camera.main.transform.right.x,
0,
Camera.main.transform.right.z
);
}
}
}
Klikněte do bloku pro jeho zkopírování
using UnityEngine;
public class CameraMovement : MonoBehaviour
{
float Sensitivity = 10f;
void Update()
{
float dx = Input.GetAxis("Mouse X");
transform.eulerAngles += Vector3.up * dx * Sensitivity;
float dy = Input.GetAxis("Mouse Y");
transform.eulerAngles += Vector3.left * dy * Sensitivity;
}
}
Klikněte do bloku pro jeho zkopírování
Následně tyto dva skripty adekvátně přiřadíme našim objektům:
PlayerMovement.cs
– objektu PlayerCameraMovement.cs
– objektu Main CameraZkontrolujte si, že vám vše funguje – měli byste se moci pohybovat volně pomocí kláves WASD nebo šipek. Dopomůže vám kostka Target jakožto referenční bod.
Nyní vytvoříme samotnou překážkovou dráhu. Pro lehkou manipulovatelnost ji dáme do nového objektu. Přesuneme do ní též naší kostku Target. Dráhá by měla vypadat přibližně následovně:
Překážky budeme chtít dle všeho identické, použijeme proto Prefab. Ale z důvodů, který bude vyjasněn později budeme vyžadovat, aby měli všechny tyto překážky souřadnice [0,0,0]. Obalíme je tedy prázdným GameObjectem, kterému pak dáváme souřadnice, které chceme. Naše dráha bude prozatím koridor, v němž se naskýtají mezi hráčem a cílem čtyři identické překážky. Po tomto rozšíření může vypadat strutura následovně:
Hráči přidejte Rigidbody a nastavte mu v něm velké úhlové tření (Angular drag) a uzamkněte mu pohyb a rotaci v ose y. Postraním stěnám dejte také Rigidbody a naprosto uzamkněte jejich pozici a rotaci.
Nyní už nám chybí poslední krok před animacemi – potřebujeme překážky nastavit tak, aby při kolizi s hráčem byl hráč poslán zpět na start.
Přidejte proto hráči (tj. GameObjektu Player) Capsule collider. V prefabu překážek dejte
přímo kvádru ještě tag Obstacle a Box Collider. Následně vytvořte skript
PlayerCollisionHandler.cs
s následujícím obsahem:
using UnityEngine;
public class PlayerCollisionHandler : MonoBehaviour
{
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
}
public void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Obstacle"))
{
// posuň hráče do výchozí polohy
transform.position = new Vector3(START_X, START_Y, START_Z);
// vyresetuj jeho hybnost
rb.velocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
}
}
}
Klikněte do bloku pro jeho zkopírování
Tento skript jednoduše resetuje hráče na původní pozici, narazí-li do objektu s tagem Obstacle.
START_X, START_Y, START_Z
nastavte na původní pozici hráče ve vaší implementaci této
překážkové dráhy.
Zkontrolujte si, že hráč se může hýbat a narážet do stěn (nesmí jimi procházet). Zároveň se po kolizi s nimi náhodně neroztáčí. Také zkontrolujte, že narazíte-li do překážky, nikoliv do jedné ze stěn, tak jste resetováni zpátky na původní pozici
Zkontrolujte si, že hráč se může hýbat a narážet do stěn (nesmí jimi procházet). Zároveň se po kolizi s nimi náhodně neroztáčí. Také zkontrolujte, že narazíte-li do překážky, nikoliv do jedné ze stěn, tak jste resetováni zpátky na původní pozici
Vyberme nyní nejpřednější překážku (na samotný kvádr, nikoliv jeho obal) a otevřme editor animací z
{Window → Animation → Animation}
. Otevře se nám nové okno, v němž poklikáme Create.
Tím si v assetech vytvoříme novou animaci, pojmenujme ji napříkad ObstacleMovement.
popis UI + vysvětlení nutnosti wrapperů, keyframes, křivek, …
Pokud jsme již s animací spokojeni, odebereme ji z původního objektu, na kterém jsme ji testovali a přidáme ji do našeho prefabu. Jdeme tedy do editoru prefabu, přidáme komponent Animation a v tomto komponentě vybereme naší animaci ObstacleMovement. S prefaby se však chovají animace trochu specificki, musíme proto samotnou aplikaci ještě opravit, a to následovně. V okně s assety na ni poklikáme a v inspektoru se pomocí třech teček překlikneme do Debug mode. Zde nastavíme Wrap mode na Loop a zaškrtneme tlačítko Legacy mode.
Nyní by nám již hra měla fungovat!
Zkontrolujte si, zda vám hra funguje! Nejasnosti?