Tässä harjoituksessa käydään läpi 2D-fysiikkaa.
Mallityö: http://dattari.fi/opettaja/Unity/Wheel2/
Tässä harjoituksessa opittavia uusia asioita:
- Ground Check (esimerkiksi ilmassa hyppäämisen estämistä varten)
- 2D fysiikkaa: AddForce, AddTorque, Impulse
- 2D colliderit
- 2D materiaali: kitka (friction) ja kimmoisuus (bounciness)
- Reittiä pitkin kulkeva peliobjekti, kuten hissi
- Layerien käyttö
- Pelaajaa tasaisesti seuraava kameraskripti (SmoothDamp)
1. Ground Check
Tee Asseteihin ainakin seuraavat alikansiot: Scripts, Prefabs, 2DMaterials, Graphs, Scenes. Asettele uudet assetit jatkossa noihin. Juuri äsken tuodut kaksi spriteä voit viedä Graphs -kansioon.
Raahaa ground scenelle ja aseta se koordinaatteihin (0, -4, 0). Aseta sen skaalaksi (scale) (7, 3, 1). Lisää sille vielä komponentiksi 2D box collider (Add Component | Physics2D | Box Collider 2D). Nyt sinulla on pelialusta josta pelivälineet eivät tipu läpi. Tee siitä Prefab.
Luo uusi Layer nimeltä Ground ja aseta se pelialustan Layeriksi alla olevan kuvan mukaan.
Raahaa wheel sceneen ja aseta sille komponentiksi 2D circle collider.
Wheel valittuna luo uusi tyhjä lapsi-peliobjekti (GameObject | Create Empty Child). Aseta se täsmälleen samoihin koordinaatteihin Wheelin kanssa (Sen pitäisi jo olla). Muuta sen nimeksi GroundHitCheck. Koska meillä oli Wheel valittuna objektin luomishetkellä, siitä tuli Wheelin lapsiobjekti.
Luo uusi C#-koodi nimeltä GroundHitCheck ja lisää siihen alla oleva koodi:
https://pastebin.com/pBnnkfGv
Huomaa että isGrounded tarkistus tehdään Physics2D.OverlapCircle –funktiolla, joka ”ottaa sisään” kolme parametria. Ensimmäinen on sijainti (meidän tapauksessa 0,0) ja toinen on säde, joka on sama kuin Wheelin säde eli 1. Kolmas on layerit joista overlap tarkistetaan.
Raahaa luotu koodi Wheel-objektiin Inspectorissa. Raahaa sitten koodin Ground Check 1 –kenttään tyhjä peliobjekti GroundHitCheck ja muuta sen Ground_layers arvoksi Ground.
Nyt koodilla voi testata koskeeko objekti maahan. Paina Play ja mene pelitilassa Scene-näkymään. Ota Console –näkymä esille ja raahaa Wheeliä maahan ja ilmaan. Konsoliin pitäisi tulla rivejä Ground: True / False riippuen siitä koskeeko Wheel maahan.
Lisää renkaaseen komponentiksi Rigidbody2D jotta painovoima alkaa vaikuttaa siihen. Testaa että rengas putoaa pelitilanteessa Groundin päälle ja pysähtyy siihen.
Suurenna Ground-laattaa scenellä (scale) noin kaksinkertaiseksi (sekä y- että x-akseli).
Aseta Wheelille tagi "Player". Tee Wheelistäkin Prefab, jotta voit lisätä sen myöhemmin mahdollisiin muihin Sceneihin valmiina. Lisää seuraavaksi tehtävät kontrollit nimenomaan tähän prefabiin, ei Scenellä olevaan renkaaseen.
2. Kontrollit
Fysiikkoihin sidottuja gameobjekteja liikutetaan Unityssä muuttamalla Rigidbody2D –komponentin Velocity –arvoja (x, y, z) AddForce (Vector2) tai AddTorque (float) funktioilla.
Luo uusi C#-skripti WheelControls ja kirjoita siihen alla oleva koodi.
https://pastebin.com/x6SYh5ph
Huomaa että koodissa on annettu kaksi tapaa liikuttaa pyörää: Oletuksena toimiva AddForce antaa pyörälle työntöä eteenpäin, kun taas AddTorque antaa ”vääntöä”, eli pyörittää rengasta. Näiden käytössä ero nähdään varsinkin kitkan kohdalla, joka esitellään myöhemmin.
Alussa määritellyt public-muuttujat näkyvät Wheelin Inspectorissa, ja niitä voi kokeilla muuttaa koskematta koodiin. Kokeile eri arvoja, ja kokeile molempia ”työntötapoja”. Säädä lopuksi työntötavaksi AddForce, MaxSpeediksi 50 ja Accelerationiksi 10.
Piirrä nyt Photoshopilla tai Gimpillä tai vastaavalla vihreä ympyrä, jonka läpimitta on noin 200 ja tausta läpinäkyvä. Tallenna se .png muodossa projektin Assets –kansioon. Png säilyttää läpinäkyvyyden.
Raahaa ympyrä kukkulaksi pelialustalle. Aseta sen layeriksi Ground jotta se lasketaan ”maaksi” pelissä. Aseta sille komponentiksi 2D circle collider jotta peliratas törmää siihen eikä mene läpi. Tee kukkulasta prefabi. Tuo kukkuloita lisää scenelle, asettele niitä lomittain ja venytä joistakin eri muotoisia (scale). Aseta Groundin Order in Layer ykköseksi, jotta kukkulat jäävät taustalle. Asettele kaikki esimerkiksi kuten minulla:
Testaa peliä. Huomaat nopeasti, ettei litteämmän kukkulan collider ympyränmuotoisena toimi. Poista Circle Collider ja laita siihen tilalle 2D Polygon Collider. Säädä nyt sen yläreuna mahdollisimman tarkasti laakean kukkulan muotoja vastaavaksi. Voit luoda kiintopisteitä hiiren oikealla napilla ja siirrellä niitä hiiren vasemmalla napilla.
3. Materiaali ja hyppy
Luo uusi Physics 2D Material nimeltä Rengas. Raahaa se renkaan Circle Collider 2D:n Materiaaliksi.Määritä nyt materiaalille kitka (Friction) ja kimmoisuus (Bounciness). Molemmissa arvo kannattaa asettaa nollan ja ykkösen väliin. Kimmoisuudessa 0 tarkoittaa täysin poukkuamatonta esinettä, 1 tarkoittaa täysin kimmoisaa, joka ei menetä törmäyksissä yhtään liike-energiaa. Asettele arvot vastaamaan mielikuvaasi auton renkaasta.
Muuta koodia siten että se käyttää AddTorque –metodia renkaan liikuttamiseen. Aseta renkaan Rotation Acceleration arvoon 10. Voit käyttää myös niden yhdistelmää, jolloin liikuttaminen tapahtuu sekä AddTorquella että AddForcella.
Lisää seuraava koodinpätkä WheelControlin update –metodiin:
Ja lisää vielä alun muuttujamäärittelyihin yksi rivi:
public float bounceForce;
Tuo koodi antaa renkaalle ”pulssimaisen” työnnön ylöspäin (x-akseli vektorissa on nolla, y-akseli 10) painettaessa Space-näppäintä. Anna editorissa vielä bounceForce –arvoksi vaikkapa 8. Testaa peliä.
Homma toimii muuten, mutta renkaalla hypätä myös ilmasta, mikä ei tunnu realistiselta. Hyödynnämme nyt Ground Check –toimintoa, joka tehtiin aivan alkuun.
Kiinnitä huomiota Ground Check -skriptin muuttujamäärittelyyn:
public bool isGrounded = false;
Jos muuttuja ei olisi public, ei Wheel Control voisi lukea sitä.
Tämän jälkeen lisää WheelControlsin hyppyspriptiin vielä yksi if-tarkistus, eli aseta se kokonaisuudessaan seuraavanlaiseksi:
Nyt hypyn pitäisi onnistua enää maahan kosketettaessa.
Lisää peliin johonkin kohtaan oma nimesi ja hio siitä mielekkäämpi. Voit esimerkiksi kokeilla muuttaa renkaan massaa.
4. Liikkuva alusta
Lopuksi luodaan liikkuva platformi johon pelihahmo voi hypätä. Tätä ohjetta voi käyttää niin 2D- kuin 3D-peleissä.
Luo näkymään tyhjä peliobjekti ja anna sille nimi MovingPlatform. Anna sille jokin väri ikoniksi alla olevan ohjeen mukaisesti.

Piirrä nyt jonkinnäköinen platformi jonka päälle renkaalla voisi hypätä. Aseta se samaan kohtaan kuin tyhjä objekti MovingPlatform ja aseta se myös MovingPlatformin lapsiobjektiksi.
Tee MovingPlatform –objektille vielä kaksi tyhjää lapsiobjektia ja nimeä ne point1 ja point2. Aseta niillekin näkyvä ikoni, ja siirrä ne eri kohtiin: point1 on liikkumisen alkupiste, point2 on loppupiste. Voit halutessasi asettaa pisteitä niin paljon kuin haluat, viimeisen jälkeen platform palaa alkupisteeseen. Aseta point1 jne oma ikoni kuten isäntäobjekti Moving Platformille.
Luo uusi skripti ja aseta siihen seuraava koodi: https://pastebin.com/KHBbG31E itsellesi ja aseta se objektin MovingPlatform komponentiksi. Tutustu koodiin ja yritä ymmärtää sen idea.
Nyt raahaa itse piirtämäsi platformi juuri tehdyn (Moving Platform -peliobjektin) skriptin kohtaan Platform. Aseta MoveSpeediksi vaikkapa 5. Määritä points sizeksi kaksi ja paina entteriä. Nyt raahaa sekä point1 että point2 gameobjektit skriptin kohtiin element 0 ja element 1. Raahaa Current Pointiin itse isäntäobjekti, josta se saa lähtöpisteen.
Testaa peliä. Tekemäsi platform pitäisi nyt kulkea pointtien 1 ja 2 väliä määrittämälläsi nopeudella.
5. Pelaajaa seuraava kamera
Kameran voisi asettaa pelaajan lapsiobjektiksi, jolloin se seuraisi sitä, mutta jos testaat sitä, huomaat että kamera liikkuu liian nykivästi esimerkiksi törmäystilanteissa. Kameraa kannattaa ohjata skripteillä. Tehdään tässä yksinkertainen skripti joka saa kameran seuraamaan pelihahmoa tasaisesti.Tee uusi skripti nimeltä SmoothCameraFollow ja aseta se MainCameran komponentiksi. Lisää siihen seuraava koodi: https://pastebin.com/gwqnQjrt
SmoothDamp siirtää vektoria kohti jotain objektia tietyssä ajassa. Sitä käytetään yleisesti kameran siirtämiseen.
Aseta targetiksi pelaaja. Jos kyseessä olisi "normaali" tasohyppelypeli, kannattaisi jonkin verran pelihahmon eteen tehdä tyhjä lapsiobjekti seurattavaksi, jolloin kamera antaisi aina vähän enemmän näkymää pelihahmon etupuolelle. Nyt kuitenkin pelaaja "pyörii", jolloin tuo lapsiobjektikin pyörisi mukana.
6. Bouncerit
Piirrä seuraavaksi eräänlainen kolmionmuotoinen vino"trampoliini", josta rengas saa suuren kimmokkeen. Tee siitä myös peilikuva, koska tarvitsemme molempiin puoliin ponnauttavan peliobjektin. Anna niille nimiksi BouncerLeft ja BouncerRight. Alla omat tekeleeni.Lisää Bouncereihin seuraavaksi kolme collideria: Ensin kaksi Box Collideria, jotka asetat alareunaan ja sivureunaan Edit Collider -toiminnolla. Lopuksi Polygon Collider, jonka asetat viistoon osoittavaan reunaan (Hypotenuusaan), kuten alla:
Tee polygon colliderista Trigger. Lisää BouncerLeftille skripti BouncerLeft, ja aseta sille sisällöksi seuraava:
https://pastebin.com/cTg7Gu3A
Nyt pelaajan törmätessä BouncerLeftiin, pelaajan liikevektori saa käänteisen arvon, jonka lisäksi pelaaja saa impulssin (myös liikevektori) vasemmalle ja ylöspäin. Tutustu koodiin.
Tee vastaava koodi BouncerRightiin. Sinun täytyy muuttaa vain yksi arvo, impulssivektorin horisontaaliarvo käänteisluvukseen.
7. Voitto ja kuolema
Rakenna pelikentästä nyt iso, siten, että siinä on jossain ylhäällä ruutulippu johon pyrkiä. Pelaajan olisi hyvä nähdä se heti alussa, jotta tietää mihin pelissä yritetään päästä, katso esimerkkityöstä mallia. Suurenna kameran näkemää aluetta sen Camera-komponentin Size-ominaisuutta kasvattamalla. Tee näkymästä tarpeeksi iso, että pelaaminen onnistuu ilman suurempia ongelmia.
Tee ruutulipulle Box Collider 2D, ja aseta se triggeriksi. Tee sitten skripti Voitto, ja aseta se ruutulipulle komponentiksi. En neuvo voitto-skriptiä tarkalleen, mutta tee se vaikka seuraavalla tavalla:
- Muuttuja win (bool), joka muuttuu TRUE:ksi kun pelaaja pääsee maaliin
- Funktioksi OnTriggerEnter2D, jota kutsutaan kun jokin törmää siihen, ja win muuttuu TRUE:ksi
- Funktioksi OnGUI, joka kirjoittaa ruudulle VOITTO! -tekstin kun win muuttuu TRUEksi.
Lisää vielä WheelControls -skriptiin alkuun kirjasto:
using UnityEngine.SceneManagement;
Tuon avulla voimme hyödyntää SceneManager-metodeja.
Seuraavaksi lisää siihen kaksi muuttujaa:
public float levelBottomY = -20f;
private GameObject rengas;
Aseta Start-funktioon seuraava rivi:
rengas = this.gameObject;
"rengas" on nyt viittaus pelihahmoon.
Lopuksi lisää seuraava ehtolause saman skriptin Update-funktioon:
if (rengas.transform.position.y <= -20f)
{
Scene scene = SceneManager.GetActiveScene(); SceneManager.LoadScene(scene.name);
}
Nyt scene lataa itse itsensä, kun pelihahmo tippuu alemmaksi kuin y=-20. Voit säätää tätä omissa kentissäsi sopivaksi.
Tee kentästä nyt hieno, siten että siinä on sopivasti haastetta päästä maaliin. Asettele bouncereita, maata ja mahdollisesti liikkuvia laattoja sopivasti, testaa, ja viritä lisää.
Kirjoita johonkin kohtaan peliä oma nimesi.
No comments:
Post a Comment