Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pjv:laboratoare:2020:02 [2020/10/14 11:16]
alexandru.gradinaru created
pjv:laboratoare:2020:02 [2021/11/10 20:16] (current)
alexandru.gradinaru
Line 1: Line 1:
 ===== Animatii si interactiuni 2D ===== ===== Animatii si interactiuni 2D =====
 +
 +==== Animatii 2D in Unity ====
 +
 +In Unity (versiuni dupa 2018) avem doua posibilitati de a face animatii 2D: //​sprite-sheet//​ si //​bone-based//​.
 +
 +{{ :​pjv:​laboratoare:​ninja.jpg?​200 |}} 
 +
 +În prima imagine, caracterul este prezentat în mai multe poziții, cu o secvență de poziții pentru diferite acțiuni. Aceasta imagine reprezinta un //​sprite-sheet//,​ fiind foarte popular in jocurile 2D. Aceasta vă permite să vă imaginați în mod clar modul în care se va mișca în joc. 
 +
 +{{ :​pjv:​laboratoare:​02.png?​200 |}}
 +
 +In a doua imagine, balaurul este împărțit în mai multe părți ale corpului (cap, corp, brațe și așa mai departe), necesitand o tehnică mai recentă de animație 2D, denumită în mod normal animație bazată pe oase (//​bone-based//​). După cum sugerează și numele, animația va fi pe bază de os, în care fiecare os din corp poate avea o acțiune sau o animație specifică. Având toate părțile principale ale corpului separat, permite dezvoltatorilor să creeze animațiile direct în editor. Această tehnică nouă de animație este foarte asemănătoare cu cea utilizată în animația 3D.
 +
 +=== Sprite-sheet ===
 +
 +Puteti descarca imaginea urmatoare ca exemplu: {{ :​pjv:​laboratoare:​ken-sprite-sheet.png?​direct&​300 |}}
 +Pentru a folosi sprite-sheet-ul,​ incarcati imaginea in Unity si configurati ''​Sprite Mode''​ ca ''​Multiple'',​ dupa care accesati ''​Sprite Editor''​. {{ :​pjv:​laboratoare:​managingstates4.jpg?​direct&​300 | }} {{ :​pjv:​laboratoare:​managingstates6.jpg?​direct&​300 |}}
 +
 +In editor accesati meniul de ''​Slice''​ si puteti folosi varianta automata, sau manuala pentru a selecta diferitele stari ale animatiei. Dupa aceasta operatie, veti avea fiecare sprite individual. {{ :​pjv:​laboratoare:​managingstates81.jpg?​direct&​300 |}}
 +
 +Pentru a crea animatii din secvente de sprite-uri, puteti selecta sprite-urile si din folositi functia de ''​Create Animation''​ sau, mai simplu, puteti face drag-and-drop in scena si vi se creaza automat o animatie pe care va trebui sa o salvati. {{ :​pjv:​laboratoare:​managingstates11.jpg?​direct&​300 |}}
 +
 +Pentru sprite-ul oferit animatiile sunt asezate in felul urmator:
 +  * idle = 0 - 9
 +  * walk =   10 - 20
 +  * hadooken = 21 - 31
 +  * crouch ​ =  32 - 37
 +  * jump = 38 - 48
 +{{ :​pjv:​laboratoare:​managingstates13.jpg?​direct&​300 |}}
 +
 +=== Bone-based (Simulated) ===
 +
 +Folosirea animatiilor pe baza de oase necesita mai multa munca.
 +{{ :​pjv:​laboratoare:​02.png?​direct&​300 |}}
 +
 +In primul rand, plecand de la o imagine (puteti folosi imaginea de mai sus), trebuie despartita in slice-uri, similar cu procesul de la sprite sheet.
 +{{ :​pjv:​laboratoare:​16.png?​direct&​300 |}}
 +
 +Apoi, aceste sprite-uri trebuie asamblate in scena, astfel incat sa formeze un obiect. Este indicat sa aveti o structura arborescenta. Acest lucru va fi folositor in crearea animatiilor,​ deoarece atunci cand misc bratul (arm), evident trebuie sa misc si mana (hand).
 + 
 +{{ :​pjv:​laboratoare:​24.png?​direct&​300 |}} 
 +{{ :​pjv:​laboratoare:​27.png?​direct&​300 |}}
 +
 +Pentru ordine puteti folosi urmatoarele valori ​
 +  * Dragon: 0
 +  * Body: 3
 +  * Head: 4
 +  * Left Leg: 4
 +  * Left Upper Arm: 5
 +  * Left Arm: 4
 +  * Left Hand: 5
 +  * Right Leg: 1
 +  * Right Upper Arm: 2
 +  * Right Arm: 1
 +  * Right Hand: 2
 +  * Tail: 4
 +  * Tail Tip: 5
 +
 +Urmatorul pas este crearea animatiilor,​ care de aceasta data trebuie facuta manual folosind utilitarul de animatie (Window > Animation). Vedeti subcapitolul de mai jos.
 +
 +=== Bone-based ===
 +
 +Incepand cu versiunea din 2018 (2018.2.0f2),​ Unity are suport si pentru animatii Bone-based pentru 2D, functionalitate accesibila prin instalarea pachetului de 2D Animation.
 +
 +Puteti folosi imaginea de mai jos ca exemplu: {{ :​pjv:​laboratoare:​plunkahgreen.png?​direct&​200 |}}
 +
 +Fluxul de lucru:
 +
 +Se construieste ierarhia de oase în editor (Sprite Editor > Bone Editor).
 +{{ :​pjv:​laboratoare:​boneeditor.png?​direct&​300 |}}
 +
 +Se genereaza geometria și se atribuie greutăți ale pielii în editor (Sprite Editor > Geometry And Weight Editor).
 +{{ :​pjv:​laboratoare:​geowaiteditor.png?​direct&​300 |}}
 +
 +Se adauga componenta ''​Sprite Skin''​ pentru a genera oasele.
 +{{ :​pjv:​laboratoare:​bonehierarchy.png?​direct&​300 |}}
 +
 +Mai multe detalii aici: 
 +  * [[https://​github.com/​Unity-Technologies/​2d-animation-samples/​blob/​master/​Documentation/​2DAnimation.md]]
 +  * [[https://​blogs.unity3d.com/​2018/​11/​09/​getting-started-with-unitys-2d-animation-package/​]]
 +  * [[https://​docs.unity3d.com/​Packages/​com.unity.2d.animation@1.0/​manual/​index.html]]
 +
 +Urmeaza crearea de animatii pentru obiect folosind oasele.
 +
 +
 +=== Crearea de animatii ===
 +
 +Crearea animatiilor se poate face folosind utilitarul de animatie (Window > Animation).
 +
 +Pentru a crea animatia unui obiect, puteti selecta acel obiect si sa creati un animator pentru acesta (in cazul in care nu exista).
 +Cum se foloseste animatorul: Folositi butonul de ''​Record''​ si creati key-frame-uri in care sa se diversi parameri de Transform sau Render. Spre exemplu puteti roti capul dragonului: {{ :​pjv:​laboratoare:​11.png?​direct&​300 |}}
 +
 +Pentru a crea o noua animatie folositi butonul de Create new Clip (spre exemplu pentru Jump): {{ :​pjv:​laboratoare:​16_1_.png?​direct&​300 |}}
 +
 + 
 +=== Animator Controller ===
 +
 +Urmatorul pas este sa configuram aceste animatii astfel incat sa le putem folosi, si sa putem tranzitiona intre ele. Pentru acest lucru, vom folosi un ''​Animator Controller''​. Acest controller functioneaza ca un automat de stari, fiecare stare putand fi o animatie.
 +
 +Pentru a folosi animatiile se pot adauga cu drag-and-drop in Animator.
 +{{ :​pjv:​laboratoare:​unitystates5.png?​direct&​300 |}}
 +
 +Pentru animatii fluente si controlate, trebuie sa definim tranzitii intre acestea. Tranzitiile au mai multe proprietati,​ printre care timpi de activare, conditii etc.
 +{{ :​pjv:​laboratoare:​unitystates11.jpg?​direct&​300 |}}
 +{{ :​pjv:​laboratoare:​unitystates10.png?​direct&​300 |}}
 +{{ :​pjv:​laboratoare:​unitystates12.jpg?​direct&​300 |}}
 +
 +Conditiile sunt folosite pentru a controla cand are loc o tranzitie. Spre exemplu, putem folosi un parametru de stare, pentru a trece dintr-o animatie in alta, sau alte conditii (spre exemplu daca este pe sol, in aer, primeste damage etc.)
 +
 +Spre exemplu putem folosi urmatoarea conventie pentru un parametru de stare:
 +  * ken_idle = 0
 +  * ken_walk =  1
 +  * ken_crouch = 2
 +  * ken_jump = 3
 +  * ken_hadooken = 4
 +
 +si punem conditia de tranzitie de la Idle la Walk ''​state=1''​. Acest lucru îi va spune personajului,​ dacă este în Idle, pentru a tranzitiona la animația de Walk dacă parametrul de stare se schimbă la 1.
 +
 +=== Schimbarea starilor unui Animator ===
 +
 +Pentru a schimba starile unui animator, trebuie in primul rand adaugata componenta de Animator pe obiect.
 +Apoi, putem controla parametrii definiti prin functii disponibile in clasa Animator.
 +
 +<code c#>
 +const int STATE_IDLE = 0;
 +const int STATE_WALK = 1;
 +const int STATE_CROUCH = 2;
 +const int STATE_JUMP = 3;
 +const int STATE_HADOOKEN = 4;
 + 
 +string _currentDirection = "​left";​
 +void Start()
 +{
 +        //define the animator attached to the player
 +        animator = this.GetComponent<​Animator>​();​
 +}
 +    ​
 +void Update()
 +{
 +        if (Input.GetKey ("​right"​)) {
 +          changeDirection ("​right"​);​ //schimba directia personajului
 +          transform.Translate(Vector3.left * walkSpeed * Time.deltaTime);​ //muta personajul
 +          animator.SetInteger ("​state",​ STATE_WALK);​ //activeaza animatia
 +          ​
 +        }
 +}
 +
 +void changeDirection(string direction)
 +     {
 + 
 +         if (_currentDirection != direction)
 +         {
 +             if (direction == "​right"​)
 +             {
 +             ​transform.Rotate (0, 180, 0);
 +             ​_currentDirection = "​right";​
 +             }
 +             else if (direction == "​left"​)
 +             {
 +             ​transform.Rotate (0, -180, 0);
 +             ​_currentDirection = "​left";​
 +             }
 +         }
 + 
 +     }
 +</​code>​
 +
 +=== Animatie fundal ===
 +
 +Petru a anima fundalul unui joc 2D, putem altera pozitia texturii. Astfel, trebuie sa definim un material cu o textura, si sa o aplicam pe un obiect (de obicei un quad). Dupa care avem la dispozitie componenta de Render in care putem accesa materialul si implicit texturile, la care putem adauga un offset, in functie de pozitia caracterului,​ sau o miscare in timp etc.
 +
 +<​code>​
 +   ​renderer = GetComponent<​Renderer>​();​
 +   
 +   ​renderer.material.SetTextureOffset("​_MainTex",​ offset);
 +   
 +   // "​_MainTex"​ is the main diffuse texture. This can also be accessed via mainTextureOffset property. ​
 +   // "​_BumpMap"​ is the normal map. 
 +   // "​_Cube"​ is the reflection cubemap.
 +</​code>​
 +
 +Pentru a functiona corect, textura pe care o folositi trebuie sa fie setata pe ''​Repeat''​
 +{{ :​pjv:​laboratoare:​2018-10-24_2_li.jpg?​direct&​300 |}}
 +
 +=== Animatii proiectile / tragere ===
 +
 +Pentru animatia de tragere, se foloseste in general o stare pentru a actualiza animatia jucatorului,​ iar proiectilul se genereaza in felul urmator (recomandat):  ​
 +  * Pe arma (care se afla in scena) se adauga un script care gestioneaza generarea si directia proiectilelor
 +  * Plecand din locatia armei, se instantiaza (folosind functia Instantiate,​ studiata deja) un proiectil (prefab de regula, nu trebuie sa existe deja in scena, folosind pozitia armei). Proiectilul are atasat un script ce contine detalii de viteza, damage etc
 +  * Proiectilul are o miscare de translatie continua pe o directie, pana la atingerea unei limite sau a unui collider cand produce un trigger
 +
 +=== Animatii si instantiere in scena ====
 +
 +Pentru instantiere se foloseste functia ''​Instantiate(gameobject,​ position)''​.
 +Pentru a genera continut doar in spatiu vizil pe ecran, se pot defini obiecte care fixeaza acest cadru, si generat random apoi in acest interval.
 +Obiectele generate pot fi scriptate astfel incat sa aiba animatii si miscari continui.
 +
 +=== Miscarea personajului ===
 +
 +Miscarea personajului se poate face folosind o componenta de RigidBody2D si aplicand forte sau miscari.
 +<​code>​
 +rb = GetComponent<​Rigidbody2D>​();​
 +float moveHorizontal = Input.GetAxis ("​Horizontal"​);​
 +float moveVertical = Input.GetAxis ("​Vertical"​);​
 +
 +Vector3 movement = new Vector3 (moveHorizontal,​ 0.0f, moveVertical);​
 +
 +rb.AddForce (movement * speed);
 +
 +rb.MovePosition (transform.position + offset * Time.deltaTime);​
 +</​code>​
 +
 +=== Coliziuni ===
 +
 +Pentru detectia coliziunilor se poate folosi un collider2D. Pentru o interactiune usoara, se poate genera un Trigger la evenimentul de coliziune bifand caseta de ''​Trigger''​ din componenta. Dupa care se poate prelua evenimentul si obiectul cu care se face coliziunea.
 +<​code>​
 +void OnTriggerEnter(Collider otherObject) {
 +
 + score += 10;
 + scoreText.text = score.ToString();​
 + Destroy(otherObject.gameObject);​
 +
 + }
 +</​code>​
 +
 +===== Tilemaps 2D =====
 +
 +==== Elemente componente ====
 +  - Grid: componenta de tip canvas, in care se pot adauga tilemap-uri
 +  - Tilemap: obiectul in care se vor adauga tile-urile
 +  - Tilemap Renderer: componenta care controleaza cum se deseneaza tile-urile
 +  - Tile Palette: asset ce defineste o colectie de tile-urile ce ar putea fi folosite
 +  - Tile: asset ce poate contine un Sprite, o culoare sau un colider
 +  ​
 +Tile-urile pot fi scriptate astfel incat sa se creeze comportamente personalizate,​ spre exemplu in functie de vecini sau pozitia tile-ului.
 + 
 +==== Palette ==== 
 +
 +Pentru a utiliza tilemaps, in primul rand trebuie definita o paleta folosind utilitarul Window -> 2D -> Tile Palette.
 +
 +Acest utilitar va permite sa creati palete diferite pentru a construi usor tilemap-ul.
 +
 +{{ :​pjv:​laboratoare:​tile-palette-window.png?​direct&​300 |}}
 +
 +La aceasta paleta se adauga sprite-uri ce se vor putea folosi ulterior ca template-uri de desenare (brush).
 +
 +{{ :​pjv:​laboratoare:​create-tiles-from-spritesheet.gif?​direct&​300 |}}
 +
 +Se pot folosi si brush-uri standard sau personalizate,​ prefab-uri etc.
 +
 +{{ :​pjv:​laboratoare:​2018-10-31_1_.png?​direct&​300 |}}
 +
 +==== Tile maps ====
 +
 +Pentru a adauga un tilemap in scena, adaugati un GameObject de tipul 2D -> Tilemap. Acesta va genera un Grid parinte si un tilemap.
 +
 +Folosind paleta construita, se poate `picta` tilemap-ul.
 +
 +{{ :​pjv:​laboratoare:​select-sandy-brush.png?​direct&​300 |}}
 +
 +{{ :​pjv:​laboratoare:​paint-sand.gif?​direct&​300 |}}
 +
 +Exista si posibiltatea de a folosi un prefab pentru un tile prin ''​PrefabBrush''​. Acest lucru ne permite definirea de obiecte mai complexe (scriptate, de ex pickups sau inamici) si generarea lor in tile-uri.
 +
 +{{ :​pjv:​laboratoare:​setup-prefab-brush.png?​direct&​300 |}}
 +
 +{{ :​pjv:​laboratoare:​painting-prefabs-down.gif?​direct&​300 |}}
 +
 +Se pot adauga mai multe tilemap-uri in grid (spre ex unul pentru teren, unul pentru vegetatie, inamici etc)
 +
 +{{ :​pjv:​laboratoare:​switch-layer-to-dungeonfloor.png?​direct&​300 |}}
 +
 +Un tilemap poate avea si coliziuni, prin adaugarea unei componente de ''​Tilemap Collider 2D''​.
 +
 +Separarea in mai multe layere de tilemap ne ajuta sa adaugam coliziuni doar pentru elementele importante: de exemplu pot avea un tilemap cu pereti (care vor avea coliziune) si un tilemap cu elemente de podea sau decor in fundal, care de regula nu au coliziuni.
 +
 +{{ :​pjv:​laboratoare:​wall-colliding.gif?​direct&​300 |}}
 +
 +O componentă utilă este Colliderul ''​Composite Collider''​. Adăugarea acestuia Tilemap Collider 2D va fuziona toate coliderele într-o plasă de coliziune mult mai optimizată a geometriei!
 +
 +{{ :​pjv:​laboratoare:​composite-collider-2d.png?​direct&​300 |}}
 +
 +==== Tiles ====
 +
 +Tile-urile pot fi scriptate, astfel ca se pot defini reguli pentru afisarea lor. Pentru a usura acest lucru, se poate folosi pachetul de add-on de ``2D extras`` de la unity: [[https://​github.com/​Unity-Technologies/​2d-extras]].
 +
 +Astfel, aveti la dipozitie crearea simpla de tile-uri:
 +  * RuleTile: script de baza pentru contruirea de reguli manuale in plasarea automata a tile-urilor
 +  * Animate: creaza o animatie prin afișarea unei liste de sprite în ordine (sprite animation pentru tile)
 +  * Pipeline: iau în considerare tile-urile ortogonale învecinate și afișează un sprite daca tile-ul vecin este simlar sau nu
 +  * Random: aleg aleator un sprite dintr-o listă dată de sprites și o locație țintă și afișează sprite-ul
 +  * Terrain: iau in considerare vecinii ortogonali si diagonali si afiseaza un sprite daca tile-urile vecine este simlar sau nu
 +
 +Crearea unui RuleTile va permite sa definiti usor scripturi automate de generare a terenului folosind un tile, care se afiseaza diferit in functie de amplasare.
 +
 +{{ :​pjv:​laboratoare:​rule-tile-selection.png?​direct&​300 |}}
 +
 +
 +Acest tip de tile imi permite sa definesc reguli pentru existenta sau nu a vecinilor. In functie de aceste reguli se poate folosi un sprite sau altul. X rosu inseamna ca nu trebuie sa existe, iar sageata verde indica necesitatea vecinilor.
 +
 +{{ :​pjv:​laboratoare:​finishedruletile.png?​direct&​300 |}}
 +
 +Ouput-ul unei reguli poate fi un singur sprite, o animatie sau alegerea random a unui sprite.
 +
 +{{ :​pjv:​laboratoare:​makesensof-this-1024x899.png?​direct&​300 |}}
 +
 +==== Generare procedurala ====
 +
 +Tilemaps-urile ofera, dupa cum ati vazut prin RuleTile, posibilitatea de a seta tile-urile dinamic, folosind scripturi. Asta inseamna ca se pot genera procedural tilemap-uri intregi.
 +
 +{{ :​pjv:​laboratoare:​image3.gif?​direct&​300 |}}
 +
 +Un mod usor de a genera procedural o scena, este prin folosirea de RuleTile. Astfel, se genereaza un grid care se completeaza pe alocuri cu tile-ul dinamic (RuleTile), sprite-ul afisat fiind in functie de pozitia si vecinii tile-ului curent.
 +
 +Pentru a seta un tile, se poate folosi functia
 +<​code>​
 +
 +using UnityEngine.Tilemaps;​
 +
 +[Tooltip("​The Tilemap to draw onto"​)]
 +public Tilemap tilemap;
 +[Tooltip("​The Tile to draw (use a RuleTile for best results)"​)]
 +public TileBase tile;
 +
 +//​SetTile(position,​ tile)
 +tilemap.SetTile(new Vector3Int(x,​ y, 0), tile);
 +</​code>​
 +
 +Pentru a genera random o scena, se pot folosi tehnici precum Perlin Noise, Random Walk, Cellular Automata etc.
 +Mai multe detalii si exemple de implementare gasiti aici: [[https://​blogs.unity3d.com/​2018/​05/​29/​procedural-patterns-you-can-use-with-tilemaps-part-i/​|Part I]] [[https://​blogs.unity3d.com/​2018/​06/​07/​procedural-patterns-to-use-with-tilemaps-part-ii/​|Part II]]
 +
 +De asemenea, in proiectul de starter, mai este definit un tip de tile, denumit PrefabTile, prin care practic se pot adauga prefab-uri ca tile-uri efectiv (se inlocuieste gameObjectul tile-ului cu cel al prefab-ului). Puteti verifica in Add-Ons > PrefabTile. Astfel, se pot folosi prefab-uri pentru generare automata de tile-uri.
 +
 +===== Cerinte =====
 +
 +Leapşa 2D platformer: realizati un 2D platformer cu interactiuni simple care sa includa:
 +  - Un mediu de joaca prin folosirea de tilemap:
 +    - Creati o paleta de sprite-uri
 +    - Creati un tilemap
 +    - Desenati tilemap-ul folosind paleta definita, adaugand coliziune pe alocuri
 +    - Desenati tilemap-ul cu diverse tipuri de brush, inclusiv cu cel definit custom (GemBrush)
 +  - Un mediu generat aleator
 +    - Definiti un RuleTile si reguli pentru un tile (de ex JungleTile - aveti deja exemplu cu GrassPlatform)
 +    - Creati un tilemap
 +    - Creati un script pentru a genera random o suprafata de teren/​obstacole cu coliziune folosind RuleTile
 +    - [bonus] Creati un script pentru a genera random elemente de mediu fara coliziune (le gasiti in EnvironmentProps;​ puteti folosi un output de Random sau direct un RandomTile)
 +    - [bonus] Creati un script pentru a genera random elemente de pickup (aveti un prefab ''​CollectableGem''​ la dispozitie pe care il puteti folosi intr-un PrefabTile)
 +  - Un fundal animat in scena (o imagine, sau obiecte)
 +  - Minim doua tipuri de inamici animati (prin orice tehnica prezentata)
 +    - trag cu proiectile aleator/in jucator: la atingerea jucatorului iau damage
 +    - animat in mai multe stari (minim 3: miscare, atac, distrugere)
 +    - la coliziune cu jucatorul se distrug
 +    - sunt generati dinamic, la pozitii aleatoare si se deplaseaza continuu
 +  - Un personaj principal
 +    - Configurati camera astfel incat sa urmareasca personajul principal din scena
 +    - Se poate controla de la tastatura
 +    - Animat in mai multe stari (minim 3: mers, sarit, damage)
 +    - Health (viata jucatorului):​ se decrementeaza in momentul in care este atins de proiectile inamice
 +    - Score (scorul jucatorului):​ se incrementeaza in momentul in care atinge inamicii sau [bonus] trece prin obiecte colectabile
 +
 +<note tip>​Descarcati scena de start de aici, cu personaj deja configurat si cu rule-tile-uri:​ [[https://​www.dropbox.com/​s/​8lo09g081ni0j2c/​2DTilemapsStarter.zip?​dl=0 | Download ZIP]]</​note>​
 +
 +===== Resurse =====
 +
 +[[https://​felgo.com/​game-resources/​make-pixel-art-online|Aplicatii de desenat sprite-uri]]
 +
 +
pjv/laboratoare/2020/02.1602663371.txt.gz · Last modified: 2020/10/14 11:16 by alexandru.gradinaru
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0