Differences

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

Link to this comparison view

pjv:laboratoare:2022:03 [2022/11/09 11:31]
alexandru.gradinaru
pjv:laboratoare:2022:03 [2022/11/10 15:05] (current)
alexandru.gradinaru
Line 1: Line 1:
-===== Controlul ​personajelor =====+===== Programarea ​personajelor =====
  
 ==== Cerinte ===== ==== Cerinte =====
Line 7: Line 7:
 <note tip>​Resurse folosite: <note tip>​Resurse folosite:
   * [[https://​assetstore.unity.com/​packages/​3d/​environments/​fantasy/​fantasy-forest-environment-free-demo-35361|Fantasy Forest Environment - Free Demo]]   * [[https://​assetstore.unity.com/​packages/​3d/​environments/​fantasy/​fantasy-forest-environment-free-demo-35361|Fantasy Forest Environment - Free Demo]]
 +  * [[https://​assetstore.unity.com/?​category=3d%2Fenvironments%5C3d%2Fvegetation&​free=true&​orderBy=1|3D Environments - vegetatation]]
 +  * [[https://​assetstore.unity.com/​packages/​3d/​environments/​fantasy/​canon-tower-50215|Canon tower]]
 +  * [[https://​assetstore.unity.com/​packages/​3d/​environments/​fantasy/​awesome-stylized-mage-tower-53793|Canon tower 2]]
 +  * [[https://​assetstore.unity.com/​packages/​3d/​environments/​stylized-fantasy-house-153587|Fantasy house]]
 +  * [[https://​assetstore.unity.com/​packages/​3d/​environments/​fantasy/​fantasy-kindom-building-pack-lite-78378|Fantasy kingdom]]
 +  * [[https://​assetstore.unity.com/​packages/​3d/​environments/​fantasy/​baker-s-house-26443|Baker house]]
 </​note>​ </​note>​
  
-Realizati o scena de joc similara cu un joc de Duck Hunt 3D+Realizati o scena de joc similara cu un MOBA (ex Dota 2, LoL, Smite etc.)
  
-  ​Mediul:  +  ​Mediul:  
-    ​un teren simplu si ceva vegetatie +    ​un teren cu 3 lane-uri 
-  ​Playerul: +    ​* turnuri pe fiecare lane (vedeti punctele rosii/​albastre ​de pe harta) - ar trebui sa fie diferentiate pe echipe (de ex un steag de culoare deferitasau culoare ​de material deferita ​etc.) 
-    ​- este reprezentat ​de o camera statica in scena (e suficient sa aveti doar camera, nu exista miscare din partea jucatorului) +    ​* cate o baza pentru fiecare player ​(de ex un steag de culoare deferitasau o culoare ​de material deferita ​etc.) 
-    ​are posiblitatea ​de a trage inspre inamici in 2 moduri: +{{ :​pjv:​laboratoare:​2022:​map_of_moba.svg.png |}} 
-      - left click: lanseaza ​un proiectil fizic care mere inspre directia une a fost apasat click (cu anumite reguli: fie are o durata ​de viatafie pana a nimerit ceva, fie adaugati ​forta combinata cu reguli ​de distrugere ​etc.) +  * Playerul are moduri de control. Schimbul intre cele doua moduri se poate face folosind ​tasta, sau la anumite evenimente definite de voi 
-      - right click: damage instant - se realizeaza cu un raycast dinspre camera spre inamic si atinge instant locul in care a fost apasat click +    - Navigatie: o camera 3rd person isometric sau top-down (similar moba - dotalol etc.care sa permita miscarea personajului pe harta in mod automat catre pozitia selectata cu mouse-ul 
-  - Inamicii: +    - Combat mode: o camera ​1st person 
-    ​- exista inamici 3D animati care se deplaseaza inspre camera incotinuu +  ​* Inamiciacestia sunt generati din timp in timp de la bazele fiecarei echipe si se misca automat pe unul din lane-uri catre baza celuilalt player
-    - inamicii se instantiaza ​(spawneaza) incontinuu (puteti pune anumite reguli - de ex sa fie max 5 in scena la un moment dat) intr-o zona din scena care sa fie vizibila ​de catre camera) +
-    - inamicii au comportament fizic (coloziunisunt afectati ​de gravitatie ​etc.) +
-    - inamicii au animatii posibile: run si hit (alergat, si animatie pentru cand au fost doborati/​atinsi) +
-    - inamicii sunt distrusi in momentul in care i-a nimerit playerul ​(cu o animatie scurtaapoi dispar din scena+
-    - inamicii se misca incontinuu spre player (camera) +
-  ​- GUI +
-    - In momentul ​in care au fost doborati 5 inamici, apare in mijlocul ecranului o imagine 2D animata +
-    - In momentul in care au fost doborati 10 inamici, apare in mijlocul ecranului o alta imagine 2D animata print-o metoda diferita fata de cea afisata ​la 5 inamici doborati+
  
 +<note important>​
 +Momentan nu sunt necesare interactiuni. Acest laborator vizeaza doar miscarea/​controlul personajelor si al inimicilor. Vom aborda in laboratoare viitoare intaractiuni dintre obiecte/​inamici etc. 
 +
 +Puteti folosi mecanica de tras implementata in laboratorul 2.
 +</​note>​
  
 ==== Documentatie video ===== ==== Documentatie video =====
Line 48: Line 51:
 === CharacterController === === CharacterController ===
  
-CharacterController este o componenenta ce poate fi adaugata pentru a putea controla ​caracaterul. Aceasta componenta nu foloseste elemente de fizica in nici nu fel, dar vine atasat cu un collider de baza ''​Capsule Collider''​ care nu permite intrarea in alte collidere. Acest lucru simplifica foarte mult scriptarea caracterului.+CharacterController este o componenenta ce poate fi adaugata pentru a putea controla ​personajul. Aceasta componenta nu foloseste elemente de fizica in nici nu fel, dar vine atasat cu un collider de baza ''​Capsule Collider''​ care nu permite intrarea in alte collidere. Acest lucru simplifica foarte mult scriptarea caracterului.
  
 Character Controller pune la dispozitie doua metode pentru miscarea caracterului: ​ Character Controller pune la dispozitie doua metode pentru miscarea caracterului: ​
Line 151: Line 154:
 </​code>​ </​code>​
  
-==== Raycasting ​====+==== Navigare automata ​====
  
-In spatiul 3D testarea selectarii sau tintirii asupra unui obiect se face in general printr-o tehnica numita Raycasting, care presupune trasarea unei raze de la sursa (in general camera) la destinatie. Acest lucru este util atat pentru object picking (selectarea unui obiect in spatiul 3D cu mouse-ul spre exemplu) cat si pentru tintirea si lansarea de proiectile.+=== NavMesh ===
  
-Desi in cazul unui FPSlansarea ​de proiectile se poate face si fizic (deci instantiez ​un proiectil care are damagesi ii imprim o forta cu care sa se deplaseze spre o directie)in general ea se simuleaza prin trasarea unei raze si detectia coliziuniii cu aceasta, si apoi aplicarea ​de efecte astfel incat impactul sa para real (proiectilul in general nu este vizibil ochiului uman).+Pentru navigarea automata a personajelor pana la un punct pe hartaindiferent ca e vorba de un personaj controlat sau un agent inteligentavem nevoie in primul rand de generarea unor zone in care acestea ​sa se poata misca. Aceste zone poarta numele de Navigation Mesh sau NavMeshprescurtat. In Unity se pot genera automat acest NavMesh folosind utilitarul ​de Navigation Bake: Window > AI > Navigation > Bake.
  
-Pentru trasarea unei raze de la camera la o tinta se poate folosi functia de Raycast din pachetul de Physics oferit de Unity. Functia Raycast accepta o multitudine de variante de paramtri, in functie nevoia de utilizare, parametrii principali fiind punctul de start si directia. Un exemplu pentru o camera FPS si o tinta intr-un anumit range se poate folosi urmatoarea secventa de cod:+{{ :pjv:​laboratoare:​bakenavmesh.png?​direct&​300 |}}
  
-<code c#> +De mentionat este ca un navmesh se genereaza folosind elementele statice ale scenei. Pentru a marca un obiect ca fiind static, trebuie bifat in inspector casuta de Static.
-RaycastHit hit;+
  
-//daca am un obiect pe directia in range +{{ :​pjv:​laboratoare:​staticmesh.png?​direct&​300 |}}
-if(Physics.Raycast(fpsCam.transform.position,​ fpsCam.transform.forward,​ out hit, range)) ​ +
-  //accesez un script de damage pe targetul meu daca accesta exista +
-  Enemy orc = hit.transform.GetComponent<​Enemy>​();​ +
-  if(orc!=null) ​{ +
-    orc.TakeDamage(ammount);​ //​TakeDamage este o functie publica in scriptul de Enemy +
-     +
-    enemyHealthBar.SetActive(true);​ //pot afisa si Healthbar-ul inamicului la plasarea tintei pe acesta +
-  } +
-   +
-  if(orc.rigidbody != null) { +
-    orc.rigidbody.addForce(-hit.normal * impactForce);​ //adauga o forta la impact +
-  ​} +
-} +
-</​code>​+
  
-Asa cum se observa si in exemplul ​de mai susRacycast-urile ​se pot folosi in multe moduri. Cateva exemple: +Mai mult, meniul ​de Navigationpermite detalierea fiecarui obiect cu privire la navigatie, astfel incat se poate specifica daca un obiect ​e static sau daca e Walkable sau nu.
-  * aplicarea unei coliziuni +
-  * selectia unui obiect +
-  * tintirea unui obiect +
-  * actionarea unei functii din obiectul tintit +
-  * si altele+
  
-==== Elemente de GUI in 3D ====+{{ :​pjv:​laboratoare:​navigationobjectdetails.png?​direct&​300 |}}
  
-Similar cu spatiul 2D, se pot folosi atat obiecte ​plasate in scenacat si partea de Canvas, in ceea ce priveste interfata grafica.+Crearea (Bake) NavMesh-ului este staticain sensul ca odata creata ea nu se mai modifica la runtime. Astfel, daca avem obiecte ​mobilecare influienteaza NavMesh-ulnu le putem declara statice si nu le putem include ​in procesul de Bake. Pentru acestea exista o componenta ''​Nav Mesh Obstacle''​ care altereaza dinamic NavMesh-ul.
  
-=== FPS Gun ===+{{ :​pjv:​laboratoare:​navmeshobstacle.png?​direct&​300 |}}
  
-Astfel, spre exemplu pentru un FPS single player, ​in general nu avem nevoie ​de caracter, ci doar de maini, sau eventual doar o arma animata. +Rezultatul este o zona in care agentii sau jucatorii pot naviga folosind functii puse la dispozitie ​de unity pentru ​deplasare.
-Pentru a controla usor acest aspect se poate importa un obiect texturat ​pentru ​arma, care se va atasa camerei 3D disponibile in scena si se va configura astfel incat sa arate cat mai natural.+
  
-{{ :​pjv:​laboratoare:​gun.png?​direct&​750 |}}+{{ :​pjv:​laboratoare:​navmesh.png?​direct&​750 |}}
  
-Pentru a crea un crosshair sau o tinta se poata adauga un disc sau o imagine cu transparenta in centrul canvas-ului. ​+==== Agenti ====
  
-{{ :​pjv:​laboratoare:​crosshair.png?​direct&​750 |}}+Pentru a programa o miscare automata pe harta se poate folosi aceasta functionalitate de navigare automata (NavMesh) si componenta de tip NavMeshAgent.
  
-Bineinteles,​ se poate crea un crosshair animat si folosind 4 dreptunghiuri simple. 
  
-{{ :​pjv:​laboratoare:​crosshair2.png?​direct&​750 |}}+=== Inamici ===
  
-=== Healthbar ===+Pentru ca un inamic sa se miste spre player, atunci cand player-ul intra in raza de actiune putem folosi componenta de NavMeshAgent
  
-Pentru reprezentarea healthbar-ului sau a altor elemente ​de tip bara, se poate folosi ​un element ​de UI (gameobject) ​de tip Slider, asa cum este reprezentat in imaginea ​de mai sus.+<​code>​ 
 + 
 +void Update() { 
 +  //calculam distanta intre player si inamic 
 +  float distance = Vector3.Distance(target.position,​ transform.position);​ 
 + 
 +  if(distance <= radius) 
 +  { 
 +    //misca agentul pana la player 
 +    agent.SetDestination(target.position);​ 
 +     
 +    //in momentul in care intra in raza de atac, ataca 
 +  
 +  } else { 
 +    // agentul se misca in treaba lui / patruleaza etc. 
 +  } 
 +</​code>​ 
 +   
 +Mai departe, se poate folosi ​o alta distanta, pentru a determina raza de atac. Un inamic poate avea atac melee (de aproape) sau de la o anumita distanta
  
 <​code>​ <​code>​
-GetComponent.<​Slider>​().value myHealth;+ 
 +public float attackRadius = 1; 
 + 
 +void Update() 
 +  //calculam distanta intre player si inamic 
 +  float distance = Vector3.Distance(target.position,​ transform.position);​ 
 + 
 +  if(distance <radius) 
 +  { 
 +    //misca agentul pana la player 
 +    agent.SetDestination(hit.point); 
 +     
 +    //in momentul in care intra in raza de atac, ataca 
 +    if(distance <= attack)  
 +    { 
 +      //ataca 
 +    } 
 +  
 +  } 
 +  ​
 </​code>​ </​code>​
  
-=== Minimap === 
  
-Pentru crearea unui minimap se foloseste de regula o camera suplimentara,​ plasata top-down deasupra scenei. 
  
-{{ :​pjv:​laboratoare:​minimap1.png?​direct&​350 |}}+=== Miscarea personajului la o destinatie point-and-click ===
  
-Camera special creata va trebui ​sa afiseze scena intr-o textura. Pentru ​acest lucru vom folosi ​un asset de tip ''​Render texture'' ​(//Assets -> Create -> Render Texture//) pe care o vom atasa ca Target in camera nou creata.+Pentru a misca efectivul jucatorul, trebuie ​sa folosim sistemul de navigare al Unity. Pentru ​asta se poate folosi ​pachetul UnityEngine.AI,​ vom adauga o componenta ​de tip ''​Nav Mesh Agent'' ​si vom initializa un agent.
  
-{{ :​pjv:​laboratoare:​minimap3.png?​direct&​350 |}}+<​code>​ 
 +using UnityEngine.AI;
  
-Pasul urmator este sa afisam Minimap-ul. Pentru acest lucru, in canvas vom crea o imagine si vom lega textura in care salvam imaginile de la camera la aceasta.+void Start() { 
 +   agent = GetComponent<​NavMeshAgent>​();​ 
 +}
  
-{{ :​pjv:​laboratoare:​minimap4.png?​direct&​350 |}}+</​code>​
  
-Rezultatul poate fi ibunatatit prin plasarea acestuia intr-un loc potrivit adaugarea unei masti sau a unei borduri si asa mai departe.+Pentru a controla jucatorul cu mouse-ul, avem nevoie de destinatia la care trebuie personajul sa navigheze. Acest lucru putem sa il aflam cu un RayCast.
  
-{{ :​pjv:​laboratoare:​minimap7.png?​direct&​750 |}}+<​code>​
  
-=== Layers === +if(Input.GetMouseButtonDown(0)) //la apasarea click stanga 
 +
 +  Ray mouseClickRay ​camera.ScreenPointToRay(Input.mousePosition);​ //creaza o raza printr-un punct de pe ecran 
 +  RaycastHit hit; 
 +   
 +  if(Physics.Raycast(mouseClickRay,​ out hit)) 
 +  { 
 +    //misca player-ul pana la destinatie 
 +    agent.SetDestination(hit.point);​  
 +  }
  
-Pentru a defini sau actualiza Layere se paote merge la Edit -> Project Settings -> Tags and Layers. +}
-Putem folosi Layere pentru a delimita diverse lucruri, de exemplu care obiecte se vad pe carema, pentru care se calculeaza coliziunea etc.+
  
-Putem simplifica geometria din minimap folosind Layere si primitive simplificate.+</​code>​
  
-{{ https://blog.theknightsofunity.com/​wp-content/​uploads/​2016/​04/​desktop.png |}}+In multe cazuri avem actiuni mai complexe la mouse click dreaptacum ar fi atacarea unui inamic, sau preluarea unui obiect etc, caz un care obiectele se pot misca in scenaPentru asta, trebuie implementata o functie astfel incat sa se poata actualiza pozitia targetului curent.
  
-De exemplu se poata adauga un obiect copil pentru caracter sau obietele care vreau sa apara pe harta. Setam Layerul de Minimap pentru obiect.+<​code>​
  
-{{ https://​blog.theknightsofunity.com/​wp-content/​uploads/​2016/​04/​0f762c1f-bc89-4dd7-af2e-04b11abe7520.png |}}+Transform target = null;
  
-Adaugam si cativa inamici cu alta culoare+if(Input.GetMouseButtonDown(1)) //la apasarea click dreapta 
 +
 +  Ray mouseClickRay = camera.ScreenPointToRay(Input.mousePosition);​ //creaza o raza printr-un punct de pe ecran 
 +  RaycastHit hit; 
 +   
 +  if(Physics.Raycast(mouseClickRay,​ out hit)) 
 +  { 
 +    target = hit.transform;​ 
 +    StartCoroutine(FollowTarget());​ //follow target pana la destinatie 
 +  }
  
-{{ https://​blog.theknightsofunity.com/​wp-content/​uploads/​2016/​04/​c57d0c80-c9e3-42b4-9a0d-6efa9d7a68ca.png |}}+}
  
-Urmatorul pas este sa configuram camera principala astfel incat sa nu afiseze aceste primitive.+if(Input.GetMouseButtonDown(0)) //la apasarea click stanga 
 +
 +  target=null;​ //​dezactiveaza target-ul 
 +}
  
-{{ http://blog.theknightsofunity.com/​wp-content/​uploads/​2016/​04/​5b252849-280c-4322-9115-7e20fb71de52.png |}}+IEnumerator FollowTarget() 
 +{ 
 +  while(target!=null) ​{ 
 +    agent.SetDestination(target);​  
 +    yield return null; 
 +  ​} 
 +  yield return 0; 
 +} 
 +</​code>​
  
-Apoi dezactivam toate celelalte layere si lasam doar Minimap pentru ​camera ​care face Render to Texture din setarea ​de Culling Mask+Pentru a avea o miscare completa, ​camera ​trebuie sa urmareasca jucatorul. Astfel, putem plasa camera ca si child al player-ului,​ sau putem actualiza pozitia folosind un script ca in exemplul ​de mai jos.
  
-{{ https://​blog.theknightsofunity.com/​wp-content/​uploads/​2016/​04/​da459b5f-c6ad-4217-a2e8-938f418535b7.png |}}+<​code>​ 
 +public Transform target; 
 +public Vector3 offset; 
 +public float height = 2f; 
 +public float zoom=10f;
  
-Rezultatul este simplificat ca geometrie si urmeaza pozitiile personajelor+void LateUpdate() //se apeleaza imediat dupa update 
 +
 +  transform.position = target.position - offset * zoom; //​actualizeaza pozitia 
 +  transform.LookAt(target.position + Vector3.up * height); //seteaza directia camerei inspre player 
 +}
  
-{{ https://​blog.theknightsofunity.com/​wp-content/​uploads/​2016/​04/​3b117f6d-153f-4df6-a96c-51487c410209.png |}}+</code>
  
pjv/laboratoare/2022/03.1667986318.txt.gz · Last modified: 2022/11/09 11:31 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