Differences

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

Link to this comparison view

pjv:laboratoare:07 [2019/01/16 14:19]
alexandru.gradinaru
pjv:laboratoare:07 [2019/10/02 12:57] (current)
alexandru.gradinaru
Line 9: Line 9:
   * 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)
  
-==== Inamici ​====+=== Inamici ===
  
 Astfel, pentru inamici putem defini un controller cu un radius de actiune, si un gizmos pentru vizualizare usoara a acestuia in editor. Astfel, pentru inamici putem defini un controller cu un radius de actiune, si un gizmos pentru vizualizare usoara a acestuia in editor.
Line 26: Line 26:
 } }
 </​code>​ </​code>​
 +
 +{{ :​pjv:​laboratoare:​enemy-radius.png?​500 |}}
 +
 Pentru ca un inamic sa se miste spre player, atunci cand player-ul intra in raza de actiune putem folosi componenta de NavMeshAgent Pentru ca un inamic sa se miste spre player, atunci cand player-ul intra in raza de actiune putem folosi componenta de NavMeshAgent
  
Line 37: Line 40:
   {   {
     //misca agentul pana la player     //misca agentul pana la player
-    agent.SetDestination(hit.point);+    agent.SetDestination(target.position);
     ​     ​
     //in momentul in care intra in raza de atac, ataca     //in momentul in care intra in raza de atac, ataca
Line 96: Line 99:
 </​code>​ </​code>​
  
-<hidden>+<code> 
 + 
 +        //Roteste cu 90 grade 
 +        void RotateN() { 
 +         ​Vector3 currentRotation = transform.rotation;​ 
 +         ​Vector3 wantedRotation = currentRotation * Quaternion.AngleAxis(-90,​ Vector3.up);​ 
 +         ​transform.rotation = Quaternion.Slerp(currentRotation,​ wantedRotation,​ Time.deltaTime * rotationSpeed);​ 
 +        } 
 +        //Roteste inamicul cu fata catre player  
 + void FaceTarget () 
 +
 + Vector3 direction = (target.position - transform.position).normalized;​ 
 + Quaternion lookRotation = Quaternion.LookRotation(new Vector3(direction.x,​ 0, direction.z));​ 
 + transform.rotation = Quaternion.Slerp(transform.rotation,​ lookRotation,​ Time.deltaTime * 5f); 
 +
 +</​code>​ 
 + 
 +=== NPC === 
 + 
 +In ceea ce priveste NPC-urile, acestea de obicei interactioneaza cu player-ul prin dialog: oferirea de informatii, gossip, quest-uri etc. 
 + 
 +Sistemele de dialog si de quest-uri pot fi foarte complexe, iar posibilitatile nelimitate. In continuare voi prezenta cateva lucruri de baza prezente in aceste sisteme. 
 + 
 +Din punct de vedere programatic,​ NPC-urile sunt tot un tip de obiect cu care se poate interactiona,​ astfe ca se poate folosi aceasi paradigma din laboratorul precedent, de InteractionObject. 
 + 
 +Primul punct important in interactiunea cu NPC-urile este sistemul de dialog. 
 + 
 +=== Dialog System === 
 + 
 +Pentru crearea unui sistem de dialog, se folosesc elemente de UI Canvas: Panel, Button, Image etc. 
 + 
 +{{ :​pjv:​laboratoare:​dialog-panel.png?​500 |}}  
 + 
 +Mai departe, putem face un DialogManager,​ tot sub format singleton, pentru a putea referentia elementele de UI mai usor, o singura data. In acest manager putem configura diverse linii de dialog, numele NPC-ului care sa apara in caseta de dialog etc. De asemenea, va trebui sa tinem minte si in ce moment, sau la care linie de dialog ne aflam. 
 + 
 +<​code>​ 
 + 
 +public class DialogManager : MonoBehaviour {
   ​   ​
 +  public static DialogManager instance;
 +  public GameObject panel;
 +  public string NPCName;
 +  public List<​string>​ sentences = new List<​string>​();​
 +  ​
 +  Button continueButton;​
 +  Text dialogeTextContainer,​ NPCNameContainer; ​
 +  ​
 +  int lineIndex;
 +    ​
 +  void Awake()
 +  {
 +    //get child components
 +    dialogeTextContainer = ... 
 +    NPCNameContainer = ...
 +    continueButton = ...
 +    continueButton.onClick.AddListener(delegate { ContinueDialog();​ });
 +    ​
 +    instance = this;
 +  }
 +  ​
 +  public void AddNewDialogue(string[] lines, string NPCName)
 +  {
 +    //​initializeaza dialogul curent din NPC
 +    lineIndex=0;​
 +    ...
 +  }
 +  ​
 +  public void showDialog()
 +  {
 +    dialogeTextContainer.text = sentences[lineIndex];​ //afiseaza linia de dialog curenta
 +    NPCNameContainer.text= NPCName;
 +    panel.SetActive(true);​
 +    ​
 +  }
 +  ​
 +  public void ContinueDialog()
 +  {
 +    lineIndex++;​
 +    showDialog();​
 +  }
 +  ​
 +}
 +
 +</​code>​
 +
 +Apoi, in clasa NPC-ului, putem instantia un dialog personalizat pentru NPC-ul respectiv:
 +
 +<​code>​
 +
 +public class NPC : InteractionObject {
 +
 +  public string[] sentences; //se pot configura liniile de dialog in editor
 +  public string name;
 +  ​
 +  public override void Interaction()
 +  {
 +    base.Interaction();​ // se apeleaza metoda parinte
 +
 +    DialogManager.Instance.AddNewDialog(sentences,​ name);
 +  }
 +
 +</​code>​
 +
 +{{ :​pjv:​laboratoare:​dialog.png?​500 |}}
 +
 +=== Quest System ===
 +
 +In ceea ce priveste quest-urile,​ sunt foarte multe posibilitati de abordare, dar in general implica urmatoarele elemente:
 +  * obiectivele quest-ului
 +  * recompensele
 +  * cine gestioneaza quest-ul
 +
 +Astfel, o abordare sugerata este sa se abstractizeze o clasa de tip Quest, una de tip Goal (obiectiv) si una de tip Recompensa, intrucat exista multe tipuri in care se pot instantia aceste lucruri.
 +
 +Exemple de tipuri de Obiective:
 +  * Kill - kill a bunch of stuff
 +  * Gather - gather stuff for me
 +  * Deliver - deliver my live letter
 +  * etc.
 +
 +Exemple de tipuri de Recompense:
 +  * items
 +  * experience
 +  * gold
 +  * skill
 +  * etc.
 +
 +Exemplu de clasa generica de tip Quest
 +
 +<​code>​
 +public class Quest : MonoBehaviour {
 +
 +  public List<​Goal>​ Goals = new List<​Goal>​();​
 +  public List<​Reward>​ Rewards = new List<​Reward>​();​
 +  public bool completed;
 +  ​
 +  public void CheckGoals() {
 +    completed = Goals.All(g => g.completed);​ //questul este gata cand toate obiectivele sunt complete
 +  }
 +  ​
 +  public void GiveReward() {
 +    //in functie de tipul recompensei se adauga obiecte in inventar, sau se adauga experienta, skill points etc.
 +  }
 +  ​
 +  ​
 +
 +}
 +</​code>​
 +
 +Apoi, un exemplu de un quest concret.
 +
 +<​code>​
 +
 +public class RandomSlayThingsQuest : Quest {
 +
 +  void Start()
 +  {
 +    QuestName = "​Random Slayer";​
 +    Description = "Kill some time";
 +    ​
 +    Goals.Add(new KillGoal( ...));
 +    Goals.Add(new KillGoal( ...));
 +    ​
 +    Rewards.Add(new ItemReward( ...));
 +    Rewards.Add(new ExperienceReward( ...)); ​   ​
 +  ​
 +  }
 +
 +}
 +
 +</​code>​
 +
 +Si un exemplu de Obiectiv
 +
 +<​code>​
 +
 +public class KillGoal : Goal {
 +  ​
 +  bool completed;
 +  int currentAmmount;​
 +  ​
 +  public KillGoal(int enemyId, int ammount) {
 +    ...
 +  }
 +  ​
 +  public override void Init() {
 +    //listen to enemy death event
 +    EnemyManager.onDie += EnemyDied;
 +  }
 +  ​
 +  void EnemyDied(enemy) {
 +    this.currentAmmount++;​
 +    if(this.currentAmmount >= ammount) {
 +      this.completed = true;
 +    }
 +  }
 +  ​
 +  ​
 +}
 +
 +</​code>​
 +
 +In ceea ce priveste cine gestioneaza questul, acesta este de obicei un NPC, deci putem extinde clasa NPC cu cateva lucuri specifice:
 +
 +<​code>​
 +
 +public class QuestNPC : NPC {
 + 
 +
 +  public bool assigned;
 +  public Quest quest;
 +  ​
 +  public override void Interaction()
 +  {
 +    base.Interaction();​ // se apeleaza metoda parinte
 +
 +    if(!assigned) {
 +      //dialog
 +      //assign
 +    }
 +    ​
 +    void CheckQuest() {
 +      if(quest.completed) {
 +        quest.GiveReward();​
 +      }
 +    }
 +  }
 +}
 +
 +</​code>​
 +
 +Gestiunea interfetei de quest pentru player, se poate face similar cu cea de inventar, prezentata in laboratorul precedent.
 +
 +
 +==== Cerinte ====
 +
 +Realizarea unui joc 3D RPG
 +
   - Adaugati unul sau mai multi NPC care:   - Adaugati unul sau mai multi NPC care:
       - stiu sa converseze (text) prin raspunsuri la intrebari standard       - stiu sa converseze (text) prin raspunsuri la intrebari standard
-      - pot oferi un quest +      - pot oferi un quest (quest-urile au obiective si recompense)
   - Adaugati unul sau mai multi inamici in scena scriptati astfel incat:   - Adaugati unul sau mai multi inamici in scena scriptati astfel incat:
       - sa fie animati       - sa fie animati
       - sa se plimbe intr-o proximitate       - sa se plimbe intr-o proximitate
-      - la apropierea jucatorului,​ sa il atace+      - la apropierea jucatorului,​ sa il atace  
 + 
 +<​hidden>​ 
 +   
 +  ​
  
 NPC NPC
Line 122: Line 365:
    
       -        - 
-      - </​hidden>​+</​hidden>​
  
 <​hidden>​ <​hidden>​
pjv/laboratoare/07.1547641181.txt.gz · Last modified: 2019/01/16 14:19 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