• Rezultati Niso Bili Najdeni

Korutine v skripti PlayerMovement.cs

4.4 Premikanje v tretji osebi in animacije

4.4.4 Korutine v skripti PlayerMovement.cs

Slika 26: Prikaz kapsule za testiranje in CapsuleCollider.

4.4.4 Korutine v skripti PlayerMovement.cs

V skripti definiramo več korutin, s katerimi skušamo program nekoliko optimizirati. Običajna koda se izvede od začetka do konca in ob vsaki sličici vrne končne rezultate. To pomeni, da se koda za vsako sličico izvede v celoti, od prve do zadnje vrstice danega bloka. Če želimo, da se koda izvede do določene vrstice, vrne neko vrednost in nato čaka do naslednje sličice, nam pridejo prav korutine. Te nam omogočajo tudi čakanje (npr. počakaj 1 sekundo, nato nadaljuj izvajanje).

Korutine definiramo s pomočjo IEnumerator vmesnika "IEnumerator ImeKorutine()". Zaradi konsistentnosti so v skripti vse korutine poimenovane po ključu "EnImeKorutine", pri čemer "En"

označuje besedo enumerator. Na ta način hitreje najdemo želeno korutiono, saj jih vklapljamo in izklapljamo s klicem njihovega imena.

Slika 27 prikazuje korutino "EnGroundCheck()", ki jo uporabljamo za preverjanje stika glavnega lika s tlemi. V korutini s pogojnim stavkom preverjamo logično vrednost spremenljivke

"isGrounded". Dokler se lik dotika tal, je pogoj "while" zanke resničen, kar pomeni, da se koda v bloku periodično izvaja. Znotraj bloka se izvede metoda "CapsuleCheck()", s katero preverimo, ali se lik še vedno dotika tal, nato pa korutina izvede ukaz "yield". Ta izstopi iz korutine in vklopi premor za desetinko sekunde. Če pogoj "while" stavka ne drži, se vklopi korutina z imenom

"EnLandingCheck", trenutno izvajajoča korutina pa doseže svoj konec, zato se prekine.

28

IEnumerator EnGroundCheck() {

while (isGrounded) {

CapsuleCheck();

yield return new WaitForSeconds(.1f);

}

StartCoroutine("EnLandingCheck");

}

Slika 27: Korutina EnGroundCheck().

Slika 28 prikazuje korutino "EnLandingCheck()", s katero preverjamo pristanek igralca potem, ko je zapustil tla. Korutino vklopimo v primeru, ko igralec pritisne tipko za skok ali v primeru, ko skripta zazna, da lik ne stoji več na tleh (isGrounded == false).

V telesu korutine je "while" zanka, ki se izvaja, dokler se igralec dotika tal. V bloku zanke se izvede metoda "CapsuleCheck()", nato pa korutina doseže "yield", ki ne vrne ničesar (return null).

V trenutku, ko pogoj prve zanke ni izpolnjen, se v animatorju kontrolna spremenljivka za "Jump"

nastavi na "false", tista, ki kontrolira animacijo "MidAir" pa na "true" (igralec je v zraku, zato se vključi animacija "MidAir"). Po tem korutina izvede naslednjo zanko, ki preverja, ali je glavni lik še vedno v zraku. Znotraj zanke se zopet izvede metoda "CapsuleCheck()", nato izstopi, ne da bi vrnila vrednost (return null).

Takoj, ko je vrednost spremenljivke "isGrounded" enaka "true", se v animatorju kontrolna spremenljivka animacije "MidAir" nastavi na "false", tista, ki kontrolira "Landing", pa na "true".

Posledično se izključi animacija "MidAir" in vključi animacija "Landing". Na tej točki korutina zopet izstopi, ne da bi vrnila vrednost (počaka na naslednji okvir, saj mora nova animacija pričeti z izvajanjem)

Zadnja zanka preverja, ali se trenutna animacija ("Landing") še vedno izvaja. Pogoj pokliče metodo animatorja, ki vrne informacijo o izvajanju trenutnega stanja na plasti nič (naš Animator Controller ima samo eno plast), ime stanja pa mora biti enako "Landing". Za vsak okvir, ko se animacija še ne izvede do konca, korutina izstopi, ne da bi vrnila vrednost.

Takoj, ko se animacija pristanka izvede do konca, korutina nastavi vrednost spremenljivke

"isJumping" na "false". Nato se v animatorju kontrolna spremenljivka za animacijo "Landing"

nastavi na "false", na koncu pa se vklopi še korutina "EnGroundCheck", ki prične s ponovnim preverjanjem dotikanja tal.

29

IEnumerator EnLandingCheck() {

while (isGrounded) {

CapsuleCheck();

yield return null;

}

animator.SetBool("Jump", false);

animator.SetBool("MidAir", true);

while (!isGrounded) {

CapsuleCheck();

yield return null;

}

animator.SetBool("MidAir", false);

animator.SetBool("Landing", true);

yield return null;

while (animator.GetCurrentAnimatorStateInfo(0).IsName("Landing")) {

yield return null;

}

isJumping = false;

animator.SetBool("Landing", false);

StartCoroutine("EnGroundCheck");

}

Slika 28: Korutina EnLandingCheck().

Slika 29 prikazuje korutini "EnRun()" ter "EnRunBack()". V prvi korutini znotraj zanke preverjamo, ali igralec še vedno drži tipko za vertikalno premikanje. Ko igralec tipko spusti, se vrednost kontrolne spremenljivke v animatorju za animacijo "Run" nastavi na "false" (posledično se izključi animacija "Run"). Podobno funkcijo ter način delovanja ima korutina "EnRunBack()", s katero izključimo animacijo "RunBack".

30

while (Input.GetButton("Vertical")) {

yield return null;

}

animator.SetBool("RunBack", false);

}

Slika 29: Korutina EnRun().

Slika 30 prikazuje korutini "EnLCtrlDown()" ter "EnLCtrlUp()". Korutini vklapljata druga drugo, z njima pa preverjamo, ali je igralec pritisnil oz. spustil levi Ctrl ter vklapljamo oz. izklapljamo vrednost kontrolne spremenljivke v animatorju za animacijo "Walk".

IEnumerator EnLCtrlDown() {

while (!Input.GetKeyDown(KeyCode.LeftControl)) {

yield return null;

}

isWalking = true;

animator.SetBool("Walk", true);

StartCoroutine("EnLCtrlUp");

}

IEnumerator EnLCtrlUp() {

while (!Input.GetKeyUp(KeyCode.LeftControl)) {

yield return null;

}

isWalking = false;

animator.SetBool("Walk", false);

StartCoroutine("EnLCtrlDown");

}

Slika 30: Korutini EnLCtrl...()

Korutina "EnLCtrlDown()" je vključena preden igralec pritisne levi Ctrl. V pogoju zanke čakamo, da igralec pritisne levi Ctrl. Dokler se to ne zgodi, se korutina konča tako, da vrne vrednost "null".

31

Ob zaznanem pritisku levega Ctrl, se vrednost spremenljivk "isWalking« ter "Walk" v animatorju nastavita na "true".

Na koncu se vključi korutina "EnCtrlUp()", trenutna pa se prekine. Nova korutina preverja ravno obraten proces (čaka, da igralec spusti tipko levi Ctrl), na koncu pa logični spremenljivki nastavi na vrednost "false".

Slika 31 prikazuje korutini "EnLShiftDown()" ter "EnLShiftUp()", ki delujeta prav tako, kot korutini iz prejšnjega primera (slika 30). Za razliko od "EnLCtrl…()" korutine, v tem primeru preverjamo pritisk in spust tipke levi Shift, upravljamo pa logične spremenljivke "IsSprinting" oz.

kontrolno spremenljivko za animacijo "Sprint", s tem pa vklapljamo animacijo "Sprint" ter spreminjamo hitrost premikanja.

IEnumerator EnLShiftDown() {

while (!Input.GetKeyDown(KeyCode.LeftShift)) {

yield return null;

}

isSprinting = true;

animator.SetBool("Sprint", true);

StartCoroutine("EnLShiftUp");

}

IEnumerator EnLShiftUp() {

while (!Input.GetKeyUp(KeyCode.LeftShift)) {

yield return null;

}

isSprinting = false;

animator.SetBool("Sprint", false);

StartCoroutine("EnLShiftDown");

}

Slika 31: Korutini EnLShiftDown() in EnLShiftUp().

32

Slika 32 prikazuje korutino "EnJump()", ki jo uporabimo za izvedbo skoka ob zaznanem pritisku tipke presledek ter za natančno vklapljanje oziroma izklapljanje animacij in ostalih korutin.

IEnumerator EnJump() {

enJumpStarted = true;

while (!Input.GetKeyDown(KeyCode.Space) || !isGrounded) {

yield return null;

}

animator.SetBool("Jump", true);

yield return null;

PlayerJump();

enJumpStarted = false;

}

Slika 32: Korutina EnJump().

Skok izvedemo s pomočjo korutine, saj se metodi "Update()" in "FixedUpdate()" izkažeta za nezanesljivi. Če pritisk tipke presledek preverjamo v metodi "FixedUpdate()", pritisk tipke pogosto ni zaznan, zato se skok ne izvede. Če pritisk tipke preverjamo v metodi "Update()", se skok pogosto izvede nepredvidljivo (občasno je preveč klicev, zato je skok previsok).

Na začetku korutine spremenljivki "enJumpStarted" določimo vrednost "true", s katero pri ponovnih klicih preverimo oz. ugotovimo, ali je korutina že vklopljena. Ta korak je zelo pomemben, saj mora bili vklopljena le ena korutina "EnJump()". V nasprotnem primeru lahko pride do vklopa več istih korutin, zato skoki postajajo nepredvidljivi.

S pomočjo "while" zanke preverjamo, ali je igralec pritisnil tipko presledek ter ali se glavni lik dotika tal. Ko sta oba pogoja izpolnjena, korutina izstopi, ne da bi vrnila vrednost (return null).

Sledi ukaz, s katerim nastavimo animatorjevo kontrolno spremenljivko za animacijo "Jump" na vrednost "true", nato pa izstopimo iz korutine, ne da bi vrnili vrednost (return null). Z vmesnim

"yield" izstopom dosežemo, da se prične izvedba animacije "Jump", tej pa sledi klic metode

"PlayerJump()", s katero dosežemo, da se glavni lik dvigne od tal.

Na koncu nastavimo spremenljivko "enJumpStarted" na vrednost "false", da omogočimo ponoven vklop korutine "EnJump()".

33