This shows you the differences between two versions of the page.
pjv:laboratoare:2022:04 [2022/11/10 15:07] alexandru.gradinaru |
pjv:laboratoare:2022:04 [2022/11/23 13:12] (current) alexandru.gradinaru |
||
---|---|---|---|
Line 9: | Line 9: | ||
* Personaj (player) | * Personaj (player) | ||
* Controlabil | * Controlabil | ||
- | * Are cel putin 2 atribute (de ex strength si dexterity) | + | * Are viata (health) |
- | * Are viata (health) si viteza (speed) variabile in functie de atribute (de ex strength si dexterity) | + | * Are un XP care creste la diverse evenimente (de ex elimina un inamic, elimina un turn, rezolva un quest etc.) |
- | * Are un XP care creste la diverse evenimente (de ex elimina un inamic, elimina un turn etc.) | + | |
* Poate interactiona cu obiecte (e un corp solid) | * Poate interactiona cu obiecte (e un corp solid) | ||
* Poate ataca inimicii | * Poate ataca inimicii | ||
- | * Minim 3 obiecte de tip pick-up care pot creste atributele personajului - cate unul pentru fiecare atribut si viata. | + | * Minim 1 obiect de tip pick-up care pot reface viata personajului, implementat cu collider. |
- | * Inamici care se misca pe harta | + | * Inamici care se misca pe harta (de ex patruleaza intr-o zona, sau se misca spre baza inamica) |
- | * In momentul in care detecteaza player-ul (intr-o anumita raza de exemplu) se intorc cu fata catre player si il urmaresc | + | * In momentul in care detecteaza player-ul (intr-o anumita raza de exemplu) se intorc cu fata catre player si il urmaresc, implementat custom (fara collider) |
* Au viata (health) | * Au viata (health) | ||
* Pot muri - cand mor ofera experienta personajului | * Pot muri - cand mor ofera experienta personajului | ||
- | * Un minimap cu buline rosii pentru inamici si bulina albastra pentru player | + | |
+ | Bonus: | ||
+ | * Quest system (fara interfata grafica) | ||
==== Documentatie video ===== | ==== Documentatie video ===== | ||
Line 66: | Line 67: | ||
} | } | ||
</code> | </code> | ||
+ | |||
+ | La fel de bine aceste interactiuni pot fi detectate folosind sistemul de colizuni din Unity | ||
+ | > **Physics Events** | ||
+ | |||
+ | <code c#> | ||
+ | /* Both objects have to have a Collider and one object has to have a Rigidbody for these Events to work */ | ||
+ | private void OnCollisionEnter(Collision hit) { Debug.Log(gameObject.name + " just hit " + hit.gameObject.name); } | ||
+ | private void OnCollisionStay(Collision hit) { Debug.Log(gameObject.name + " is hitting " + hit.gameObject.name); } | ||
+ | private void OnCollisionExit(Collision hit) { Debug.Log(gameObject.name + " stopped hitting " + hit.gameObject.name); } | ||
+ | |||
+ | /* Trigger must be checked on one of the Colliders */ | ||
+ | private void OnTriggerEnter(Collider hit) { Debug.Log(gameObject.name + " just hit " + hit.name); } | ||
+ | private void OnTriggerStay(Collider hit) { Debug.Log(gameObject.name + " is hitting " + hit.name); } | ||
+ | private void OnTriggerExit(Collider hit) { Debug.Log(gameObject.name + " stopped hitting " + hit.name); } | ||
+ | |||
+ | /* For 2D Colliders just add 2D to the Method name and the Parameter Type */ | ||
+ | private void OnCollisionEnter2D(Collision2D hit) { } | ||
+ | private void OnCollisionStay2D(Collision2D hit) { } | ||
+ | private void OnCollisionExit2D(Collision2D hit) { } | ||
+ | private void OnTriggerEnter2D(Collider2D hit) { } | ||
+ | private void OnTriggerStay2D(Collider2D hit) { } | ||
+ | private void OnTriggerExit2D(Collider2D hit) { } | ||
+ | |||
+ | </code> | ||
+ | |||
Astfel, toate obiectele ce vor avea interactiuni, vor mosteni aceasta clasa. | Astfel, toate obiectele ce vor avea interactiuni, vor mosteni aceasta clasa. | ||
Line 78: | Line 104: | ||
//mecanica | //mecanica | ||
... | ... | ||
+ | PlayerManager.instance.score += value; | ||
| | ||
//distrugem obiectul | //distrugem obiectul | ||
Line 98: | Line 125: | ||
{{ :pjv:laboratoare:gizmosselected.png?direct&750 |}} | {{ :pjv:laboratoare:gizmosselected.png?direct&750 |}} | ||
- | === Referinte globale la player === | + | === Referinta globala la player === |
O problema in programarea interactiunilor este detectarea player-ului, in sensul de referinta. Astfel, avem mai multe variante: | O problema in programarea interactiunilor este detectarea player-ului, in sensul de referinta. Astfel, avem mai multe variante: | ||
Line 119: | Line 146: | ||
</code> | </code> | ||
- | Folosind varianta simpla cu singleton, putem lua pozitia player-ului de inters, similar cu laboratorul precedent: | + | Folosind varianta simpla cu singleton, putem lua pozitia player-ului de interes: |
<code> | <code> | ||
Line 169: | Line 196: | ||
* NPC-urile interactoneaza la fel, bazate pe o raza de actiune sau efectiv interactiune directa (click) | * NPC-urile interactoneaza la fel, bazate pe o raza de actiune sau efectiv interactiune directa (click) | ||
+ | Pentru ca un inamic sa se miste spre player, atunci cand player-ul intra in raza de actiune putem folosi componenta de NavMeshAgent | ||
+ | <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> | ||
+ | |||
+ | 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> | ||
+ | |||
+ | In multe cazuri avem actiuni mai complexe la mouse click dreapta: cum ar fi atacarea unui inamic, sau preluarea unui obiect etc, caz un care obiectele se pot misca in scena. Pentru asta, trebuie implementata o functie astfel incat sa se poata actualiza pozitia targetului curent. | ||
+ | |||
+ | <code> | ||
+ | |||
+ | Transform target = null; | ||
+ | |||
+ | 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 | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | if(Input.GetMouseButtonDown(0)) //la apasarea click stanga | ||
+ | { | ||
+ | target=null; //dezactiveaza target-ul | ||
+ | } | ||
+ | |||
+ | IEnumerator FollowTarget() | ||
+ | { | ||
+ | while(target!=null) { | ||
+ | agent.SetDestination(target); | ||
+ | yield return null; | ||
+ | } | ||
+ | yield return 0; | ||
+ | } | ||
+ | </code> | ||
=== Quest System === | === Quest System === |