În această serie de tutorial, vă vom arăta cum să recreați jocul clasic Arkanoid (sau Breakout) în Unity, utilizând uneltele 2D native ale Unity. În fiecare post, ne vom concentra pe o anumită parte a jocului; în acest post, vom obține cu zbaturi și mingea se mișcă.
În tutorialul anterior, ați configurat proiectul, ați importat materialele și ați pregătit scena pentru primul nivel. Dacă nu ați finalizat tutorialul anterior, vă recomandăm să faceți acest lucru înainte de a începe acest tutorial.
Aruncați o privire la acest demo pentru a vedea ce vrem să urmărim în întreaga serie:
Iată ce vom avea la sfârșitul acestei părți:
Aveți deja paleta jucătorului în interfață; acum trebuie să interacționați cu el. O veți muta într-un mod orizontal, la stânga și la dreapta. Pentru a crea această mișcare prin introducere, trebuie să creați o scenariu.
Scripturile sunt fragmente de cod de programare care fac anumite sarcini. Unitatea poate gestiona trei limbi de programare: Boo, C # și JavaScript. Toate scripturile create în acest tutorial vor fi scrise în C # (dar nu ezitați să le implementați într-o altă limbă, dacă preferați).
Pentru a crea un script, mergeți la dvs. Proiect selectați dosarul Scripturi, și faceți clic dreapta pe el pentru a afișa un meniu. Selectați Creați> Script C #. Un nou fișier numit NewBehaviourScript
va aparea; redenumiți-o PlayerScript
. În Inspector veți vedea conținutul scriptului însuși.
Faceți dublu clic pe script pentru al edita. IDE-ul MonoDevelop se va deschide în mod implicit, dar puteți configura un alt editor de coduri pentru al deschide dacă preferați.
utilizând UnityEngine; utilizând System.Collections; public class NewBehaviourScript: MonoBehavior // Folosiți acest lucru pentru inițializare void Start () // Actualizarea se numește o dată pe cadru void Update ()
Toate scripturile Unity vor avea în mod implicit două metode:
Start()
: utilizat pentru inițializarea oricăror variabile sau parametri de care avem nevoie în codul nostru.Actualizați()
: numit fiecare cadru al jocului și folosit pentru a actualiza starea jocului.Pentru a muta jucătorul, aveți nevoie de două informații:
Astfel, creați două variabile (variabile de clasă globală) pentru a stoca acele informații:
jucator public floatVelocity; privat Vector3 playerPosition;
După cum probabil ați observat, playerVelocity
este o variabilă publică, în timp ce pozitia jucatorului
este privat. De ce am făcut asta? Ei bine, Unitatea vă permite să modificați valorile variabilelor publice în interiorul editorului fără a fi nevoie să modificați codul real; acest lucru este foarte util atunci când aveți parametri care trebuie să fie ajustați în mod continuu. Viteza este unul din acele cazuri, așa că facem publice.
Salvați scriptul (în MonoDevelop) și mutați din nou editorul Unity.
Acum ai scenariul; trebuie doar să o atribuiți obiectului cu palete al jucătorului. Selectați paleta din Ierarhie tab și în Inspector, clic Adăugați componenta. Acum, introduceți numele scriptului pe care tocmai l-ați salvat și adăugați-l la obiectul jocului.
Pentru mai multe informații despre conceptul de Componente și despre modul în care acestea lucrează în unitate, consultați Unitatea: Acum gândiți la componente.
Un alt mod de a adăuga script-ul la component ar fi să-l trageți din folderul său și să-l aruncați peste Adăugați componenta zonă. Ar trebui să vezi ceva de genul ăsta în tine Inspector:
După cum puteți vedea, de când am părăsit playerVelocity
publicul variabil, puteți să-i setați acum valoarea în editor. Pentru moment, setați valoarea la 0.3
și reveniți la cod.
Veți inițializa acum pozitia jucatorului
. Pentru a face acest lucru, trebuie să accesați poziția obiectului jocului în scriptul start
metodă:
// Folosiți acest lucru pentru inițializare void Start () // obțineți poziția inițială a game player objectPosition = gameObject.transform.position;
Acum am definit paleta iniţială poziția și viteza, dar trebuie să-l mutăm. Pentru aceasta, vom edita Actualizați
metodă.
Din moment ce dorim doar să obligem să ne mișcăm orizontal, putem folosi GetAxis
metodă a Intrare
pentru a afla în ce direcție intrarea jucătorului este îndreptată de-a lungul axei orizontale (-1
pentru stânga, +1
pentru dreapta), multiplicați această valoare cu viteza, adăugați această valoare la poziția curentă X a paletei și actualizați actualul pozitia jucatorului
a se potrivi.
În timp ce avem de-a face cu intrarea, vrem să ne asigurăm că jocul iese atunci când jucătorul apasă Esc cheie.
Fragmentul complet este de mai jos:
utilizând UnityEngine; utilizând System.Collections; public class PlayerScript: MonoBehour public float playerVelocity; privat Vector3 playerPosition; // Folosiți acest lucru pentru inițializare void Start () // obțineți poziția inițială a game player objectPosition = gameObject.transform.position; // Actualizarea se numește o dată pe cadru void Update () // mișcare orizontală playerPosition.x + = Input.GetAxis ("Orizontal") * playerVelocity; // părăsiți jocul dacă (Input.GetKeyDown (KeyCode.Escape)) Application.Quit (); // actualizarea obiectului de joc transform transformation.position = playerPosition;
Salvați scenariul și reveniți la editorul Unity. Acum apăsați Joaca și încercați să mutați jucătorul cu săgețile stânga și dreapta.
Probabil ați observat că cuțitul se poate mișca în afara nivelului. Acest lucru se întâmplă deoarece nu există limite definite pentru zona de joc.
Pentru a crea granița, creați mai întâi o altă variabilă publică - apelați-o limite
.
Această variabilă va stoca poziția X maximă la care se poate deplasa paleta. De vreme ce vom construi nivelul într-o formă simetrică în jurul poziției (0, 0, 0)
, aceasta înseamnă că valoarea limită absolută va fi aceeași atât pentru pozitivul cât și pentru negativul X..
Pentru a nu lăsa jucătorul să treacă granița, vom adăuga câteva dacă
Condiții. Practic, vom spune că dacă valoarea x a poziției este mai mare decât valoarea limită, atunci valoarea x va fi setată egală cu limita. În acest fel, ne asigurăm că paleta nu poate părăsi zona de joc. Codul relevant este de mai jos:
utilizând UnityEngine; utilizând System.Collections; public class PlayerScript: MonoBehour public float playerVelocity; privat Vector3 playerPosition; limita flotă publică; // Folosiți acest lucru pentru inițializare void Start () // obțineți poziția inițială a game player objectPosition = gameObject.transform.position; // Actualizarea se numește o dată pe cadru void Update () // mișcare orizontală playerPosition.x + = Input.GetAxis ("Orizontal") * playerVelocity; // părăsiți jocul dacă (Input.GetKeyDown (KeyCode.Escape)) Application.Quit (); // actualizarea obiectului de joc transform transformation.position = playerPosition; // limitele dacă (playerPosition.x < -boundary) transform.position = new Vector3 (-boundary, playerPosition.y, playerPosition.z); if (playerPosition.x > limită) transform.position = Vector3 nou (graniță, playerPosition.y, playerPosition.z);
Acum, du-te înapoi la editor și de a elabora cea mai bună valoare pentru limite
. Prin tragerea poziției paletei pe axa X, puteți vedea că este valoarea perfectă 5.46
(cel puțin în proiectul nostru).
În Inspector, resetați valoarea X a poziției paletei la 0
, și intrare 5.46
pe Limite parametru în cadrul Player Script component.
presa Joaca în editor. Acum puteți deplasa paleta, dar numai în zona de joc.
În acest joc special, trebuie să creăm proprietăți fizice pentru trei componente: paleta, mingea și pereții. Deoarece creăm un joc 2D, vom folosi și aplica 2D acceleratoare. (Un collider este un tip particular de componentă care permite obiectelor lor asociate să reacționeze la alte colizoare.)
Începeți prin adăugarea unui collider la paleta noastră. În Ierarhie, selectați obiectul paletei noastre. Deplasați-vă la Inspector, clic Adăugați componenta și tip Collider
. După cum puteți vedea în ecranul de mai jos, sunt disponibile mai multe tipuri de agenți de coliziune pentru a le utiliza. Fiecare colizoare individuală are proprietăți specifice care seamănă cu obiectul asociat.
Deoarece playerul are un format dreptunghiular, vom folosi Box Collider 2D. Selectați-l și componenta va fi adăugată automat în obiectul player. Valorile pentru dimensiune și poziția centrală a colizorului sunt deja definite; aceste valori implicite vor funcționa pentru dvs., deci nu trebuie să le schimbați.
Faceți același proces pentru cele trei bare și bloc. (Ierarhia> Inspector> Adăugați componenta> Box Collider 2D).
Toate obiectele de joc au acum colizoare, se așteaptă la minge. Deoarece mingea are o formă diferită, va trebui să utilizați un coliziune diferită. Selectați-l și, în Inspector , adăugați componenta Circle Collider 2D.
Circle Collider 2D este similar cu Box Collider, cu excepția faptului că în loc de mărimea parametru care definește lățimea și înălțimea casetei, are un a Rază parametru care definește raza cercului.
Pentru a face mingea sări, trebuie să creăm un material fizic și să-l atașăm la minge. Unitatea are deja acel material specific creat, deci trebuie doar să-l adăugăm.
Pe Proiect , creați un nou dosar în interiorul activ și denumiți-o Fizică
. Selectați acest dosar, faceți clic pe Crea, și alegeți Physics2D Material. Denumiți noul material fizic BallPhysicsMaterial
.
Materialul are doi parametri: Frecare și bounciness. Din moment ce doriți un comportament pur bouncy, trebuie să modificați valorile în consecință: 0
pentru Frecare, 1
pentru bounciness.
Acum că aveți materialul gata, aplicați-l pe minge. Selectați obiectul joc de minge pe Ierarhie și treceți la Inspector. Dacă te uiți mai atent la tine Circle Collider 2D, veți observa că această componentă are un parametru numit Material; aici, puteți atașa orice material fizic pe care doriți să-l obiect.
Pentru a atașa BallPhysicsMaterial, trebuie doar să o selectați și să o trageți în Material parametru de pe coliziune.
Nota editorului: Această captură de ecran afișează a Box Collider 2D, dar ar trebui să fie a Circle Collider 2D.Pentru ca mingea să se miște sub controlul fizicii, trebuie să adăugăm un ultim lucru: o componentă rigidă. Selectați obiectul mingii și adăugați componenta RigidBody 2D. Această componentă are mai mulți parametri care pot fi ajustați. Deoarece mingea se va mișca doar prin sărituri, ar trebui să schimbați Scală gravitațională parametru de la 1
la 0
-în acest fel, ne asigurăm că mingea nu este afectată de gravitate. Restul parametrilor pot fi lăsați în mod prestabilit:
Bilele vor fi complet dinamice, așa că trebuie să creăm un script personalizat pentru acest comportament.
Creați un script nou (vom folosi din nou C #) și îl vom numi BallScript
. Atribuiți acest script nou obiectului cu bile (Ierarhia> Inspector> Adăugați componenta).
Acum, analizați regulile și proprietățile mingii, înainte de a le codifica în script:
Pe baza acestor informații, vom crea mai întâi variabilele globale ballIsActive
, ballPosition
, și ballInitialForce
.
private bool ballIsActive; private Vector ballPosition; private Vector2 ballInitialForce;
Acum, când ați setat variabilele, ar trebui să inițializați obiectul jocului. În start
metodă, ar trebui:
Iată cum arată:
void Start () // a crea forța de forțăInitialForce = Vector2 nou (100.0f, 300.0f); // setat la inactive ballIsActive = false; // balon pozitionare minge Pozitie = pozitie transforma;
Aici, aplicăm o forță de 300
de-a lungul axei Y pentru a face mingea să se miște în sus și 100
de-a lungul axei X pentru a face mingea să se miște în diagonală în loc de direct în sus. În acest fel, forțați jucătorul să deplaseze poziția paletei.
În Actualizați
, vom defini comportamentul mingii Să abordăm acest caz după caz.
În primul rând, trebuie să ne ocupăm de intrarea utilizatorului; vom folosi setările implicite A sari
butonul Unity as și cheia de acțiune. Cheia asociată cu A sari
pot fi modificate, dar implicit este Spaţiu bara de pe tastatură.
void Update () // verificați pentru intrarea utilizatorului dacă (Input.GetButtonDown ("Jump") == true)
Următorul lucru pe care trebuie să-l faceți este să verificați starea mingii, deoarece cheia de acțiune ar trebui să funcționeze numai atunci când mingea este inactivă:
void Update () // verificați dacă utilizatorul a introdus (Input.GetButtonDown ("Jump") == true) // verificați dacă este prima redare dacă (! ballIsActive)
Să presupunem că acesta este la începutul jocului, așa că trebuie să aplicăm o forță mingii și să o punem activă. Noul Actualizați
metoda ar trebui să arate ca:
void Actualizare () // verifica daca userul a introdus daca (Input.GetButtonDown ("Jump") == true) // verifica daca este primul joc daca (! ballIsActive) // adauga o forta rigidbody2D.AddForce (ballInitialForce ); / / set minge activ ballIsActive =! ballIsActive;
Acum, Joaca proiectul dvs. și de testare a A sari
acțiune; veți observa că mingea se împinge în sus și începe să bată în jurul valorii de exact cum ar trebui. Cu toate acestea, veți observa de asemenea că mingea nu urmărește poziția paletei atunci când este inactivă. Opreste jocul si haide sa schimbam asta.
În Actualizați
, trebuie să verificăm starea mingii și, dacă mingea este inactivă, trebuie să ne asigurăm că valoarea X a mingii este aceeași cu valoarea X a paletei.
Ah, dar cum putem accesa poziția jucătorului dacă se află într-un alt obiect de joc? Simplu: doar creăm o variabilă de obiect de joc și stocăm o referință la obiectul paletei din ea. Deci, adăugați obiectul paletei ca o variabilă globală publică de tip GameObject
:
private bool ballIsActive; private Vector ballPosition; private Vector2 ballInitialForce; // GameObject public GameObject playerObject;
Înapoi la Actualizați
metodă. Vom verifica starea mingii și referința paletei. Dacă starea este inactivă și obiectul paletei nu este nul (adică avem o referință la ea), mingea ar trebui să urmeze poziția paletei. Complet Actualizați
este acum:
void Actualizare () // verifica daca userul a introdus daca (Input.GetButtonDown ("Jump") == true) // verifica daca este primul joc daca (! ballIsActive) // adauga o forta rigidbody2D.AddForce (ballInitialForce ); / / set minge activ ballIsActive =! ballIsActive; dacă (! ballIsActive && playerObject! = null) // primiți și utilizați poziția jucătorului ballPosition.x = playerObject.transform.position.x; // aplicați poziția jucătorului X la balonul transform.position = ballPosition;
Salvați scriptul și reveniți la editor. După cum probabil ați observat, referința paletei este publică, ceea ce înseamnă că o veți transmite editorului. Pe Ierarhie selectați bara. În Inspector, veți observa Obiectul jucătorului parametru în scriptul nostru este în prezent Nici unul
.
Pentru a face acest lucru o referință la obiectul jucătorului cu zbaturi, pur și simplu trageți și plasați obiectul jocului cu zbaturi din Ierarhie la Obiectul jucătorului parametru în scenariu.
Apasă pe Joaca buton, și testați-vă jocul. Veți vedea acum că mingea va urma jucătorul înainte de A sari
este apăsată tasta.
Există încă un lucru pe care trebuie să-l faceți pentru a termina scenariul. După cum probabil ați observat, dacă jucătorul nu prinde mingea, acesta va cădea din set și jocul nu va fi resetat. Să modificăm Actualizați
metodă de a repara acest lucru.
Vom verifica dacă mingea este activă și dacă poziția ei Y este mai mică decât -6
. Dacă da, vom seta mingea în poziția inactivă și vom reseta poziția mingii în poziția jucătorului. Fragmentul pentru care arată astfel:
dacă (ballIsActive && transform.position.y < -6) ballIsActive = !ballIsActive; ballPosition.x = playerObject.transform.position.x; ballPosition.y = -4.2f; transform.position = ballPosition;
Dacă salvați scriptul și verificați editorul, puteți observa că de fiecare dată când mingea cade din ecran, poziția mingii este repoziționată în poziția jucătorului și setată la inactivitate. Cu toate acestea, dacă începeți să jucați veți observa un comportament ciudat De fiecare dată când mingea cade, data viitoare când apăsați tasta de acțiune crește viteza acesteia. De ce este asta?
Amintiți-vă că adăugăm o forță la minge când se lansează - deci, de fiecare dată când resetați jocul, continuați să adăugați forță corpului rigid, făcând jocul greu sănătos doar după câteva încercări. Deci, întrebarea este, cum putem rezolva acest lucru?
Pentru a menține aceeași forță globală aplicată, trebuie să vă asigurați că eliminați toate forțele aplicate mingii de fiecare dată când o resetați. Pentru a face acest lucru, putem activa pur și simplu Este cinematică
parametru de fiecare dată când mingea se oprește și dezactivați-o când începe jocul. Acest parametru determină dacă mingea este afectată sau nu de fizică, iar dezactivarea acesteia va asigura că toate forțele aplicate înainte vor dispărea.
Adăugați încă două linii la dvs. Actualizați
metodă de a face acest lucru:
rigidbody2D.isKinematic = false
înainte de adăugarea forței șirigidbody2D.isKinematic = adevărat
când vrem ca bila să înceapă din nou să se miște.În cele din urmă, completă Actualizați
metoda ar trebui să arate astfel:
clasa publica BallScript: MonoBehavior private bool ballIsActive; private Vector ballPosition; private Vector2 ballInitialForce; // GameObject public GameObject playerObject; // Folosiți acest lucru pentru inițierea void Start () // crea forța ballInitialForce = Vector2 nou (100.0f, 300.0f); // setat la inactive ballIsActive = false; // balon pozitionare minge Pozitie = pozitie transforma; // Actualizarea se numește o singură dată per cadru void Update () // verificați pentru intrarea utilizatorului dacă (Input.GetButtonDown ("Jump") == true) // verificați dacă este prima redare dacă (! BallIsActive) / / resetați forța rigidă a forței2D.isKinematic = false; // adăugați o forță rigidbody2D.AddForce (ballInitialForce); / / set minge activ ballIsActive =! ballIsActive; dacă (! ballIsActive && playerObject! = null) // primiți și utilizați poziția jucătorului ballPosition.x = playerObject.transform.position.x; // aplicați poziția jucătorului X la balonul transform.position = ballPosition; / / Verificați dacă mingea cade dacă (ballIsActive && transform.position.y < -6) ballIsActive = !ballIsActive; ballPosition.x = playerObject.transform.position.x; ballPosition.y = -4.2f; transform.position = ballPosition; rigidbody2D.isKinematic = true;
Acum poti Joaca jocul și verificarea tuturor caracteristicilor implementate mai sus.
Aceasta incheie a doua parte a seriei. Ați implementat acum scripturi personalizate, colizori de fizică și intrări programate de utilizatori. Data viitoare vom stabili blocurile.
Dacă aveți întrebări sau feedback despre ceea ce am acoperit până acum, vă rugăm să lăsați un comentariu mai jos.