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!

Com instal·lar 2022 LTS

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.

Disseny de jocs

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

Jugador

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

Enemics

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.

Bandera final

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.

Monedes

Després, hi ha les monedes. La recollida de monedes augmentarà la puntuació del jugador, que es mostrarà a la interfície d'usuari.

Bucle de joc

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.

Creació d'un nou projecte

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.

Importació de The Sprites

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 .

Configuració dels 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.

L'sprite del 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.

Els components del jugador

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:

El desplaçament és (0, 0,64)

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.

Addició d'una plataforma

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.

Moure el jugador

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);

}

Actualització de l'escena

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.

Fixació de la velocitat

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.

Implementació del salt

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);

 }

 }

}

Actualització de l'escena

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:

El controlador del jugador > la força de salt és 10 Rigidbody 2D > l'escala de gravetat és 2

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.

Implementació de la comprovació de 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.

La direcció de la mirada de Sprite

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.

Connexió de la càmera al reproductor

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.

Creació de la paleta de rajoles

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.

Dibuix amb rajoles

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.

El Col·lisionador Tilemap

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.

Edifici A Level

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.

L'objecte del joc 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  

El guió de l'enemic

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

Inici Pos

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;

 }

 }

 }

Actualització de l'escena

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.

La funció Game Over

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);

 }

}

El joc de tardor sobre el repte

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.

GAME OVER per caiguda

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);

 }

}

L'enemic va colpejar el joc

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.

La puntuació del jugador

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

 }

}

L'objecte del joc de la moneda

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

El guió de la moneda

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

Jugador:

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 .

Augmentar la puntuació del jugador

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);

 }

}

Actualització de l'escena

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 .

L'animació de la moneda

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.

Creació d'un llenç

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.

Addició d'un text

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.

Configuració de l'objecte de text

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.

Actualització de la interfície d'usuari de puntuació

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;

 }

}

Actualització de l'escena

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.

L'objecte del joc End Flag

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

L'script de la bandera final

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);

 }

 }

 }

}

Prova de la bandera final

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.

Creació dels Prefabricats

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.

Retocs finals al nivell 1

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.

Creació del nivell 2

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.

Actualització de la configuració de compilació

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ú.

Creació de l'escena del 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ú.

La interfície d'usuari 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.

L'script del menú

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();

 }

}

Actualització de l'escena

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 .

Actualització de la configuració de compilació

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 .

La fricció per col·lisió de paret

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.

L'error de salt

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.

Opcional

Portar la puntuació entre nivells

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à!

Crea el teu primer joc 2D a Unity

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

Es troba a Project/Assets/Scripts

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

Es troba a Project/Assets/Scripts

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

Es troba a Project/Assets/Scripts

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

Es troba a Project/Assets/Scripts

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

Es troba a Project/Assets/Scripts

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();

 }

}