matheostsik Δημοσ. 22 Μαΐου 2018 Δημοσ. 22 Μαΐου 2018 Καλημερα παιδια, Με ευκαιρια μια εργασια που εχω στη σχολη μου,προσπαθω να μαθω unity. Σαν πρωτο βημα θελω σε ενα ετοιμο project (Tanks) να προσθεσω καποια χαρακτηριστικα οπως healthpickups. Αλλα οτι εχω δοκιμασει δε λειτουργει και δε ξερω γιατι,παραθετω τον κωδικα που εχω βαλει στο σκριπτ να μου πειτε αν υπαρχει λαθος εκει. public class HealthPickup : MonoBehaviour{ TankHealth tankHealth; public float healthBonus = 15f; void Awake(){ tankHealth = FindObjectOfType<TankHealth>(); } void OnTriggerEnter2D(Collider2D col){ if(tankHealth.m_CurrentHealth < tankHealth.m_StartingHealth){ Destroy(gameObject); tankHealth.m_CurrentHealth = tankHealth.m_CurrentHealth + healthBonus; } } } Μηπως φταει που εγω βαζω 2D collider σε 3D αντικειμενο ? Επισης αν χρησιμοπηοιησω Sphere για το health point μου και βαλω Sphere collider πρεπει να αλλαξω το παρακατω? //.. void OnTriggerEnter2D(Collider2D col){ //... } Ευχαριστω!
Moderators Kercyn Δημοσ. 22 Μαΐου 2018 Moderators Δημοσ. 22 Μαΐου 2018 Άμα ο κόσμος σου είναι 3D τότε όλοι οι colliders πρέπει να είναι 3D. Δεύτερον η προσέγγισή σου είναι λάθος. Στο pickup σου πρέπει να έχει μόνο ό,τι σχετίζεται με αυτό, στη συγκεκριμένη περίπτωση το πόσο health γεμίζει (και πιθανότατα και τον τύπο του pickup για να γλυτώσεις calls σε functions που βρίσκουνε τον τύπο του αντικειμένου). Έχοντας λοιπόν το prefab του pickup σου, βάζεις έναν trigger collider στον παίκτη σου που δουλειά του είναι να μαζεύει τα pickups. Αναλόγως του τι pickup μαζεύει, κάνει και την αντίστοιχη ενέργεια. Αν δει, πχ, ότι ο τύπος του pickup που μάζεψε είναι "health", τότε διαβάζει από το pickup πόσο health πρέπει να κάνει restore και το κάνει. Τέλος, μην κάνεις destroy το gameobject σου, κάνε το disable. Το να κάνεις create/destroy gameobjects είναι πολύ πιθανό να σου βγάλει performance issues αν ασχοληθείς παραπάνω. 1
matheostsik Δημοσ. 22 Μαΐου 2018 Μέλος Δημοσ. 22 Μαΐου 2018 30 λεπτά πριν, Kercyn είπε Άμα ο κόσμος σου είναι 3D τότε όλοι οι colliders πρέπει να είναι 3D. Δεύτερον η προσέγγισή σου είναι λάθος. Στο pickup σου πρέπει να έχει μόνο ό,τι σχετίζεται με αυτό, στη συγκεκριμένη περίπτωση το πόσο health γεμίζει (και πιθανότατα και τον τύπο του pickup για να γλυτώσεις calls σε functions που βρίσκουνε τον τύπο του αντικειμένου). Έχοντας λοιπόν το prefab του pickup σου, βάζεις έναν trigger collider στον παίκτη σου που δουλειά του είναι να μαζεύει τα pickups. Αναλόγως του τι pickup μαζεύει, κάνει και την αντίστοιχη ενέργεια. Αν δει, πχ, ότι ο τύπος του pickup που μάζεψε είναι "health", τότε διαβάζει από το pickup πόσο health πρέπει να κάνει restore και το κάνει. Τέλος, μην κάνεις destroy το gameobject σου, κάνε το disable. Το να κάνεις create/destroy gameobjects είναι πολύ πιθανό να σου βγάλει performance issues αν ασχοληθείς παραπάνω. Προσπαθησα να το αλλαξω λιγο ξεκινωντας με την γραμμη κωδικα που ελεγα και παραπανω και μετα τα υπολοιπα. Τωρα μου βγαζει αυτo: NullReferenceException: Object reference not set to an instance of an object HealthPickup.OnTriggerEnter (UnityEngine.Collider col) (at Assets/Scripts/HealthPickup.cs:16) (Συγγνωμη αλλα οντως ειμαι αρχαριος πρωτο 3ωρο unity κλεινω)
Moderators Kercyn Δημοσ. 22 Μαΐου 2018 Moderators Δημοσ. 22 Μαΐου 2018 Για κάνε έναν κόπο και βάλε εδώ το HealthPickup σε code tags. Αν και αυτό που σου λέει είναι ότι έχεις δηλώσει ένα object στο script σου το οποίο χρησιμοποιείς πιο κάτω αλλά δεν του έχεις δώσει κάποιο πραγματικό object από τον κόσμο σου. Πχ αν έχεις μια γραμμή public Collider c, τότε στον editor θα πρέπει να πεις ποιος collider είναι αυτός ο c (συνήθως με drag & drop). Εξοικιώσου πάντως λίγο με το UI του Unity και πώς δουλεύει, μόνο χρόνο θα κερδίσεις. Καταλαβαίνω ότι ίσως να είναι βαρετό και θες να τελειώνεις την εργασία σου και και και, αλλά άμα δεν ξέρεις έστω τα βασικά πράγματα για το πώς δουλεύει το εργαλείο σου θα χάσεις χρόνο και θα εκνευριστείς.
matheostsik Δημοσ. 22 Μαΐου 2018 Μέλος Δημοσ. 22 Μαΐου 2018 public class HealthPickup : MonoBehaviour{ TankHealth tankHealth; public float healthBonus = 50f; void Awake(){ tankHealth = FindObjectOfType<TankHealth>(); } void OnTriggerEnter(Collider col){ if(tankHealth.m_CurrentHealth < tankHealth.m_StartingHealth){ Destroy(gameObject); tankHealth.m_CurrentHealth = tankHealth.m_CurrentHealth + healthBonus; } } } Ενταξει δεν ετσι τα πραγματα,απλα ειναι κατι τελειως καινουριο και δε ξερω απο που να πρωτοαρχισω...καθε γκουγκλαρισμα δημιουργει απορια αντι για απαντηση
Moderators Kercyn Δημοσ. 22 Μαΐου 2018 Moderators Δημοσ. 22 Μαΐου 2018 Ε ναι ρε συ λογικό είναι να ψάχνεις μία απάντηση και να σου βγαίνουν 10 απορίες. Αυτό που έχεις βάλει στο awake δεν έχει κανένα απολύτως νόημα, πρέπει να κάνεις drag & drop το object που έχει component TankHealth πάνω στο πεδίο tankHealth του script σου. Έτσι όπως είναι θα σου έλεγα να το αφήσεις τελείως και να το γράψεις από την αρχή με καθαρό μυαλό, γιατί αυτό που έχεις κάνει τώρα είναι να προσπαθείς να κατανοήσεις και να υλοποιήσεις ταυτόχρονα, και αν πας να το διορθώσεις θα μπερδευτείς. Πέτα το script όπως είναι και ξεκίνα απ' την αρχή, διαβάζοντας: Τι είναι τα prefabs, πώς τα φτιάχνουμε και πώς τα χρησιμοποιούμε. Τι είναι οι trigger colliders. Object tags και ενδεχομένως layer-based collision. Είναι απλά κι εύκολα πράγματα τα οποία όμως αν κατανοήσεις, έστω και σε πρώτη φάση, θα σε βοηθήσουν πολύ στο να υλοποιήσεις αυτό που έχεις στο μυαλό σου. 1
Alithinos Δημοσ. 26 Μαΐου 2018 Δημοσ. 26 Μαΐου 2018 (επεξεργασμένο) Καταρχάς ένα πρόβλημα που βλέπω εγώ στο κώδικά σου είναι ότι καλείς τη Destroy() πριν ανεβάσεις τη ζωή του tank. Και disable να κάνεις, κάνε το ΑΦΟΥ ανεβάσεις τη ζωή. Πρώτα θα ανεβάσεις τη ζωή του tank και μετά θα βάλεις το pickup να καταστραφεί. Γιατί αλλιώς καταστρέφεις το pickup πριν προλάβει να ανεβάσει τη ζωή, και για αυτό δε δουλεύει. Σαφώς και θα σου βγάλει Null Reference, γιατί προσπαθείς να κάνεις κάτι με ένα αντικείμενο που έχεις ήδη απενεργοποιήσει / διαγράψει και δε το βρίσκει. Επεξ/σία 26 Μαΐου 2018 από Alithinos
matheostsik Δημοσ. 29 Μαΐου 2018 Μέλος Δημοσ. 29 Μαΐου 2018 Στις 26/5/2018 στις 7:37 ΠΜ, Alithinos είπε Καταρχάς ένα πρόβλημα που βλέπω εγώ στο κώδικά σου είναι ότι καλείς τη Destroy() πριν ανεβάσεις τη ζωή του tank. Και disable να κάνεις, κάνε το ΑΦΟΥ ανεβάσεις τη ζωή. Πρώτα θα ανεβάσεις τη ζωή του tank και μετά θα βάλεις το pickup να καταστραφεί. Γιατί αλλιώς καταστρέφεις το pickup πριν προλάβει να ανεβάσει τη ζωή, και για αυτό δε δουλεύει. Σαφώς και θα σου βγάλει Null Reference, γιατί προσπαθείς να κάνεις κάτι με ένα αντικείμενο που έχεις ήδη απενεργοποιήσει / διαγράψει και δε το βρίσκει. Καλησπερα εκανα καποιες μικροαλλαγες και καταφερα να λειτουργει τουλαχιστον το Destroy(); (και να εξαφανιζεται). Ομως οπω επες εχω ερρορ Null REference ενω τα εχω βαλει με την σωστη σειρα,destroy και αυξηση. Το λαθος αν εχω καταλαβει καλα ειναι οτι με το FindObjectOfType<> δεν "εντοπιζεται" το health του tank.
Alithinos Δημοσ. 29 Μαΐου 2018 Δημοσ. 29 Μαΐου 2018 5 ώρες πριν, matheostsik είπε Καλησπερα εκανα καποιες μικροαλλαγες και καταφερα να λειτουργει τουλαχιστον το Destroy(); (και να εξαφανιζεται). Ομως οπω επες εχω ερρορ Null REference ενω τα εχω βαλει με την σωστη σειρα,destroy και αυξηση. Το λαθος αν εχω καταλαβει καλα ειναι οτι με το FindObjectOfType<> δεν "εντοπιζεται" το health του tank. για βάλε τη νέα εκδοχή να δω πως είναι με τις μικροαλλαγές που έκανες.
matheostsik Δημοσ. 29 Μαΐου 2018 Μέλος Δημοσ. 29 Μαΐου 2018 10 ώρες πριν, Alithinos είπε για βάλε τη νέα εκδοχή να δω πως είναι με τις μικροαλλαγές που έκανες. Δεν εχει αλλαξει ο κωδικας οπως ειναι παραπανω απλα χωρις την if προς το παρων.Οι αλλαγες που εκανα ηταν στο να "εισαγω σωστα" to object μαζι με τον collider στο παιχνιδι.
Alithinos Δημοσ. 29 Μαΐου 2018 Δημοσ. 29 Μαΐου 2018 Πάντως έχε υπ' όψιν σου πως FindObjectOfType ίσως να μην είναι πάντα ο καλύτερος τρόπος να βρεις κάτι που υπάρχει στη σκηνή. Γιατί θα ψάξει να βρει 1 object. Αν όμως έχεις περισσότερα από 1 objects ίδιου τύπου ; Δηλαδή αν θες να έχεις 2 tanks, και το καθένα να έχει το δικό του TankHealth ; Θα σου επιστρέψει το πρώτο που θα βρει, και ίσως να μην είναι αυτό που χρειάζεσαι σε μια συγκεκριμένη περίπτωση. 1
matheostsik Δημοσ. 30 Μαΐου 2018 Μέλος Δημοσ. 30 Μαΐου 2018 (επεξεργασμένο) 21 ώρες πριν, Alithinos είπε Πάντως έχε υπ' όψιν σου πως FindObjectOfType ίσως να μην είναι πάντα ο καλύτερος τρόπος να βρεις κάτι που υπάρχει στη σκηνή. Γιατί θα ψάξει να βρει 1 object. Αν όμως έχεις περισσότερα από 1 objects ίδιου τύπου ; Δηλαδή αν θες να έχεις 2 tanks, και το καθένα να έχει το δικό του TankHealth ; Θα σου επιστρέψει το πρώτο που θα βρει, και ίσως να μην είναι αυτό που χρειάζεσαι σε μια συγκεκριμένη περίπτωση. Ωραια και πως θα το κανω να "εντοπιζει" το TankHealth και να ειναι και το συγκεκριμενο? EDIT:Μολις σκεφτηκα κατι διαφορετικο,μπορω να βαλω το destroy μονο στο σκριπτ του object και ολα τα υπολοιπα να τα προσθεση στο σκριπτ του τανκ. Επεξ/σία 30 Μαΐου 2018 από matheostsik
Moderators Kercyn Δημοσ. 30 Μαΐου 2018 Moderators Δημοσ. 30 Μαΐου 2018 Διάβασε πάλι το πρώτο μήνυμα που σου έγραψα, σου γράφω ακριβώς πώς να το κάνεις.
Alithinos Δημοσ. 1 Ιουνίου 2018 Δημοσ. 1 Ιουνίου 2018 Στις 30/5/2018 στις 8:52 ΜΜ, matheostsik είπε Ωραια και πως θα το κανω να "εντοπιζει" το TankHealth και να ειναι και το συγκεκριμενο? EDIT:Μολις σκεφτηκα κατι διαφορετικο,μπορω να βαλω το destroy μονο στο σκριπτ του object και ολα τα υπολοιπα να τα προσθεση στο σκριπτ του τανκ. Κοίτα εγώ τα health pickups που φτιάχνω τα κάνω να δουλεύουν ως εξής: 1) Καταρχάς βάζω σε gameObjects διάφορα tags. Στο δικό μου παιχνίδι ξέρω πχ. Ότι health pickups παίρνουν οι διάφοροι χαρακτήρες. Έχω φτιάξει λοιπόν το tag "Character" και το έχω βάλει στους χαρακτήρες. Εσύ ίσως να θες να φτιάξεις ένα tag "Tank" ή κάτι παρόμοιο. 2) Στην OnTriggerEnter, καταρχάς τσεκάρω αν το αντικείμενο το οποίο ακουμπάει το pickup είναι από αυτά που μπορούν να χρησιμοποιήσουν το health pickup. 3) Αν μπορούν, χρησιμοποιώ τη GetComponent() για να πάρω το component εκείνο που έχει τη ζωή του χαρακτήρα. 4) Ανεβάζω τη ζωή στο component που πήρα. Για παράδειγμα φαντάσου κάτι τέτοιο: OnTriggerEnter(Collider other) { if(other.gameObject.tag == "Character") // Έλεγχος αν ανήκει στη κατηγορία που παίρνουν το pickup. { CharacterHealth charHealth = other.gameObject.GetComponent<CharacterHealth>(); // Παίρνουμε το component με τη μεταβλητή ζωής. if(charHealth.currentHealth == charHealth.maxHealth) //Αν έχει full ζωή δε παίρνει το pickup. return; if(charHealth.currentHealth + pickupHP >= charHealth.maxHealth) // Αν η ζωή που έχει τώρα συν τη ζωή του pickup δίνουν μεγαλύτερο ή ίσο αριθμό από τη μέγιστη ζωή, γεμίζουμε τέρμα τη ζωή. charHealth.currentHealth = charHealth.maxHealth; else //Ενώ αν τέλος δεν ισχύει κάτι απ' τα παραπάνω, απλά προσθέτουμε τους πόντους του pickup στους ήδη υπάρχοντες πόντους ζωής. charHealth.currentHealth += pickupHP; } }
Moderators Kercyn Δημοσ. 1 Ιουνίου 2018 Moderators Δημοσ. 1 Ιουνίου 2018 (επεξεργασμένο) Θα μπορούσες να χρησιμοποιήσεις και min για να γλυτώσεις απ' όλα αυτά τα if/else. if (charHealth.currentHealth < charHealth.maxHealth) charHealth.currentHealth = Mathf.Min(charHealth.currentHealth + pickupHP, charHealth.maxHealth); Επεξ/σία 1 Ιουνίου 2018 από Kercyn
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα