Curs actualitzat a Unity 2022 LTS
Hem actualitzat els fitxers del projecte a la versió Unity 2022.3 LTS (publicada el juny de 2023) per a aquest curs : aquesta és una versió de suport a llarg termini, que recomana Unity. Les versions LTS es publiquen cada any i són una base estable per construir els vostres projectes.
Per als estudiants, això significa fitxers de projecte coherents en tots els cursos, independentment de quan es creïn. Així que no més descarregar diferents versions Unity o obrir projectes antics plens d'errors!
Primer, obriu el Centre d'unitat i navegueu a la pantalla d'instal·lacions. A continuació, feu clic al botó blau Instal·la l'editor.
S'obrirà una finestra més petita amb una llista de versions Unity. A la part superior de la llista de llançaments oficials, a la secció 'SUPORT A LLARG TERMINI (LTS)', volem seleccionar Unity 2022.3 [LTS] (Versió recomanada). A partir d'aquí, feu clic a Instal·la i seguiu el procés d'instal·lació.
En aquesta lliçó, veurem el disseny del joc que hi ha darrere del projecte que crearem.
Aquí teniu una visió general de les coses que el jugador podrà fer al nostre joc:
Mou-te i salta pels nivells
Recolliu monedes per augmentar la puntuació
Feu clic a la bandera final per passar al següent nivell , colpejar enemics conduirà a Game Over
El reproductor estarà controlat per les tecles de fletxa del teclat:
Tecla de fletxa esquerra per moure cap a l'esquerra Tecla de fletxa dreta per moure cap a la dreta Tecla de fletxa amunt per saltar
Els enemics es mouran entre dos punts, endavant i enrere. Si el jugador toca un enemic, això activarà l'estat Game Over, que farà un reinici de nivell.
L'objectiu del jugador de cada nivell és arribar a la bandera final. En arribar al End Flag, el joc carregarà el següent nivell, si està disponible, o carregarà la pantalla Menú, si no queden més nivells.
Després, hi ha les monedes. La recollida de monedes augmentarà la puntuació del jugador, que es mostrarà a la interfície d'usuari.
Tindrem el següent bucle de joc en el nostre joc:
Salta entre plataformes evitant Enemics Recollir monedes per augmentar la puntuació
Arribeu al senyalador final per passar al següent nivell
En aquesta lliçó, vam parlar del disseny del joc del nostre joc. A la propera lliçó, muntarem el projecte per al nostre joc.
En aquesta lliçó, crearem i muntarem un projecte per al nostre joc 2D.
En primer lloc, heu d'anar a la secció Projectes d'Unity Hub i fer clic al botó Nou projecte allà.
A la finestra següent, podeu triar una plantilla per al vostre projecte. Una plantilla defineix la configuració inicial i els connectors del vostre projecte. Anirem amb la plantilla 2D Core.
A la part dreta d'aquesta finestra, podeu configurar el nom i la ubicació del projecte. Anirem amb el
My2DGame com a nom del projecte. A continuació, fem clic al botó Crea un projecte.
Un cop creat el projecte, veureu el disseny per defecte de l'Editor de la unitat i una escena buida.
Podeu canviar el disseny de l'editor al que vulgueu arrossegant i canviant la mida de les finestres de l'editor. Si voleu restablir el disseny per defecte, podeu fer-ho mitjançant el menú de disseny a l'extrem superior dret de l'Editor Unity.
A continuació, importarem alguns recursos per al nostre joc. Podeu obtenir l' arxiu Actius des dels fitxers del curs.
Un cop hàgiu baixat i descomprimit l'arxiu Recursos, notareu que hi ha la carpeta Sprites. Hauríeu de moure aquesta carpeta Sprites a la finestra Projecte de l'Editor Unity. Això importarà aquests sprites al vostre projecte.
Veureu que hi ha els personatges i les fitxes sprites en aquesta carpeta Sprites .
Ara, seleccionem els personatges i les fitxes de personatges a la carpeta Sprites i fem els canvis següents a la finestra de l'Inspector:
Establiu el mode Sprite a múltiples, ja que tenim diverses imatges a cada personatge
Establiu els píxels per unitat a 18. Això defineix la mida dels píxels de la imatge a les unitats de joc Estableix el mode de filtre en punt, de manera que les nostres imatges no es desdibuixin
Establiu la compressió a Cap, ja que els nostres personatges ja són prou petits i no necessitem comprimir-los més
Feu clic al botó Aplica quan hàgiu acabat
Ara hem de tallar aquests sprites en imatges separades que puguem utilitzar. Comencem per l' sprite de rajoles. Seleccioneu-lo a la finestra Projecte i, a continuació, feu clic al botó Editor de personatges de la finestra de l'Inspector.
Veureu la finestra de l'Editor de personatges oberta. Per tallar aquest personatge, farem el següent:
Feu clic al botó Slice a la part superior de la finestra de l'Editor de Sprite S'obrirà el menú Slice
En aquest menú, configureu el Tipus a quadrícula per mida de cel·la, de manera que els personatges es dividiran per les mides que establirem a continuació
Ajusteu la mida del píxel a (18, 18) Configureu el farciment a (2, 2) Feu clic al botó Talla
Això dividirà la imatge de les fitxes en un munt de sprites individuals.
Finalment, heu de fer clic al botó Aplica a la part superior de la finestra de l'editor de personatges per desar aquests canvis.
Ara, a la finestra Projecte, hauríeu de veure que la imatge de les peces té una fletxa al costat dret. Si feu clic en aquesta fletxa, aquesta imatge s'expandirà per mostrar tots els personatges que conté.
A continuació, tallarem la imatge dels personatges d'una manera similar. Tot i que, un cop obriu la imatge dels personatges a l'editor de personatges, és possible que observeu que els sprites que hi ha són de diferents mides, a diferència de les fitxes sprites. Per tant, tallarem la imatge dels personatges mitjançant el tipus de tall automàtic, que s'encarregarà de les mides per a nosaltres.
Ara els nostres sprites estan configurats i llestos per començar.
En aquesta lliçó, vam crear el projecte per al nostre joc i vam importar els sprites. A la següent lliçó, configurarem el controlador de jugador.
En aquesta lliçó, configurarem l' objecte del joc Jugador.
En primer lloc, seleccionem l'sprite que volem utilitzar per al nostre reproductor:
Vés a la carpeta Sprites de la finestra Projecte
Expandiu el full de personatges fent clic a la fletxa del seu costat dret
Selecciona l'sprite que vols utilitzar per al teu reproductor. Anirem amb l'sprite character_6 Arrossegueu el personatge seleccionat a la vista Escena
Això afegirà un nou objecte de joc amb el component Sprite Renderer a la vostra escena.
A continuació, crearem un objecte de joc buit per contenir aquest personatge com a objecte infantil. Necessitem aquest objecte pare principal per poder canviar la mida de l'objecte de l'sprite infantil i no preocupar-nos per l'escala dels objectes fills d' altres jugadors.
Fem el següent:
Feu clic amb el botó dret sobre l'objecte sprite characters_6 (o el que teniu) i seleccioneu l' opció Crea un pare buit al menú contextual
Canviar el nom d'aquest nou objecte pare a Jugador
Canvieu el nom de l'objecte sprite characters_6 a Sprite
Definiu el reproductor > la propietat Transforma > posició a (0, 0, 0) a la finestra Inspector Assegureu-vos que la propietat Sprite > Transforma > Position sigui (0, 0, 0) a l'Inspector
Per seguir amb els passos següents, voldrem assegurar-nos que el commutador de posició del mànec Gizmo estigui configurat a
Pivot en lloc de Centre.
Pivot - El Gizmo es col·loca en el punt de pivot precís del GameObject, que està determinat pel component Transform.
Centre – El Gizmo es posicionarà al centre en funció dels GameObjects seleccionats.
Ara, si activeu l'eina de moviment a la vista Escena prement el botó W, podreu veure que l'Sprite està centrat en el punt d'origen del reproductor.
Però, volem que el punt d'origen del jugador estigui a les potes d'aquest sprite. Per fer-ho, haurem de moure l' objecte Sprite una mica cap amunt, fins que les cames de l'sprite estiguin dretes a la línia de quadrícula horitzontal.
O bé, només podeu establir la propietat Sprite > Transforma > Posició a (0, 0.64, 0) a l'Inspector.
Ara, haurem de configurar els components que faran que el jugador es mogui i interactuï amb el sistema de física. En primer lloc, crearem l'script que controlarà el reproductor:
Crear la carpeta Scripts a la finestra Projecte
Creeu un nou script C# anomenat PlayerController a la carpeta Scripts
A continuació, seleccionem l' objecte del joc Reproductor i afegim-hi els components següents a l'Inspector:
Afegiu el component PlayerController, de manera que podríem controlar el nostre reproductor
Afegiu el component Rigidbody2D, de manera que el nostre reproductor es veuria afectat per la física
Afegiu el component CapsuleCollider2D, de manera que el nostre reproductor xocarà amb altres objectes
A continuació, retocarem el col·lisionador que acabem d'afegir:
Feu clic al botó Reproductor > Col·lisionador de càpsules 2D > Edita el col·lisionador a l'Inspector Ara podeu canviar la mida d'aquest col·lisionador per les seves nanses a la vista Escena
Feu que s'adapti a l'sprite del jugador
Aquests són els valors que tenim per al component 2D de Player > Capsule Collider:
La mida és (1.11, 1.28)
Si comenceu el joc ara, veureu que el jugador cau. Això vol dir que el Rigidbody
El component està funcionant com hauria de ser.
Ara, afegim una plataforma, de manera que el nostre jugador no caurà immediatament:
Vés a la carpeta Sprites i expandeix les peces del full de personatges
Seleccioneu l'sprite que voleu utilitzar com a plataforma. Anirem amb l' sprite tiles_0 Arrossegueu el personatge tiles_0 a la vista d'escena per estar a sota del reproductor
A continuació, farem els següents canvis a l' objecte tiles_0 a l'Inspector:
Definiu la propietat Transforma > posició a (0, -0.6, 0) per centrar-la Afegiu el component 2D del col·lisionador de caixes
Podeu notar que els components Rigidbody i Collider tenen versions regulars (3D) i 2D. Quan es treballa amb física 2D, només es poden utilitzar les versions 2D i viceversa. La física 2D i 3D d'Unity són en realitat dos sistemes diferents i, tot i que comparteixen algunes similituds, no són compatibles i no funcionen entre si.
Si comenceu el joc ara, el jugador caurà a la plataforma i es quedarà en ella.
Fins i tot podeu moure l'objecte de la plataforma a la vista Escena mentre el joc s'executa i el jugador continuarà caient sobre ell. Tot i això, si moveu la plataforma cap al costat, el jugador començarà a bolcar-se.
No volem que el nostre jugador es bolqui. Habilitem el commutador Reproductor > Rigidbody 2D > Freeze Rotation > Z a l'Inspector. Això farà impossible que el jugador es bolqui.
Si ara intenteu moure la plataforma des de sota del jugador , el jugador només se li escaparà.
En aquesta lliçó, configurem l' objecte del joc Jugador. A la següent lliçó, treballarem el Jugador
moviment.
En aquesta lliçó, establirem el moviment Player.
Ho farem a l' script PlayerController. En primer lloc, eliminem l'Inici i l'actualització
funcions a partir d'ella, ja que encara no les necessitarem:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
}
Volem fer que el nostre jugador es mogui cap a l'esquerra i cap a la dreta quan premem les tecles de fletxa esquerra i dreta. Ho farem utilitzant el component Rigidbody del jugador. Afegim alguns camps per a això:
float moveSpeed — per establir la velocitat a la qual el nostre jugador es mourà
Rigbody2D rig — per fer referència al component Rigidbody del jugador
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
}
A continuació, afegirem la funció FixedUpdate per moure-hi el reproductor. Aquesta funció s'anomena a intervals fixos, a diferència de la funció Update que s'anomena cada fotograma (i la velocitat de fotogrames pot variar molt). La funció FixedUpdate és més adequada per interactuar amb el sistema de física, ja que treballa amb la mateixa taxa fixa.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
void FixedUpdate ()
{
}
}
A continuació, farem el següent a la funció FixedUpdate:
Obteniu l' entrada horitzontal del teclat i deseu-la a la variable moveInput Configureu el cos rígid perquè tingui el moveInput com a velocitat horitzontal
void FixedUpdate ()
{
float moveInput = Input.GetAxisRaw("Horizontal"); rig.velocity = new Vector2(moveInput, 0);
}
Després, tornarem a Unity per provar els canvis que vam fer. Però primer, establim la propietat tiles_0 > Transform > Scale a (10, 1, 1), de manera que el nostre jugador tindria una mica d'espai per passejar.
Aquesta plataforma sembla estirada, però ho solucionarem un cop arribem als mapes de rajoles més endavant.
A continuació, també definim les propietats de l' script Player > Player Controller a l'Inspector:
Establiu la velocitat de moviment a 5
Configureu el Rig perquè faci referència al component Rigidbody2D del reproductor
Si comenceu el joc ara, hauríeu de poder moure el jugador cap a l'esquerra i cap a la dreta mitjançant les tecles de fletxa.
Tot i això, és possible que observeu que si baixeu per la vora de la plataforma, el reproductor cau massa lentament. Això es deu al fet que estem restablint la velocitat vertical a 0 cada fotograma físic. I també us moveu lentament horitzontalment perquè no hem utilitzat la variable moveSpeed al nostre codi.
Per solucionar aquests problemes, farem els canvis següents a la funció FixedUpdate de la
Script de PlayerController :
En establir la velocitat, multipliqueu el moveInput pel moveSpeed
I utilitzar la velocitat vertical actual com una «nova» velocitat vertical
void FixedUpdate ()
{
float moveInput = Input.GetAxisRaw("Horizontal");
rig.velocity = new Vector2(moveInput * moveSpeed, rig.velocity.y);
}
Si proveu aquests canvis executant el joc, notareu que el jugador corre i cau molt més ràpidament.
Això és el que sembla l' script PlayerController ara mateix:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
void FixedUpdate ()
{
float moveInput = Input.GetAxisRaw("Horizontal");
rig.velocity = new Vector2(moveInput * moveSpeed, rig.velocity.y);
}
}
En aquesta lliçó, vam fer que el nostre jugador es mogués cap a l'esquerra i cap a la dreta. A la següent lliçó, farem el Jugador
saltar.
En aquesta lliçó, configurarem la capacitat de saltar per al nostre jugador.
Ho farem a l' script PlayerController. En primer lloc, afegim la variable float jumpForce per poder establir la força d'un salt de l'Inspector:
Ús de directives omeses per brevetat de public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
public float jumpForce; // Add me!
// Older code omitted for brevity
}
A continuació, gestionem el salt en si mateix a la funció Update:
Afegiu la funció Update a la classe PlayerController
Comproveu si la tecla de fletxa amunt està premuda ara mateix mitjançant la funció Input.GetKeyDown Si la tecla de fletxa amunt està baixada, afegiu la força al Rigidbody. Estem utilitzant la força de l'impuls
Mode aquí, ja que volem afegir tota la força alhora
Estem utilitzant la funció Update aquí perquè la funció GetKeyDown funciona correctament en ella, a diferència de la funció FixedUpdate on pot perdre el moment exacte de la clau d'inactivitat
void Update ()
{
if(Input.GetKeyDown(KeyCode.UpArrow))
{
rig.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
}
Això és el que sembla l' script PlayerController en aquest moment:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
public float jumpForce;
void FixedUpdate ()
{
float moveInput = Input.GetAxisRaw("Horizontal");
rig.velocity = new Vector2(moveInput * moveSpeed, rig.velocity.y);
}
void Update ()
{
if(Input.GetKeyDown(KeyCode.UpArrow))
{
rig.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
}
}
Ara, tornem a Unity i configurem la propietat Player > Player Controller > Jump Force a 5
a l'Inspector.
A continuació, podeu començar el joc i provar els salts que acabem d'implementar.
És possible que vulgueu modificar la propietat Jump Force per fer que el vostre jugador salti més alt. Després de canviar-lo a un valor superior, és possible que noteu que el vostre reproductor cau una mica flotant, com a l'espai. Per ajustar-ho, podeu canviar la força de gravetat amb una propietat Rigidbody 2D > Gravity Scale.
Aquests són els valors que establim per al nostre jugador a l'inspector:
Si heu canviat aquests valors mentre esteu en mode de reproducció, notareu que tornen a canviar un cop atureu el mode de reproducció. Per tant, assegureu-vos de configurar-los mentre esteu en mode d'edició, de manera que es desin aquests canvis.
Hi ha un problema més, però. Ara mateix, el jugador està saltant cada vegada que premeu el botó de salt, cosa que fa possible que el jugador salti massa alt. Treballarem per solucionar-ho a la propera lliçó.
En aquesta lliçó, vam fer saltar al jugador . A la propera lliçó, ho farem perquè el nostre jugador pugui saltar només estant a terra.
En aquesta lliçó, configurarem la detecció de terra per al nostre jugador, de manera que només podrem saltar estant a terra.
En primer lloc, afegirem una nova variable privada bool isGrounded per emmagatzemar-hi l'estat de terra.
Ús de directives omeses per brevetat de public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
public float jumpForce;
private bool isGrounded; // Add me!!
//Codi antic omès per brevetat
}
A continuació, afegirem una nova funció OnCollisionEnter2D. Aquesta funció s'anomena quan el nostre objecte xoca amb alguna cosa, que és exactament el que passa quan el nostre jugador xoca contra el terra.
En aquesta funció, comprovarem si la normalitat del primer punt de contacte de col·lisió apunta cap amunt. Normal aquí és un vector que està apuntat «lluny» de la superfície. Si està apuntada cap amunt, la superfície en si és horitzontal i el més probable és que sigui terra.
En aquest cas, definirem la variable isGrounded com a true:
private void OnCollisionEnter2D (Collision2D collision)
{
if(collision.GetContact(0).normal == Vector2.up)
{
isGrounded = true;
}
}
A continuació, farem els canvis següents a la funció Update:
Comproveu si la tecla amunt està baixada i el senyalador isGrounded és cert
Al salt, establiu la bandera isGrounded a false
void Update ()
{
// If we press the jump button and we are grounded, then jump.
if(Input.GetKeyDown(KeyCode.UpArrow) && isGrounded)
{
isGrounded = false;
rig.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
}
Si comenceu el joc ara, notareu que només podeu saltar una vegada després de tocar a terra.
Una cosa més que podem fer és fer que el personatge del jugador miri en la direcció en què es mou. Això és el que farem:
Afegiu la variable sr de SpriteRenderer pública a la classe PlayerController
A la funció FixedUpdate, invertiu l'sprite sr a la X, si la velocitat horitzontal és superior a zero
Ús de directives omeses per brevetat
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
public float jumpForce;
public SpriteRenderer sr; // Add me!!
private bool isGrounded;
void FixedUpdate ()
{
// Older code omitted for brevity
if(rig.velocity.x > 0) // Add those checks!!
{
sr.flipX = true;
}
else if(rig.velocity.x < 0)
{
sr.flipX = false;
}
}
}
Això és el que sembla l' script PlayerController en aquest moment:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
public float jumpForce;
public SpriteRenderer sr;
private bool isGrounded;
void FixedUpdate ()
{
float moveInput = Input.GetAxisRaw("Horizontal");
rig.velocity = new Vector2(moveInput * moveSpeed, rig.velocity.y);
if(rig.velocity.x > 0)
{
sr.flipX = true;
}
else if(rig.velocity.x < 0)
{
sr.flipX = false;
}
}
void Update ()
{
// If we press the jump button and we are grounded, then jump.
if(Input.GetKeyDown(KeyCode.UpArrow) && isGrounded)
{
isGrounded = false;
rig.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
}
private void OnCollisionEnter2D (Collision2D collision)
{
if(collision.GetContact(0).normal == Vector2.up)
{
isGrounded = true;
}
}
}
Després, a Unity, hem d'anar a l'Inspector i establir el camp Player > Player Controller > Sr per fer referència a l'objecte Sprite fill del jugador.
Ara el nostre objecte Player està mirant en la direcció en què es mou.
També fem que l' objecte Càmera estigui connectat al reproductor. En primer lloc, arrossegarem la càmera principal
objecte a l' objecte Reproductor. Això farà que la càmera segueixi el reproductor.
A continuació, ajustarem els components de la càmera principal a l'inspector així:
Establiu la transformada > posició a (0, 1, -10)
Configureu la càmera > el fons a un color agradable
Ara la càmera segueix el jugador mentre ens movem i saltem.
En aquesta lliçó, configurem la detecció de terra, la rotació de sprites i el moviment de la càmera. A la propera lliçó, començarem a treballar en la creació dels nivells.
En aquesta lliçó, configurarem un nivell mitjançant un mapa de rajoles. El sistema Unity Tilemap ens permet construir nivells 2D a partir de tilemaps o sprites.
Ja tenim la imatge de les fitxes tallades en rajoles a la nostra carpeta Sprites. Utilitzarem aquestes rajoles per construir els nostres nivells.
Podríem començar a arrossegar aquestes fitxes a la vista Escena per construir-ne un nivell, però en realitat no és la millor manera de fer-ho, ja que haureu de fer molta feina amb molta precisió i manualment.
Afortunadament, Unity té un sistema Tilemap, que ens ajudarà. Per tant, fem el següent ara:
Traieu tots els objectes de rajoles que tingueu a l'escena
Feu clic amb el botó dret a la Jerarquia i seleccioneu l' opció 2D Object > Tilemap > Rectangular del menú contextual
Això crearà els objectes Grid i Tilemap a la vostra escena.
L' objecte de joc Grid té un component Grid, que defineix la quadrícula que teniu a l'escena. Fins i tot podeu veure aquesta quadrícula a la visualització Escena.
I l' objecte Tilemap té els components Tilemap i Tilemap Renderer per mantenir la informació i representar el mapa de mosaic.
Per utilitzar un mapa de rajoles, primer hem de crear una paleta de rajoles. Obrim la finestra Paleta de rajoles seleccionant l' opció Finestra > 2D > Paleta de rajoles de la barra de menú superior.
En aquesta finestra, crearem una paleta de rajoles nova com aquesta:
Feu clic al botó Crea una paleta nova
Definiu el nom de la paleta. Anirem amb MyPalette
Feu clic al botó Crea a la part inferior
Aleshores, haureu de triar un lloc per a la paleta de rajoles. Creem una nova carpeta Tilemap a la
Carpeta d'actius i seleccioneu-la.
Després d'això, el text de la finestra Paleta de peces hauria de canviar a «Arrossega els recursos de textura de mosaic, sprite o sprite aquí.» Ara, podeu arrossegar els sprites de les peces imatge una per una, però anirem arrossegant tot el fitxer de fitxes a aquesta finestra de paleta de rajoles.
A continuació, haureu de seleccionar la carpeta per a aquestes peces. Tornarem a anar amb la carpeta Actius > Tilemap.
I ara teniu totes aquestes fitxes a la finestra de paleta de rajoles . També recomanem acoblar aquesta finestra al costat de l'inspector, ja que això farà que sigui convenient canviar ràpidament entre tots dos.
Dibuixar amb fitxes és bastant fàcil:
Ves a la finestra Paleta de peces
Feu clic a la fitxa amb què vulgueu dibuixar Assegureu-vos que el mode Pinzell estigui actiu Aneu a la vista Escena i dibuixeu-hi
Ara pintarem una mica de terreny per al nostre jugador amb una fitxa de terra.
Després, podríeu pintar a la part superior del terra amb una rajola d'herba:
Per utilitzar una goma d'esborrar, podeu seleccionar l' eina Esborrador a la finestra Paleta de rajoles o simplement mantenir premuda la botó
Canvieu la tecla i feu clic a les peces que vulgueu esborrar.
Ara, si voleu seleccionar la peça que ja heu utilitzat a la vista Escena, podeu fer-ho amb una selecció
eina. És similar a una eina comptagotes en programari gràfic.
Per exemple, podeu tornar a triar una rajola de terra.
Després, si voleu pintar sobre una àrea gran amb la mateixa rajola, podeu anar amb l' eina Fill Box.
Amb aquesta eina, podeu omplir una àrea rectangle amb una rajola.
Abans de crear el nivell en si, hem de configurar una cosa més. Si comenceu el joc ara mateix, notareu que el jugador està caient just a través de les fitxes. Això es deu al fet que aquestes rajoles encara no tenen col·lisionadors.
Per solucionar aquest problema, heu de seleccionar l' objecte Tilemap, anar a la finestra de l'Inspector i afegir el
Tilemap Collider component 2D a l' objecte Tilemap.
Com podeu veure a la vista Escena, aquest component afegeix col·lisionadors a cadascuna de les peces del mosaic.
I ara pots moure't i saltar sobre les fitxes que tens a l'escena.
Ara podeu crear un nivell per al vostre joc. Però abans de començar, volem que tinguis en compte diverses coses.
En primer lloc, el vostre jugador té una alçada de salt limitada, de manera que heu de construir un nivell de manera que pugueu saltar a totes les seves superfícies. Pots provar el teu nivell en mode de joc .
Després, afegirem enemics, monedes i una bandera final més endavant. Ja podeu començar a planificar on els voleu posar.
Aquí teniu un nivell que hem construït:
Una cosa que podeu notar mentre treballeu al vostre nivell és que l'eina de rajoles encara està activa fins i tot després de tancar la finestra de paleta de rajoles. Per desseleccionar una eina de mosaic, només heu de seleccionar una de les eines d'escena, com ara una eina de visualització o moviment. Podeu fer-ho fent clic a les seves icones a la vista Escena o prement les tecles de drecera — Q i W en conseqüència
L'últim que farem és canviar el nom de la nostra escena a Nivell 1:
Assegureu-vos que l'escena estigui desada Aneu a la carpeta Escenes
Canvieu el nom de l'escena a Nivell1
Apareixerà una finestra de modificació d'escena, feu clic al botó Recarrega
Ara podeu configurar nivells addicionals d'una manera similar si voleu.
En aquesta lliçó, construïm el nostre nivell utilitzant mapes de rajoles. A la propera lliçó, configurarem els nostres enemics.
En aquesta lliçó, treballarem en la configuració de l' enemic.
En primer lloc, creem un objecte enemic:
Crear un nou objecte de joc buit Anomena'l Enemic
Moveu-lo a l'escena de manera que no es creui amb el reproductor o el nivell
A continuació, afegirem un personatge al nostre enemic:
Seleccioneu un personatge enemic del full de personatges de la carpeta Sprites. Anirem amb characters_24 sprite
Arrossegueu aquest personatge a l' objecte Enemic de la jerarquia Canvieu el nom d'aquest objecte de joc de sprite a Sprite
A la finestra Inspector, restabliu la propietat Sprite > Transform > Position a (0, 0, 0), de manera que aquest personatge se centri en l'objecte pare
A continuació, afegirem un col·lisionador al nostre objecte enemic a la finestra de l'Inspector:
Afegir un component 2D del Col·lisionador de Cercle a l'objecte Enemic
Habilita l' enemic > Col·lisionador de cercles 2D > és la propietat Trigger , ja que no volem xocar amb els enemics
Definiu la propietat Enemy > Circle Collider 2D > Radius a 0,4, de manera que estigui més a prop de la mida del personatge
Així és com es veu aquest col·lisionador a la vista Enemic a l'escena:
Després d'això, afegim un script de controlador enemic a l' objecte Enemic:
Crear un nou script Enemy C# a la carpeta Scripts Adjuntar l' script Enemy a l'objecte del joc Enemy
Ara, estem preparats per escriure el comportament del nostre enemic. En primer lloc, afegim algunes variables a l'enemic
guió:
public float moveSpeed: per establir la velocitat a la qual es mourà el nostre enemic
public Vector3 moveOffset - per establir la posició a la qual el nostre Enemic es mourà en el joc privat Vector3 startPos - per guardar en memòria cau la posició inicial perquè el nostre Enemic pugui tornar a ella Vector3 objectiu privat - per mantenir la pista de quina posició ha de tenir el nostre Enemic
Avançar cap a
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
public float moveSpeed;
public Vector3 moveOffset;
private Vector3 startPos;
private Vector3 targetPos;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
A continuació, a la funció Start, definirem les variables privades:
Ajusteu el startPos a la posició actual de l'enemic
Establiu l' objectiuPos al startPos. Això quedarà clar en un moment
void Start()
{
startPos = transform.position;
targetPos = startPos;
}
A continuació, mourem el nostre enemic a la funció Update, que s'anomena cada fotograma. Això és el que farem:
Utilitzeu la funció Vector3.MoveTowards per actualitzar la posició enemiga
Utilitzeu la posició actual i l' objectiu com a arguments corresponents
Utilitza la moveSpeed multiplicada per deltaTime com a distància màxima a moure. D'aquesta manera, el nostre moviment serà independent
void Update()
{
// Move towards the target position.
transform.position = Vector3.MoveTowards(transform.position, targetPos, moveSpeed
* Time.deltaTime);
}
Després d'això, comprovarem si aquest enemic va arribar a la posició objectiu. Una vegada que l' enemic arriba a la posició objectiu, hem d'actualitzar la posició de l'objectiu:
Si targetPos és el mateix que el startPos, actualitzarem el targetPos perquè sigui la posició offset
En cas contrari, l' enemic arribava a la posició de desplaçament, i fixarem l' objectiu a la
void Update()
{
// Move towards the target position.
transform.position = Vector3.MoveTowards(transform.position, targetPos, moveS
peed * Time.deltaTime);
// Are we at the target position?
if(transform.position == targetPos)
{
// Is our target pos our start pos? If so, set it to be the other one.
if(targetPos == startPos)
{
targetPos = startPos + moveOffset;
}
// Otherwise, do the opposite.
else
{
targetPos = startPos;
}
}
}
Ara, tornem a Unity per provar els canvis que hem fet. Posarem l'enemic > l'enemic
component així:
Definiu la velocitat de moviment a 2
Definiu el desplaçament de moviments a (0, 3, 0)
Si comenceu el joc, veureu que l' enemic es mou 3 unitats cap amunt i després torna a la posició inicial
amb la velocitat de 2 unitats per segon.
Per previsualitzar la ruta de l'enemic a la vista Escena, podeu utilitzar la funció OnDrawGizmos:
Inicieu el de i cap a les posicions, depenent de si el joc ha començat. L'startPos no s'inicia en el mode d'edició i la posició actual està canviant en el mode de joc, de manera que no podeu utilitzar-los en aquests modes respectius
Dibuixa artefactes de línia i esfera en el de → a ruta
private void OnDrawGizmos()
{
Vector3 from;
Vector3 to;
if (Application.isPlaying)
{
from = startPos;
}
else
{
from = transform.position;
}
to = from + moveOffset;
Gizmos.color = Color.red;
Gizmos.DrawLine(from, to);
Gizmos.DrawWireSphere(to, 0.2f);
Gizmos.DrawWireSphere(from, 0.2f);
}
Així és com aquesta funció representa la ruta de l'enemic a la vista Escena:
Aquí teniu el guió d'Enemic en aquest moment:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
public float moveSpeed;
public Vector3 moveOffset;
private Vector3 startPos;
private Vector3 targetPos;
// Start is called before the first frame update
void Start()
{
startPos = transform.position;
targetPos = startPos;
}
// Update is called once per frame
void Update()
{
// Move towards the target position.
transform.position = Vector3.MoveTowards(transform.position, targetPos, moveS
peed * Time.deltaTime);
// Are we at the target position?
if(transform.position == targetPos)
{
// Is our target pos our start pos? If so, set it to be the other one.
if(targetPos == startPos)
{
targetPos = startPos + moveOffset;
}
// Otherwise, do the opposite.
else
{
targetPos = startPos;
}
}
}
private void OnDrawGizmos()
{
Vector3 from;
Vector3 to;
if (Application.isPlaying)
{
from = startPos;
}
else
{
from = transform.position;
}
to = from + moveOffset;
Gizmos.color = Color.red;
Gizmos.DrawLine(from, to);
Gizmos.DrawWireSphere(to, 0.2f);
Gizmos.DrawWireSphere(from, 0.2f);
}
}
En aquesta lliçó, vam crear l'enemic en moviment. A la següent lliçó, treballarem el Game Over.
En aquesta lliçó, configurarem l' estat Game Over per al nostre joc. En el nostre joc, l' estat Game Over passarà quan el jugador colpegi un enemic, o quan el jugador caigui del nivell.
Per implementar l'estat Game Over, anirem a l'script PlayerController i farem els següents canvis:
Afegir la biblioteca SceneManagement a la part superior de l'script Afegir la funció GameOver a l'script PlayerController
A la funció GameOver, utilitzeu la funció LoadScene per tornar a carregar l'escena actual
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; // Add me!!
public class PlayerController : MonoBehaviour
{
// Older code omitted for brevity
// Called when we get hit by an enemy or if we fall below the level.
public void GameOver ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
I això és el que sembla l' script de PlayerController en aquest moment:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
public float jumpForce;
public SpriteRenderer sr;
private bool isGrounded;
void FixedUpdate ()
{
float moveInput = Input.GetAxisRaw("Horizontal");
rig.velocity = new Vector2(moveInput * moveSpeed, rig.velocity.y);
if(rig.velocity.x > 0)
{
sr.flipX = true;
}
else if(rig.velocity.x < 0)
{
sr.flipX = false;
}
}
void Update ()
{
// If we press the jump button and we are grounded, then jump.
if(Input.GetKeyDown(KeyCode.UpArrow) && isGrounded)
{
isGrounded = false;
rig.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
}
private void OnCollisionEnter2D (Collision2D collision)
{
if(collision.GetContact(0).normal == Vector2.up)
{
isGrounded = true;
}
}
// Called when we get hit by an enemy or if we fall below the level.
public void GameOver ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
Com a repte, volem que implementeu vosaltres mateixos un dels casos de joc. En aquest repte, hauríeu de fer que l'escenari de caiguda del nivell funcioni com un game-over.
Una de les maneres de fer-ho és comprovar si la posició vertical del jugador està per sota d'algun nivell. La comprovació es podria fer a la funció Update.
En aquesta lliçó, hem implementat la funció Game Over. A la propera lliçó, implementarem els escenaris de joc.
En aquesta lliçó, implementarem els escenaris de Game Over.
Per fer que el Game Over passi quan el jugador cau del nivell, hauríem de fer els següents canvis a la funció Player Controller > Update:
A la funció Actualitza, comproveu si la posició vertical del reproductor és inferior a -4
Si és així, crideu a la funció GameOver
// Using directives omitted for brevity
public class PlayerController : MonoBehaviour
{
// Older code omitted for brevity
void Update ()
{
// Older code omitted for brevity
// If we fall below -4 on the Y, then game over.
if(transform.position.y < -4)
{
GameOver();
}
}
// Older code omitted for brevity
}
Si comenceu el joc ara i salteu des del nivell, en un parell de segons, el nivell es tornarà a carregar des del principi.
Això és el que sembla l' script PlayerController ara:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
public float jumpForce;
public SpriteRenderer sr;
private bool isGrounded;
void FixedUpdate ()
{
// Get the horizontal move input.
float moveInput = Input.GetAxisRaw("Horizontal");
// Set our velocity.
rig.velocity = new Vector2(moveInput * moveSpeed, rig.velocity.y);
// Flip the sprite to face our moving direction.
if(rig.velocity.x > 0)
{
sr.flipX = true;
}
else if(rig.velocity.x < 0)
{
sr.flipX = false;
}
}
void Update ()
{
// If we press the jump button and we are grounded, then jump.
if(Input.GetKeyDown(KeyCode.UpArrow) && isGrounded)
{
isGrounded = false;
rig.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
// If we fall below -4 on the Y, then game over.
if(transform.position.y < -4)
{
GameOver();
}
}
private void OnCollisionEnter2D (Collision2D collision)
{
if(collision.GetContact(0).normal == Vector2.up)
{
isGrounded = true;
}
}
// Called when we get hit by an enemy or if we fall below the level.
public void GameOver ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
També hauríem d'anar a l' estat Game Over una vegada que el jugador colpeja un enemic. Ho farem des de la
Guió enemic .
Però primer, hem d'afegir una manera perquè un enemic sàpiga que colpeja el jugador, i no una altra cosa. Això és el que farem:
Seleccionar l'objecte del joc Reproductor Vés a la finestra de l'Inspector
Definiu la propietat Tag a la part superior de la finestra de l'Inspector al valor Reproductor Ara el nostre jugador està etiquetat com a Reproductor. Ben fet!
I això és el que farem en el guió de l'enemic:
Afegiu la funció OnTriggerEnter2D. Aquesta funció s'anomena quan alguna cosa entra al col·lisionador disparador
En aquesta funció, comprovar si tenim una col·lisió amb un objecte etiquetat com a Reproductor
Si és així, obteniu el component PlayerController d'aquest objecte i truqueu-hi la funció GameOver
//Ús de directives omeses per brevetat
public class Enemy : MonoBehaviour
{
// Older code omitted for brevity
private void OnTriggerEnter2D (Collider2D collision)
{
// Did the player hit us?
© 2024 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com
Create Your First 2D Game in Unity
Game Over - Part 2
if(collision.CompareTag("Player"))
{
// Trigger the game over state on the player.
collision.GetComponent<PlayerController>().GameOver();
}
}
}
Ara, si us llanceu a un enemic, el joc també es tornarà a carregar. Això és el que sembla l'script complet d' Enemy :
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
public float moveSpeed;
public Vector3 moveOffset;
private Vector3 startPos;
private Vector3 targetPos;
// Start is called before the first frame update
void Start()
{
startPos = transform.position;
targetPos = startPos;
}
// Update is called once per frame
void Update()
{
// Move towards the target position.
transform.position = Vector3.MoveTowards(transform.position, targetPos, moveS
peed * Time.deltaTime);
// Are we at the target position?
if(transform.position == targetPos)
{
// Is our target pos our start pos? If so, set it to be the other one.
if(targetPos == startPos)
{
targetPos = startPos + moveOffset;
}
// Otherwise, do the opposite.
else
{
targetPos = startPos;
}
}
}
© 2024 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com
Create Your First 2D Game in Unity
Game Over - Part 2
private void OnDrawGizmos()
{
Vector3 from;
Vector3 to;
if (Application.isPlaying)
{
from = startPos;
}
else
{
from = transform.position;
}
to = from + moveOffset;
Gizmos.color = Color.red;
Gizmos.DrawLine(from, to);
Gizmos.DrawWireSphere(to, 0.2f);
Gizmos.DrawWireSphere(from, 0.2f);
}
private void OnTriggerEnter2D (Collider2D collision)
{
// Did the player hit us?
if(collision.CompareTag("Player"))
{
// Trigger the game over state on the player.
collision.GetComponent<PlayerController>().GameOver();
}
}
}
En aquesta lliçó, hem implementat els escenaris de Game Over. A la propera lliçó, treballarem les monedes de col·lecció.
En aquesta lliçó, establirem les bases del sistema de puntuació i les monedes.
En primer lloc, afegirem una variable de puntuació i una manera de canviar-la a la classe PlayerController:
Afegiu una nova variable de puntuació int pública, per emmagatzemar la puntuació del jugador
Afegiu la funció AddScore, que hauria de prendre una quantitat per la qual s'hauria d'augmentar la puntuació
En aquesta funció, augmentar la puntuació per l'import aprovat
També hem d'actualitzar la interfície d'usuari aquí, però com que no tenim la interfície d'usuari preparada, deixarem un comentari per ara
// Using directives omitted for brevity
public class PlayerController : MonoBehaviour
{
// Older code omitted for brevity
public SpriteRenderer sr;
public int score; // Add me!!
// Older code omitted for brevity
// Increases our score and updates the UI.
public void AddScore (int amount)
{
score += amount;
// TODO Update score UI
}
}
Això és el que sembla l' script PlayerController ara:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
public float jumpForce;
public SpriteRenderer sr;
public int score;
private bool isGrounded;
void FixedUpdate ()
{
// Get the horizontal move input.
float moveInput = Input.GetAxisRaw("Horizontal");
// Set our velocity.
rig.velocity = new Vector2(moveInput * moveSpeed, rig.velocity.y);
// Flip the sprite to face our moving direction.
if(rig.velocity.x > 0)
{
sr.flipX = true;
}
else if(rig.velocity.x < 0)
{
sr.flipX = false;
}
}
void Update ()
{
// If we press the jump button and we are grounded, then jump.
if(Input.GetKeyDown(KeyCode.UpArrow) && isGrounded)
{
isGrounded = false;
rig.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
// If we fall below -4 on the Y, then game over.
if(transform.position.y < -4)
{
GameOver();
}
}
private void OnCollisionEnter2D (Collision2D collision)
{
if(collision.GetContact(0).normal == Vector2.up)
{
isGrounded = true;
}
}
// Called when we get hit by an enemy or if we fall below the level.
public void GameOver ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
// Increases our score and updates the UI.
public void AddScore (int amount)
{
score += amount;
// TODO Update score UI
}
}
Comencem per crear un nou objecte Moneda:
Crear un nou objecte de joc buit Anomena'l Moneda
A la vista Escena, col·loqueu aquest objecte Moneda de manera que no es creui amb el jugador, l'enemic o el nivell
A continuació, afegirem un personatge a la nostra moneda:
Selecciona el personatge de moneda tiles_151 de les peces del full de personatges de la carpeta Sprites Arrossega aquest personatge a l' objecte Moneda de la jerarquia
Canvieu el nom d'aquest objecte de joc de sprite a Sprite
Restableix la propietat Sprite > Transform > Position a (0, 0, 0), de manera que aquest personatge de la moneda se centri en l'objecte pare
A continuació, afegirem un col·lisionador a l' objecte Coin:
Afegir un nou component 2D del Circle Collider a l'objecte Coin
Activa el commutador Coin > Circle Collider 2D > Is Trigger , de manera que aquest objecte no xocarà físicament amb altres objectes
Establiu la propietat Coin > Circle Collider 2D > Radius a 0,3, per adaptar-la a l'sprite
Finalment, crearem un guió per a la moneda:
Creeu un nou script C# anomenat Moneda a la carpeta Scripts Adjuntar l' script Coin a l'objecte del joc Coin
Ara, obrim l' script de la moneda i comencem a treballar-hi:
Suprimiu les funcions Inici i Actualització, ja que ara mateix no les necessitarem
Afegir una nova variable public int scoreToDon, de manera que podríem establir el valor de les monedes
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Coin : MonoBehaviour
{
public int scoreToGive;
}
Igual que amb l'script Enemy, utilitzarem la funció OnTriggerEnter2D per comprovar si hi ha col·lisions amb el
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Coin : MonoBehaviour
{
public int scoreToGive;
private void OnTriggerEnter2D (Collider2D collision)
{
// TODO Increase the Player's score
// TODO Destroy this coin
}
}
Tot i que, com a repte, volem que implementeu aquesta funció vosaltres mateixos. Aquesta funció
ha de fer el següent:
Comprova si hem xocat amb el jugador
Si és així, augmenteu la puntuació del jugador i suprimiu la moneda en si
Podeu referir-vos a l' escriptura Enemic, ja que aquí vam fer una cosa semblant.
En aquesta lliçó, vam començar a treballar el sistema de puntuació i l' objecte Coin. A la següent lliçó, acabarem el nostre treball sobre el guió de la moneda.
En aquesta lliçó, acabarem el nostre treball sobre el guió de la moneda .
En primer lloc, aquí teniu com hem implementat la funció OnTriggerEnter2D de la classe Coin:
Comprovar si l'objecte col·lisionat està etiquetat com a Reproductor
Si és així, obteniu el component PlayerController d'aquest objecte i augmenteu la puntuació
Després, destrueix el joc de la monedaObjecte
private void OnTriggerEnter2D (Collider2D collision)
{
// Did the player hit us?
if(collision.CompareTag("Player"))
{
// Increase their score, then destroy our GameObject.
collision.GetComponent<PlayerController>().AddScore(scoreToGive);
Destroy(gameObject);
}
}
Ara, tornem a Unity i fem el següent:
A la finestra de l'inspector, definiu la moneda > la moneda > la puntuació per donar la propietat a 1
Creeu diverses còpies de l' objecte Coin seleccionant-lo i prement Ctrl+D al teclat
Arrossegueu les còpies de monedes a diferents llocs del nivell
Ara, si comenceu el joc i recolliu les monedes, notareu que desapareixen i la
Canvis en la propietat Player > Player Controller > Score .
Podem fer que les nostres monedes es moguin amunt i avall, de manera que no siguin tan estàtiques al nivell. Fem primer les coses següents:
Afegiu la variable private float startYPos a la memòria cau de la posició inicial Y
Establiu startYPos a la funció Start, de manera que puguem tornar a la posició inicial més endavant
//Codi antic omès per brevetat classe public class Coin : MonoBehaviour
{
public int scoreToGive;
private float startYPos; // Add me!!
void Start ()
{
startYPos = transform.position.y;
}
// Older code omitted for brevity
}
Després, farem que les nostres monedes es balancegin amunt i avall:
Afegiu la variable bobHeight del flotador públic per establir l'amplitud del moviment Afegiu el flotador públic bobSpeed per establir el moviment de la velocitat
A la funció Update, utilitzeu la funció Mathf.Sin per trobar una nova posició vertical per a la moneda
A continuació, actualitzeu la posició de la moneda amb un nou valor vertical Estem utilitzant la funció Sin, ja que emet un bonic moviment ondulat.
//Codi antic omès per brevetat
public class Coin : MonoBehaviour
{
public int scoreToGive;
public float bobHeight; // Add me!!
public float bobSpeed; // Add me!!
// Older code omitted for brevity
void Update ()
{
// Bob up and down.
float newY = startYPos + (Mathf.Sin(Time.time * bobSpeed) * bobHeight);
transform.position = new Vector3(transform.position.x, newY, 0);
}
// Older code omitted for brevity
}
Ara, tornem a Unity, seleccionem els objectes de la moneda i configurem el component de la moneda a l'inspector així:
Estableix l' alçada del bob a 0,2
Establiu la velocitat del bob a 5
Si comenceu el joc ara, les monedes es balancejaran cap amunt i cap avall.
Aquí teniu el guió complet de la moneda:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Coin : MonoBehaviour
{
public int scoreToGive;
public float bobHeight;
public float bobSpeed;
private float startYPos;
void Start ()
{
startYPos = transform.position.y;
}
void Update ()
{
// Bob up and down.
float newY = startYPos + (Mathf.Sin(Time.time * bobSpeed) * bobHeight);
transform.position = new Vector3(transform.position.x, newY, 0);
}
private void OnTriggerEnter2D (Collider2D collision)
{
// Did the player hit us?
if(collision.CompareTag("Player"))
{
// Increase their score, then destroy our GameObject.
collision.GetComponent<PlayerController>().AddScore(scoreToGive);
Destroy(gameObject);
}
}
}
En aquesta lliçó, vam acabar el guió de la moneda . A la següent lliçó, treballarem la interfície d'usuari de la puntuació.
En aquesta lliçó, configurarem la interfície d'usuari de puntuació per al nostre joc.
Per fer-ho, afegirem un objecte de text que mostri la puntuació actual a la part superior de la pantalla. Utilitzarem el connector Unity TextMeshPro per a això.
Però abans, hem de crear un llenç. Un objecte Canvas ajuda a posicionar els elements de la interfície d'usuari a la pantalla. Afegim un llenç ara:
Feu clic amb el botó dret a la jerarquia
Seleccioneu l' opció UI > Canvas al menú contextual
En realitat, veureu aparèixer dos objectes: el llenç i el sistema d'esdeveniments. L' objecte Sistema d'esdeveniments és necessari per passar les entrades del ratolí, la pantalla tàctil o altres dispositius d'entrada a la interfície d'usuari. Tot i que aquí no utilitzarem entrades d'interfície d'usuari, no cal que elimineu aquest objecte.
Si seleccioneu l' objecte Canvas i premeu la tecla F per enfocar-lo, notareu que el llenç és força gran. El nostre nivell es pot veure a la cantonada inferior esquerra del llenç i és realment petit
comparat amb el llenç.
Això es deu al fet que Canvas pren una unitat Unity com a píxel. Podríeu veure la mida (amplada i alçada) del llenç al component Transformada recta a la finestra de l'Inspector. En el nostre cas, això és 1920 per 1080.
Afegim un nou objecte de text ara:
Feu clic amb el botó dret a l'objecte de joc Canvas
Seleccioneu la interfície d'usuari > text - TextMeshPro opció al menú contextual
Apareixerà la finestra de l'importador TMP, feu clic al botó Importa TMP Essentials allà
Apareixerà un nou objecte de text.
Heu de notar que l'eina d'escena ha canviat a l' eina Rect. Aquesta eina permet moure aquest objecte arrossegant el seu centre i redimensionar-lo arrossegant els punts blaus a les cantonades.
També podeu alinear l' objecte Text al llarg de les línies central i de vora de l' objecte Canvas arrossegant l' objecte Text a aquestes línies.
Col·loquem el nostre objecte Text a prop de la vora superior del llenç.
A continuació, anirem a l'Inspector i canviarem les següents propietats del Text > TextMeshPro
component:
Establiu el text a «Puntuació: 100», de manera que puguem previsualitzar la nostra puntuació a l'editor Activa l'estil de lletra en negreta
Ajusteu la mida de la lletra a 50
Habilitar l' alineació del centre
Aquest és l' aspecte del nostre objecte Text a la visualització Joc:
A continuació, hem de configurar l'ancoratge de l' objecte Text. Les àncores d'un objecte de la interfície d'usuari són els triangles blancs que podríeu veure a la vista Escena mentre se selecciona l' objecte Text.
Ara mateix, el nostre text està ancorat al centre del llenç. Això significa que la distància de l' objecte Text del centre del llenç romandrà constant en valors de píxels en totes les resolucions. En realitat, això no és bo, ja que diferents dispositius tenen resolucions de píxels diferents.
Per provar-ho, podeu configurar la visualització Joc al mode de resolució d'aspecte gratuït i canviar la mida d'aquesta visualització. El text de la partitura es mourà cap amunt o cap avall.
Per solucionar-ho, heu de fer el següent:
Vés a la finestra de l'Inspector mentre l' objecte Text està seleccionat
Feu clic al botó Predefinit d'àncora a la cantonada superior esquerra del component Transformada recta Seleccioneu la preconfiguració superior central
Després d'això, aquest objecte Puntuació de text s'ha d'ancorar a la vora superior del llenç.
Ara podeu canviar la mida de la visualització Joc amb seguretat : la puntuació sempre estarà connectada a la part superior de la pantalla.
També canviem el nom d'aquest objecte Text a ScoreText.
Una última cosa a fer aquí és connectar l' script PlayerController a aquest objecte ScoreText. Fem els següents canvis a l' script PlayerController:
Afegir la llibreria TMPro, així podríem utilitzar els objectes de text TMPro
Afegiu la variable pública TextMeshProUGUI scoreText, de manera que podríem fer referència a la nostra
Objecte ScoreText
A la funció AddScore, actualitzeu el text de l'objecte scoreText
//El codi més antic omès
using UnityEngine.SceneManagement;
using TMPro; // Add me!!
public class PlayerController : MonoBehaviour
{
// Older code omitted for brevity
public SpriteRenderer sr;
public TextMeshProUGUI scoreText; // Add me!!
// Older code omitted for brevity
// Increases our score and updates the UI.
public void AddScore (int amount)
{
score += amount;
scoreText.text = "Score: " + score; // Add me!!
}
}
And here’s what the PlayerController script looks like right now:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
© 2024 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com
Create Your First 2D Game in Unity
Score Text
using UnityEngine.SceneManagement;
using TMPro;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
public float jumpForce;
public SpriteRenderer sr;
public TextMeshProUGUI scoreText;
public int score;
private bool isGrounded;
void FixedUpdate ()
{
// Get the horizontal move input.
float moveInput = Input.GetAxisRaw("Horizontal");
// Set our velocity.
rig.velocity = new Vector2(moveInput * moveSpeed, rig.velocity.y);
// Flip the sprite to face our moving direction.
if(rig.velocity.x > 0)
{
sr.flipX = true;
}
else if(rig.velocity.x < 0)
{
sr.flipX = false;
}
}
void Update ()
{
// If we press the jump button and we are grounded, then jump.
if(Input.GetKeyDown(KeyCode.UpArrow) && isGrounded)
{
isGrounded = false;
rig.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
// If we fall below -4 on the Y, then game over.
if(transform.position.y < -4)
{
GameOver();
}
}
private void OnCollisionEnter2D (Collision2D collision)
{
if(collision.GetContact(0).normal == Vector2.up)
{
isGrounded = true;
© 2024 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com
Create Your First 2D Game in Unity
Score Text
}
}
// Called when we get hit by an enemy or if we fall below the level.
public void GameOver ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
// Increases our score and updates the UI.
public void AddScore (int amount)
{
score += amount;
scoreText.text = "Score: " + score;
}
}
Ara, tornem a Unity per fer els següents canvis d'escena a la finestra de l'Inspector:
Definiu la propietat Player > Player Controller > Score Text per fer referència al ScoreText
objecte
Definiu la propietat ScoreText > TextMeshPro > Text a «Score: 0», per tenir el valor predeterminat correcte
Si comenceu el joc ara i recolliu diverses monedes, el text de la puntuació a la part superior hauria de canviar en conseqüència.
En aquesta lliçó, configurem la interfície d'usuari per a la nostra puntuació. A la següent lliçó, treballarem l' objecte End Flag.
En aquesta lliçó, crearem l' objecte del joc End Flag.
La bandera final serà l'objectiu del jugador al final de cada nivell. Si arribeu a aquesta bandera, el reproductor es mourà al següent nivell o a la pantalla de menú si no hi ha més nivells per completar.
Igual que amb els altres objectes, comencem per crear un objecte de joc buit per al nostre End Flag:
Crear un objecte de joc buit a la jerarquia Canvieu-li el nom a EndFlag
Col·loca l'objecte del joc EndFlag de manera que no es creui amb altres objectes
A continuació, afegirem un personatge al nostre EndFlag:
Selecciona l'sprite tiles_112 del full de personatges de les fitxes de la carpeta Sprites Arrossega'l a l' objecte del joc EndFlag de la Jerarquia
Canvieu el nom d'aquest objecte de joc de sprite a Sprite
Aneu a la finestra de l'Inspector i restabliu la propietat Sprite > Transforma > Position a (0, 0, 0)
Aquest és l'aspecte de la nostra bandera final ara:
A continuació, com amb la resta d'objectes, afegirem un col·lisionador:
Seleccioneu l' objecte EndFlag i aneu a la finestra Inspector Afegiu el component Box Collider 2D a l'objecte EndFlag
Activeu el commutador Is Trigger al component 2D del col·lisionador de caixes
Finalment, creem un script de controlador per al End Flag:
Crear un nou script d'EndFlag a la carpeta Scripts Afegir l' script EndFlag a l'objecte del joc EndFlag
Ara toca treballar en l' script EndFlag. En primer lloc, fem el següent:
Suprimiu les funcions Inici i Actualització, ja que no les necessitarem
Afegiu la funció OnTriggerEnter2D per detectar col·lisions amb el reproductor, com fèiem anteriorment En aquesta funció, comproveu si l'objecte amb el qual xoquem està etiquetat com a reproductor
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EndFlag : MonoBehaviour
{
private void OnTriggerEnter2D (Collider2D collision)
{
// Did the player hit us?
if(collision.CompareTag("Player"))
{
}
}
}
Després d'això, carregarem el següent nivell o el Menú. Afegim un parell de coses per a això:
Afegiu la biblioteca SceneManagement, de manera que podríem carregar escenes
Afegiu el camp public bool finalLevel, de manera que podríem establir si aquesta bandera es posiciona al nivell final
Afegiu el camp nextLevelName de cadena pública, de manera que podríem carregar el següent nivell d'una altra manera
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; // Add me!!
public class EndFlag : MonoBehaviour
{
public bool finalLevel; // Add us!!
public string nextLevelName;
// Existing code omitted for brevity
}
A continuació, completarem la funció OnTriggerEnter2D:
Si finalLevel és cert, carregueu l' escena Menu (que tindrà un índex de 0)
En cas contrari, carregueu l'escena especificada per la variable nextLevelName
private void OnTriggerEnter2D (Collider2D collision)
{
// Did the player hit us?
if(collision.CompareTag("Player"))
{
// If this is the final level, go to menu.
if(finalLevel == true)
{
SceneManager.LoadScene(0);
}
// Otherwise load up the next level.
else
{
SceneManager.LoadScene(nextLevelName);
}
}
}
Aquí teniu l'script complet d' EndFlag :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class EndFlag : MonoBehaviour
{
public bool finalLevel;
public string nextLevelName;
private void OnTriggerEnter2D (Collider2D collision)
{
// Did the player hit us?
if(collision.CompareTag("Player"))
{
// If this is the final level, go to menu.
if(finalLevel == true)
{
© 2024 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com
Create Your First 2D Game in Unity
End Flag
SceneManager.LoadScene(0);
}
// Otherwise load up the next level.
else
{
SceneManager.LoadScene(nextLevelName);
}
}
}
}
Ara, tornem a la Unitat. Com que ara mateix només tenim una escena, podem provar el nostre End Flag d'una sola manera: fer que carregui aquesta escena. Per tant, definim la propietat EndFlag > End Flag > Next Level Name a «Level1».
Després d'això, si inicieu el joc i aneu a una bandera, reiniciarà el nivell.
En aquesta lliçó, hem creat l' objecte End Flag, que ens permet connectar nivells entre si. A la propera lliçó, treballarem per crear un nou nivell i connectar-lo amb el primer.
En aquesta lliçó, analitzarem la creació de diversos nivells.
Abans de crear nous nivells, primer hem de configurar els nostres prefabricats. Ara mateix, tots els objectes del nostre nivell, com ara el jugador, l'enemic, la moneda i l'EndFlag, són només això: objectes. Haurem de tornar a crear-los manualment per tenir-los en altres nivells.
O bé, podem utilitzar el sistema Prefabricat, per guardar aquests objectes com a prefabricats i reutilitzar-los en els altres nivells. Els prefabricats són com plànols: podeu canviar un prefabricat de monedes i totes les instàncies de monedes obtindran aquests canvis automàticament.
Ara, fem el següent:
Crear una carpeta Prefabricats nova a la finestra Projecte
Si teniu diverses còpies de l' objecte Coin a la jerarquia, suprimiu totes les còpies i deixeu només l'objecte original de la moneda
Arrossega l' objecte Coin de la Jerarquia a la carpeta Prefabricats Arrossega l' objecte EndFlag de la Jerarquia a la carpeta Prefabricats Arrossega l' objecte Enemic de la Jerarquia a la carpeta Prefabricats
Abans de desar el jugador com a prefabricat, hem de fer una cosa més. Tenim la interfície d'usuari de puntuació al nostre nivell i seria convenient tenir el jugador i aquesta interfície d'usuari de puntuació com un sol prefabricat. Per tant, fem el següent:
A la Jerarquia, arrossegueu l' objecte Canvas a l' objecte Reproductor, de manera que el llenç sigui un objecte fill del reproductor
Arrossega l' objecte Reproductor de la Jerarquia a la carpeta Prefabricats de la finestra Projecte Ara teniu la interfície d' usuari Reproductor, Càmera i Puntuació desada com a prefabricada d'un sol jugador.
És possible que observeu que tots els nostres objectes prefabricats es van tornar blaus a la Jerarquia. Aquesta és una manera fàcil de veure quins objectes són les instàncies prefabricades i quins no.
El nivell 1 sembla una mica buit ara mateix : només tenim una moneda i només un enemic, i la bandera final està just al començament del nivell. Arreglem-ho.
En primer lloc, configurarem la nostra bandera final. El traslladarem al final del nivell.
A continuació, connectarem aquest indicador final al següent nivell (encara inexistent):
Seleccionar l'objecte EndFlag Vés a la finestra de l'Inspector
Definiu la propietat EndFlag > End Flag > Next Level Name a «Level2»
D'aquesta manera, un cop arribem al End Flag al Nivell 1, ens traslladarà al Nivell 2.
A continuació, creem un munt de monedes i les posem en algun lloc del nivell. Per crear una còpia de la
Objecte de moneda, seleccioneu-lo a la Jerarquia i, a continuació, feu clic a la tecla d' accés ràpid Ctrl+D per fer un duplicat.
Ara estem preparats per crear un segon nivell. Fem el següent:
Aneu a la carpeta Escenes
Creeu una escena nova anomenada Level2
A continuació, farem un petit truc per simplificar la nostra feina al segon nivell:
Seleccioneu l' objecte Quadrícula a la jerarquia del nivell 1 Premeu la tecla d'accés ràpid Ctrl+C per copiar l'objecte Obriu el nivell2 des de la carpeta Escenes
Premeu la tecla d'accés ràpid Ctrl+V per enganxar l' objecte Quadrícula a la jerarquia del nivell 2
Traieu l' objecte Càmera principal del Level2, ja que utilitzarem la càmera del reproductor
Ara teniu una graella inicial al vostre segon nivell.
A continuació, afegirem els nostres prefabricats al Level2:
Arrossega el prefabricat del reproductor de la carpeta Prefabricats al Level2 Arrossega el prefabricat Enemy de la carpeta Prefabricats al Level2 Arrossega el prefabricat EndFlag de la carpeta Prefabricats al Level2 Arrossega el prefabricat Coin de la carpeta Prefabricats al Level2
De moment, podeu col·locar aquests objectes aleatòriament, ja que de totes maneres reconstruirem aquest nivell.
No volem que el nostre Nivell 2 sigui el mateix que el Nivell 1. Per tant, reconstruïm-lo a través de l' objecte Grid > Tilemap com fèiem abans. Podeu esborrar tot el nivell amb l'eina Esborrador i construir-lo des de zero.
Com una mica de repte, volem que construeixis aquest nivell tu mateix. Podeu utilitzar altres rajoles, com ara rajoles de neu, per fer un nivell a partir d'un bioma diferent.
Aquest és el nivell que vam construir:
Finalment, també hem de configurar la bandera final en aquest nivell. En aquesta lliçó, farem del Level2 el nivell final. Per descomptat, podeu crear més nivells vosaltres mateixos, només assegureu-vos de connectar-los a través dels EndFlags.
Això és el que farem perquè el Level2 sigui el nivell final:
Seleccionar l'objecte EndFlag Vés a la finestra de l'Inspector
Activeu el commutador EndFlag > End Flag > Final Level
Ara, un cop arribeu a la bandera final en aquest nivell, us carregarà la primera escena.
Perquè la nostra càrrega d'escena funcioni, hem d'afegir el nivell acabat de crear a la configuració de compilació. Això és el que farem:
Premeu la tecla d' accés ràpid Ctrl+Maj+B per obrir la finestra Configuració de compilació
Arrossegueu el recurs Level2 de la carpeta Escenes a la llista Escenes en construcció de la finestra Configuració de la compilació
Ara, anem a provar la connexió dels nostres nivells:
Obriu l'escena Level1
Comenceu el de Level1 i arribeu-hi a l' EndFlag El Level2 hauria de començar
Arribeu a l' EndFlag al Level2
El Level1 hauria de començar de nou, ja que és la primera escena de les escenes que construeixen l'ordre ara
En aquesta lliçó, vam crear el segon nivell. A la següent lliçó, treballarem l' escena del menú i la farem carregar després de l'últim nivell.
En aquesta lliçó, configurarem l' escena Menú.
En primer lloc, anem a la carpeta Escenes i creem una nova escena anomenada Menú.
A continuació, obrirem l' escena Menú. Si aneu a la visualització Joc, notareu que té un color de fons bastant suau.
Canviem aquest color:
Seleccioneu l'objecte de joc Càmera principal
Vés a la finestra de l'inspector
Configureu la càmera > el fons a un color agradable. Estem utilitzant un color blau amb el valor RGB de (28, 136, 248)
Ara tenim un color de fons més agradable a la nostra escena del menú.
A continuació, començarem a crear la interfície d'usuari. En primer lloc, creem un nou objecte Canvas.
A continuació, crearem un text de títol:
Afegiu un nou objecte TextMeshPro com a fill del llenç
Anomena'l Títol
Després d'això, configurarem el component Títol > TextMeshPro a la finestra de l'Inspector de la manera següent:
Definiu el text a «El meu joc 2D» Activeu l' estil de lletra en negreta
Ajusteu la mida de la lletra a 44
Habilitar l' alineació del centre
Finalment, ajustem la mida i la posició del títol a la vista Escena, de manera que tot el text encaixa en una línia i el text en si es col·loca una mica per sobre del centre de la pantalla.
A continuació, creem el botó Reproduir:
Creeu un botó TextMeshPro nou com a fill de l' objecte Canvas Anomeneu-lo PlayButton
Establiu el text del botó de reproducció > el component Text > TextMeshPro a «Reproduir» Canvieu la mida i col·loqueu el botó de reproducció com vulgueu
A continuació, crearem el botó Surt:
Seleccioneu el botó PlayButton i premeu la tecla d' accés ràpid Ctrl+D per duplicar-la Canvieu el nom del botó duplicat a SurButton
Canvieu el text del botó Surt per sortir-ne
Col·loqueu el botó de sortida a sota del botó de reproducció
Ara tenim tots els elements de la interfície d'usuari del menú creats.
Perquè els nostres botons funcionin, hem de connectar-los a algun codi. Fem el següent:
Crear un script de menú nou a la carpeta Scripts Adjuntar l' script Menu a l'objecte Canvas
Ara, obrim l' script de menú i fem primer el següent:
Suprimiu les funcions Inici i Actualització, ja que no les necessitarem
Afegiu la biblioteca SceneManagement, ja que la necessitarem per carregar les escenes
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; // Add me!!
public class Menu : MonoBehaviour
{
}
A continuació, afegirem la funció OnPlayButton. Aquesta funció hauria de carregar una escena amb l'índex de compilació de
1.
public void OnPlayButton ()
{
SceneManager.LoadScene(1);
}
A continuació, afegirem la funció OnQuitButton, que farà que el joc es tanqui.
public void OnQuitButton ()
{
Application.Quit();
}
Aquí teniu l'script complet del menú :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Menu : MonoBehaviour
{
// Called when we click the "Play" button.
public void OnPlayButton ()
{
SceneManager.LoadScene(1);
}
// Called when we click the "Quit" button.
public void OnQuitButton ()
{
Application.Quit();
}
}
Ara, tornem a Unity i connectem els nostres botons a l' script Menú. En primer lloc, connectem el
PlayButton a la seva funció:
Aneu al component Botó de reproducció > botó a la finestra de l'Inspector
A la llista d'esdeveniments OnClick, afegiu una entrada nova fent clic al botó del signe més Arrossegueu l' objecte del joc Canvas al camp Objecte d'aquesta entrada nova
Al camp Funció, seleccioneu la funció Menú > OnPlayButton Ara, un cop premut el botó de reproducció, trucarà a la funció OnPlayButton.
De manera similar, connectem l' esdeveniment QuitButton > Button > OnClick al Canvas > Menu
> funció OnQuitButton .
Finalment, afegim l' escena del menú a la configuració de compilació:
Premeu el botó Ctrl+Maj+B per obrir la finestra Configuració de compilació
Feu clic al botó Afegeix escenes obertes per afegir l' escena del menú a la llista Col·loqueu l' escena del menú per ser la primera d'aquesta llista
Ara podem provar el nostre joc:
Inicieu el joc des de l'escena Menú
Feu clic al botó Reprodueix per iniciar el primer nivell
Arribeu al End Flag al primer nivell per passar al segon nivell
Arribeu al senyal final del segon nivell per tornar al menú
En aquesta lliçó, vam crear l' escena del menú i vam connectar tots els nostres nivells junts. A la propera lliçó, farem alguns retocs finals al nostre PlayerController.
En aquesta lliçó, solucionarem alguns problemes que té el nostre PlayerController .
El primer problema que podeu notar és que quan salteu a la paret, el jugador es queda atrapat en ella, mentre premeu la tecla de fletxa esquerra o dreta. Això passa perquè per defecte els objectes tenen una fricció molt alta.
Per canviar la fricció del jugador, primer haurem de crear un nou material de física:
Feu clic amb el botó dret a la carpeta Recursos de la visualització Projecte
Seleccioneu l' opció Crea > 2D > Material de física 2D al menú contextual Anomeneu aquest material NoFriction
A la finestra de l'Inspector, definiu la propietat NoFriction > Friction a 0
A continuació, aplicarem aquest material al prefabricat del reproductor :
Feu doble clic al reproductor prefabricat a la carpeta Prefabricats per obrir-lo
Definiu el reproductor > la propietat Rigidbody 2D > Material per fer referència al material NoFriction
Ara el vostre jugador hauria de lliscar per les parets en lloc d'enganxar-s'hi.
El segon problema que abordarem aquí és que de vegades no es pot saltar. Això passa a causa de la nostra implementació de la comprovació de terra a l' script PlayerController. En ell, comprovem si la normal de la col·lisió és igual al Vector2.up, que és (0, 1).
private void OnCollisionEnter2D (Collision2D collision)
{
if(collision.GetContact(0).normal == Vector2.up)
{
isGrounded = true;
}
}
El cas és que el (0, 1) és un valor bastant precís, i el vector normal podria tenir una mica de desviació d'ell. El fet de no ser igual al Vector2.up fa que la nostra comprovació de terra falli quan no ho hauria de fer.
Per solucionar-ho, utilitzarem la funció Vector2.Dot. Aquesta funció pren dos vectors i comprova si apunten en la mateixa direcció. Com menys angle hi hagi entre aquests vectors, més gran serà el resultat de la funció Dot.
Si la funció Dot de la normal de la col·lisió i el vector cap amunt és més gran que 0,8, estan bastant a prop l'un de l'altre, i el més probable és que hàgim tocat terra.
private void OnCollisionEnter2D (Collision2D collision)
{
if(Vector2.Dot(collision.GetContact(0).normal, Vector2.up) > 0.8f)
{
isGrounded = true;
}
}
Després d'actualitzar la funció OnCollisionEnter2D, s'hauria de solucionar el problema de salt. Això és el que sembla l'script complet de PlayerController:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using TMPro;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
public float jumpForce;
public SpriteRenderer sr;
public TextMeshProUGUI scoreText;
public int score;
private bool isGrounded;
void FixedUpdate ()
{
// Get the horizontal move input.
float moveInput = Input.GetAxisRaw("Horizontal");
// Set our velocity.
rig.velocity = new Vector2(moveInput * moveSpeed, rig.velocity.y);
// Flip the sprite to face our moving direction.
if(rig.velocity.x > 0)
{
sr.flipX = true;
}
else if(rig.velocity.x < 0)
{
sr.flipX = false;
}
}
void Update ()
{
// If we press the jump button and we are grounded, then jump.
if(Input.GetKeyDown(KeyCode.UpArrow) && isGrounded == true)
{
isGrounded = false;
rig.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
// If we fall below -4 on the Y, then game over.
if(transform.position.y < -4)
{
GameOver();
}
}
private void OnCollisionEnter2D (Collision2D collision)
{
// OLD: if(collision.GetContact(0) == Vector2.up)
if(Vector2.Dot(collision.GetContact(0).normal, Vector2.up) > 0.8f)
{
isGrounded = true;
}
}
// Called when we get hit by an enemy or if we fall below the level.
public void GameOver ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
// Increases our score and updates the UI.
public void AddScore (int amount)
{
score += amount;
scoreText.text = "Score: " + score;
}
}
En aquesta lliçó final, vam solucionar els dos problemes que teníem amb el nostre PlayerController.
Si voleu que la puntuació del nivell 1 passi al següent nivell, podem aconseguir-ho amb una actualització ràpida de la variable de puntuació i de la classe PlayerController.
En primer lloc, declarem la variable puntuació com a estàtica. És a dir, a nivell de classe, tots els objectes compartiran una única còpia de la variable i el seu valor.
public class PlayerController : MonoBehaviour
{
public static int score;
...
Ara, simplement afegirem el mètode d' esdeveniment del missatge del cicle de vida Unity Start() per assegurar-nos que la interfície d'usuari de puntuació s'estableix cada vegada que es carrega el PlayerController.
private void Start()
{
scoreText.text = "Score: " + score;
};
I ja està!
Conclusió
En aquesta lliçó, podeu trobar el codi font complet del projecte utilitzat dins del curs. No dubteu a utilitzar aquesta lliçó segons sigui necessari , ja sigui per ajudar-vos a depurar el vostre codi, utilitzar-lo com a referència més endavant o ampliar el projecte per practicar les vostres habilitats.
També podeu descarregar tots els fitxers del projecte des de la pestanya Fitxers del curs mitjançant els fitxers del projecte o el resum PDF descarregable.
PlayerController.cs s'encarrega de la nostra lògica de reproductors 2D. Utilitzant el RigidBody, controla la nostra capacitat per moure el jugador cap a l'esquerra i la dreta, i la nostra capacitat per saltar correctament. Aquest guió del jugador també conté lògica per afegir a la partitura i lògica per tornar a carregar l'escena (desencadenant una partida per sobre) quan colpegem un enemic o caiem de la vora del nivell.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using TMPro;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public Rigidbody2D rig;
public float jumpForce;
public SpriteRenderer sr;
public TextMeshProUGUI scoreText;
public int score;
private bool isGrounded;
void FixedUpdate ()
{
// Get the horizontal move input.
float moveInput = Input.GetAxisRaw("Horizontal");
// Set our velocity.
rig.velocity = new Vector2(moveInput * moveSpeed, rig.velocity.y);
// Flip the sprite to face our moving direction.
if(rig.velocity.x > 0)
{
sr.flipX = true;
}
else if(rig.velocity.x < 0)
{
sr.flipX = false;
}
}
void Update ()
{
// If we press the jump button and we are grounded, then jump.
if(Input.GetKeyDown(KeyCode.UpArrow) && isGrounded == true)
{
isGrounded = false;
rig.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
// If we fall below -4 on the Y, then game over.
if(transform.position.y < -4)
{
GameOver();
}
}
private void OnCollisionEnter2D (Collision2D collision)
{
// OLD: if(collision.GetContact(0) == Vector2.up)
if(Vector2.Dot(collision.GetContact(0).normal, Vector2.up) > 0.8f)
{
isGrounded = true;
}
}
// Called when we get hit by an enemy or if we fall below the level.
public void GameOver ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
// Increases our score and updates the UI.
public void AddScore (int amount)
{
score += amount;
scoreText.text = "Score: " + score;
}
}
Enemy.cs controla com es mouen els enemics. En donar-los una posició inicial i d'objectiu, els mou endavant i enrere entre dos punts donats. L'enemic també detecta quan els jugadors xoquen amb ell, i activa el joc del jugador sobre la lògica quan es produeix una col·lisió.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
public float moveSpeed;
public Vector3 moveOffset;
private Vector3 startPos;
private Vector3 targetPos;
// Start is called before the first frame update
void Start()
{
startPos = transform.position;
targetPos = startPos;
}
// Update is called once per frame
void Update()
{
// Move towards the target position.
transform.position = Vector3.MoveTowards(transform.position, targetPos, moveS
peed * Time.deltaTime);
// Are we at the target position?
if(transform.position == targetPos)
{
// Is our target pos our start pos? If so, set it to be the other one.
if(targetPos == startPos)
{
targetPos = startPos + moveOffset;
}
// Otherwise, do the opposite.
else
{
targetPos = startPos;
}
}
}
private void OnTriggerEnter2D (Collider2D collision)
{
// Did the player hit us?
if(collision.CompareTag("Player"))
{
// Trigger the game over state on the player.
collision.GetComponent<PlayerController>().GameOver();
}
}
}
Coin.cs conté la lògica per controlar l'animació bobbing dels nostres objectes de monedes. També li diu al jugador que s'afegeixi a la nostra puntuació i destrueix l'objecte de la moneda quan el jugador xoca amb la moneda.
using System.Collections;
using System.Collections.Generic;
© 2024 Zenva Pty Ltd. All rights reserved. https://academy.zenva.com
Create Your First 2D Game in Unity
Full Source Code - First 2D Unity Game
using UnityEngine;
public class Coin : MonoBehaviour
{
public int scoreToGive;
public float bobHeight;
public float bobSpeed;
private float startYPos;
void Start ()
{
startYPos = transform.position.y;
}
void Update ()
{
// Bob up and down.
float newY = startYPos + (Mathf.Sin(Time.time * bobSpeed) * bobHeight);
transform.position = new Vector3(transform.position.x, newY, 0);
}
private void OnTriggerEnter2D (Collider2D collision)
{
// Did the player hit us?
if(collision.CompareTag("Player"))
{
// Increase their score, then destroy our GameObject.
collision.GetComponent<PlayerController>().AddScore(scoreToGive);
Destroy(gameObject);
}
}
}
EndFlag.cs controla les nostres banderes finals que representen l'objectiu final dels nostres nivells. Quan el nostre jugador xoca amb les banderes finals, aquest script carrega el següent nivell (si n'hi ha) o carrega el primer nivell.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class EndFlag : MonoBehaviour
{
public bool finalLevel;
public string nextLevelName;
private void OnTriggerEnter2D (Collider2D collision)
{
// Did the player hit us?
if(collision.CompareTag("Player"))
{
// If this is the final level, go to menu.
if(finalLevel == true)
{
SceneManager.LoadScene(0);
}
// Otherwise load up the next level.
else
{
SceneManager.LoadScene(nextLevelName);
}
}
}
}
Menu.cs ajuda a controlar el nostre senzill menú. Quan el jugador prem el botó Reproduir, carrega els primers nivells de plataformes. Quan premen el botó Surt, abandona l'aplicació (tingueu en compte que l'abandonament de l'aplicació no funciona a Unity Editor , només a les compilacions de la plataforma).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Menu : MonoBehaviour
{
// Called when we click the "Play" button.
public void OnPlayButton ()
{
SceneManager.LoadScene(1);
}
// Called when we click the "Quit" button.
public void OnQuitButton ()
{
Application.Quit();
}
}