This shows you the differences between two versions of the page.
pjv:laboratoare:07 [2019/01/16 15:22] alexandru.gradinaru |
pjv:laboratoare:07 [2019/10/02 12:57] (current) alexandru.gradinaru |
||
---|---|---|---|
Line 97: | Line 97: | ||
<code> | <code> | ||
target = PlayerManager.instance.player.transform; | target = PlayerManager.instance.player.transform; | ||
+ | </code> | ||
+ | |||
+ | <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> | </code> | ||
Line 133: | Line 150: | ||
void Awake() | void Awake() | ||
{ | { | ||
- | | + | //get child components |
+ | dialogeTextContainer = ... | ||
+ | NPCNameContainer = ... | ||
+ | continueButton = ... | ||
continueButton.onClick.AddListener(delegate { ContinueDialog(); }); | continueButton.onClick.AddListener(delegate { ContinueDialog(); }); | ||
| | ||
Line 184: | Line 204: | ||
{{ :pjv:laboratoare:dialog.png?500 |}} | {{ :pjv:laboratoare:dialog.png?500 |}} | ||
- | <hidden> | + | === 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 210: | Line 365: | ||
- | - | ||
- | - </hidden> | + | </hidden> |
<hidden> | <hidden> |