Differences

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

Link to this comparison view

pjv:laboratoare:06 [2018/11/14 22:08]
alexandru.gradinaru
pjv:laboratoare:06 [2019/10/02 12:59] (current)
alexandru.gradinaru [Cerinte]
Line 5: Line 5:
 === NavMesh === === NavMesh ===
  
-Pentru navigarea ​personajelor ​automata pana la un punct pe harta, indiferent ca e vorba de un personaj ​conrolat ​sau un agent inteligent, avem nevoie in primul rand de generarea unor zone in care acestea sa se poata misca. Aceste zone poarta numele de Navigation Mesh sau NavMesh, prescurtat. In Unity se pot genera automat acest NavMesh folosind utilitarul de Navigation Bake: Window > AI > Navigation > Bake.+Pentru navigarea automata ​a personajelor ​pana la un punct pe harta, indiferent ca e vorba de un personaj ​controlat ​sau un agent inteligent, avem nevoie in primul rand de generarea unor zone in care acestea sa se poata misca. Aceste zone poarta numele de Navigation Mesh sau NavMesh, prescurtat. In Unity se pot genera automat acest NavMesh folosind utilitarul de Navigation Bake: Window > AI > Navigation > Bake.
  
 {{ :​pjv:​laboratoare:​bakenavmesh.png?​direct&​300 |}} {{ :​pjv:​laboratoare:​bakenavmesh.png?​direct&​300 |}}
Line 106: Line 106:
  
 </​code>​ </​code>​
 +
 +
 +==== Animatia caracterelor ====
 +
 +Animatia caracterelor 3D, se face similar ca in 2D, fiind utilizata animatia bazata pe oase. Astfel, fiecare caracter 3D are definite oase (bones) care controleaza miscarea si animatia acestuia.
 +
 +{{ :​pjv:​laboratoare:​humanoid_bones.png?​direct&​600 |}}
 +
 +Crearea animatiilor se poate face folosind utilitarul de animatie (Window > Animation), similar ca in spatiul 2D. Similar, se poate folosi Animator Controller pentru a gestiona starile.
 +
 +Ca notiune suplimentara,​ se pot defini stari de tranzitie/​interpolare intre anumite animatii. Un exemplu comun este trecerea sau ajustarea animatiei de walk si run in functie de viteza curenta a personajului,​ sau a animatie de alergare stanga - fata - dreapta (daca sunt definite animatii diferite). Acest lucru se poate realiza folosind ''​BlendTrees''​ (Create State > From New Blend Tree).
 +
 +{{ :​pjv:​laboratoare:​mecanimblendtreestatediagramcombined.png?​direct&​600 |}}
  
 ==== Interactiunea cu obiectele ==== ==== Interactiunea cu obiectele ====
Line 141: Line 154:
  
 Astfel, toate obiectele ce vor avea interactiuni,​ vor mosteni aceasta clasa. Astfel, toate obiectele ce vor avea interactiuni,​ vor mosteni aceasta clasa.
 +Spre exemplu pentru un obiect de pickup putem avea urmatoarea secventa:
 +<​code>​
 +public class PickupObject : InteractionObject {
 +
 +  public override void Interaction()
 +  {
 +    base.Interaction();​ // se apeleaza metoda parinte, in caz ca avem ceva generic
 +    ​
 +    //mecanica
 +    ...
 +    ​
 +    //distrugem obiectul
 +    Destroy(gameObject);​
 +    ​
 +  }
 +}
 +</​code>​
  
-Pentru a controla mai bine zona de actiune (radius) si punctul de interes, se poate defini o functie de editor, atunci cand obiectul este selectat. In exemplul de mai jos, la selectarea obiectului se va afisa o sfera wireframe de culoare alba.+Pentru a controla mai bine zona de actiune (radius) si punctul de interes ​pentru un obiect de interactiune (InteractionObject), se poate defini o functie de editor, atunci cand obiectul este selectat. In exemplul de mai jos, la selectarea obiectului se va afisa o sfera wireframe de culoare alba.
  
 <​code>​ <​code>​
Line 154: Line 184:
 {{ :​pjv:​laboratoare:​gizmosselected.png?​direct&​750 |}} {{ :​pjv:​laboratoare:​gizmosselected.png?​direct&​750 |}}
  
-==== Cerinte ====+=== Inventar ​===
  
-Realizarea unui joc 3D RPG+Pentru a crea un sistem de inventar avem nevoie in primul rand de date atasate fiecarui obiect, cum ar fi nume, icon, atribute etc. Putem realiza acest lucru usor prin obiecte scriptabile (Scriptable Objects). Obiectele Scriptable sunt containere de date ce nu trebuie sa fie atasate la un GameObject intr-o scena. Ele pot fi salvate ca asset-uri in bibliteca proiectului ca mai apoi sa poata fi utilizate.
  
-  - Configurati scena pentru rulare 3D +Obiectele scriptabile se definesc prin crearea unui script ce mosteneste clasa ScriptableObject. 
-  - Adaugati in scena un caracter TPS animat ​(puteti lua resurse ​din asset store sau alte locuri: [[pjv:​resurse|]]astfel incat+ 
-      - camera urmareste caracterul 3rd person +Pentru a instantia ​un obiect scriptabil avem doua variante: 
-      - se va controla cu mouse-ul pe harta+  * prin script: SciptableObject.CreateInstance<​MyScriptableObjectClass>​(
-      - poate lua obiecte in inventar +  * din mediuCreateAssetMenu - adauga o intrare noua in meniul de create asset 
-      - poate arunca obiecte din inventar ​ +<​code>​ 
-       + 
-<hidden+[CreateAssetMenu(fileName = "New Item", menuName = "​Inventory/​Item",​ order = 1)
-      - poate schimba arma de atac echipata +public class Item ScriptableObject { 
-      - poate consulta quest-ul curent +    new public string name = "New MyScriptableObject";​ //​suprascrie atributul name 
-      - poate ataca +    ​public string objectName = "New MyScriptableObject"​
-      - are experienta si level-uri +    ​public bool colorIsRandom = false; 
-      - in functie ​de level poata adauga puncte intr-un skilltree +    ​public Color thisColor = Color.white;​ 
-      - poate folosi skill-uri/abilitati speciale+    ​public Sprite icon; 
 +    public Vector3[] spawnPoints;​ 
 +} 
 +</code
 + 
 +Intrucat exista atribute implicite pentru un obiect scriptabil (e.g. name), putem folosi variabile diferite (e.g. objectName) sau putem suprascrie definirea acestui atribut prin folosirea metodei ''​new''​ (new public string name). 
 + 
 +Mai departe, pentru un inventar vom avea nevoie ​de o lista de obiecte gestionabile. Pentru acest lucru vom face un script de gestiune pentru inventar (e.g InventoryManager) care gestioneaza adaugarea, eliminarea si interogarea inventarului. Pentru o accesare mai usoara si mai facila, ideal ar fi ca acest inventorymanager sa fie un Singleton. Pentru a avea un singleton trebuie sa ne asiguram ca avem o singura instanta creata pentru acest script atunci cand e accesat. 
 + 
 +<​code>​ 
 +public class InventoryManager : MonoBehaviour { 
 + 
 +  ​// singleton 
 +  public static InventoryManager instance; 
 +  void Awake() { 
 +    instance = this; 
 +  }
   ​   ​
-  ​- Adaugati unul sau mai multi NPC care: +  ​//lista de obiecte 
-      - stiu sa converseze ​(textprin raspunsuri la intrebari standard +  ​public List<​Item>​ items = new List<​Item>​(); 
-      - pot oferi un quest  +   
-  ​- Adaugati unul sau mai multi inamici in scena scriptati astfel incat: +  ​//metode pentru gestionare 
-      - sa fie animati +  ​public void Add(Item item) { 
-      - sa se plimbe intr-o proximitate +    ​items.Add(item);​ 
-      - la apropierea jucatorului,​ sa il atace</​hidden>​+  } 
 +   
 +  public void Remove(Item item) { 
 +    items.Remove(item);​ 
 +  }
  
-<hidden> +
-(vezi demo UI de la 3dpub) +</code>
-  - coliziuni, proiectile +
-  - interfata grafica pt un fps +
-  - Managing weapons, Navmeshes, navmesh Agents, AI Auto-Attack +
-  - animatie caractere atac, arma, coliziuni atac+
  
-73d RPG inventory system, quest system, skill system, pathfinding,​Grid Snapping, Managing weapons, Navmeshes, navmesh Agents, AI Auto-Attack+Fiind definit ca un singleton, putem accesa acum foarte usor gestionarea inventarului: 
 +<​code>​ 
 +Inventory.instance.Add(item);​ 
 +Inventory.instance.Remove(item);​ 
 +</​code>​
  
-QuestLog+Inca un element util in gestionarea inventarului este definirea unei metode de a notifica atunci cand s-a produs o modificare in inventar. Pentru acest lucru putem folosi ''​Delegates''​. Un Delegate este un pointer la o metode. Aceasta ne permite sa tratam metoda ca o variabila și sa o folosim pentru un callback. Cand este apelata, acesta notifica toate metodele care fac referire la delegate. Astfel putem definit o variabila pentru evenimentul de schimbare. 
 +<​code>​ 
 +  public delegate void OnInventoryChanged();​ 
 +  public OnInventoryChanged onInventoryChangedCallback;​ 
 +   
 + //​metode pentru gestionare 
 +  public void Add(Item item) { 
 +    ... 
 +    onInventoryChangedCallback.Invoke();​ //notifica despre modificare 
 +  } 
 +   
 +  public void Remove(Item item) { 
 +    ... 
 +    onInventoryChangedCallback.Invoke();​ //notifica despre ​ modificare 
 +  } 
 +</​code>​ 
 +Urmatorul pas este crearea unei interfete grafice si legarea interfetei de functionalitatea InventoryManger-ului. 
 +Pentru interfata grafica, putem folosi, ca si pana acum, canvas-ul oferit de Unity, structurat astfel incat sa avem un panou general pentru inventar, si mai multe slot-uri pentru obiectele din acesta. Pe fiecare slot putem defini urmatoarele aspecte: 
 +  * un gameobject 
 +  * un buton de accesare : pentru folosirea obiectului, echipare etc. 
 +  * un buton de eliminare : pentru eliminarea din inventar 
 +  * o imagine: icon pentru obiectul in inventar 
 +  * script de gestionare: pentru fiecare slot putem avea un script de gestionare care va actualiza interfata slotului respectiv (nume, icon etc).
  
-playerul +Interfata grafica a inventarului ​are nevoie si de un script de gestionare. Astfel vom aveam un script ​care asculta ​(subscribeevenimentul definit ​(''​delegate''​la actualizarea inventaruluisi actualizeaza fiecare slot din interfata grafica:
-are abilitati speciale ​care consuma mana/puncte de abilitate +
-poate prelua unul sau mai multe quest-uri +
-poate cara obiecte ​(iau un cub dintr-o parte si il pun in alta, ca sa sar pe el) +
-poate interactiona cu NPC (botsipentru preluare de quest-uri +
-are un scor in functie de numarul de quest-uri rezolvate +
-este animat (atacmiscare)+
  
-NPC +<​code>​ 
-Agenti de la care se pot prelua/​rezolva quest-uri +void Start() { 
-Sunt animati +  ​inventory = Inventory.instance;​ 
-Pot purta conversatie cu mai multe fire de dialog si mai multe variante de raspuns+  ​inventory.onInventoryChangedCallback += UpdateUI; //​definesc ​metoda ca se apeleaza la aparitia unui eveniment delegat 
 +   
 +  slots = GetComponentsInChildren<​InventorySlot>​();​ //fiecare slot din inventar 
 +}
  
-</hidden>+void UpdateUI() { 
 +   
 +  ​//​actualizare fiecare slot 
 +  for(i=0; i < slots.Length;​ i++) 
 +  { 
 +    if(i<​iventory.items.Count) slots[i].AddItem(..) 
 +    else slots[i].RemoveItem(..) 
 +  } 
  
 +}
 +</​code>​
  
-<​hidden>​ +<​hidden>​sistem inventar
-===== Elemente de programare a jocurilor 3D ===== +
-- animatii cu blend tree+
  
 +Bineinteles,​ in inventar se pot pune diferse restrictii si interactiuni (cum ar fi dimensiunea maxima a inventarului)
 +<​code>​
 +bool AddItem() {
  
 +if(items.Count >= space)
 +//no more room
 +return false
 +
 +else return true;
 +}
 +
 +if(Inventory.instance.Add(item)) Destroy(gameObject);​
 +</​code>​
 </​hidden>​ </​hidden>​
 +
 +==== Cerinte ====
 +
 +Realizarea unui joc 3D Top-Down
 +
 +  - Configurati scena pentru rulare 3D
 +  - Adaugati in scena un caracter animat (puteti lua resurse din asset store sau alte locuri: [[pjv:​resurse|]]) astfel incat:
 +      - camera urmareste caracterul de sus
 +      - se va deplasa prin click mouse-ul la o locatie pe harta;
 +      - poate lua obiecte in inventar
 +      - poate arunca obiecte din inventar ​
 +  - Adaugati mai multe tipuri de obiecte interactionabile in scena
pjv/laboratoare/06.1542226130.txt.gz · Last modified: 2018/11/14 22:08 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