Jump to content
Unity Insider Forum

Ein PowerUp durchwechseln


RipperRoo

Recommended Posts

Hi,

Also ich will ganz einfach n PowerUp, was sich alle x sekunden ändern kann, man kennt das evtl. von den alten SHMUPs, wo man erst nen Schuss Upgrade hat und nach paar sekunden wechselt das eben zu nem anderem Upgrade.

 

Ich wollte fragen, ob mein Ansatz gut ist oder obs da nen viel besseren und eleganteren Weg gibt:

 

Ich dachte mir ich teil das nun so auf, ein PowerUp script auf dem powerup, das nur den wechsel von sprite auf das jeweilige powerup regelt und einen string, der dann per SendMessage an ein PowerUpManager Script gehen würde.

 

Der PowerUpManager würde dann darauf reagieren, je nachdem welches powerup eben nun grade eingesammelt wurde, und die entsprechenden stats in den andern scripts ändern. Wobei ich das so halten will, dass man jedes powerup maximal 3 mal einsammeln kann, danach würde es nur noch zusätzliche score geben. Das würde ich dann aber alles im PowerUpManager regeln.

 

PS: hatte zuerst noch ein Problem mit dem PowerUp script, warum ich eigentlich den Thread eröffnen wollte, aber beim Tippen, fiel mir auf was das Problem mit der Coroutine ist. Manchmal hilft es wirklich sein Problem zu beschreiben, dabei merkt man es dann vllt schon selbst lol.

 

 

EDIT: so noch der Code den ich momentan verwende, ohne könnt ihr ja nicht sehen, was man verbessern könnte^^:

 

using UnityEngine;
using System.Collections;
using Enum = System.Enum;
public class PowerUps : MonoBehaviour
{
public float changeTime = 2.0f;
public bool changing = true;
public Sprite[] powerUpSprites;
public enum PowerUp
{
 Damage,
 Firerate,
 Turrets,
}
private SpriteRenderer sr;
public PowerUp powerUp;
// Use this for initialization
void Start ()
{
 sr = GetComponentInChildren<SpriteRenderer> ();
 StartCoroutine (CyclePowerUp ());
}
void OnTriggerEnter2D ()
{
 GameObject.FindGameObjectWithTag ("Player").SendMessage ("PowerUp", powerUp);
 gameObject.Recycle ();
}
IEnumerator CyclePowerUp ()
{
 if (changing) {
  while (true) {
   SwitchPowerUp ();
   Debug.Log ((int)powerUp + " " + powerUp);
   yield return new WaitForSeconds (changeTime);
   powerUp++;
   if ((int)powerUp > Enum.GetValues (typeof(PowerUp)).Length - 1)
 powerUp = 0;
  }
 }
}
void SwitchPowerUp ()
{
 switch (powerUp) {
 case PowerUp.Damage:
  sr.sprite = powerUpSprites [(int)powerUp];
  //Debug.Log ("Damage Power Up");
  break;
 case PowerUp.Firerate:
  sr.sprite = powerUpSprites [(int)powerUp];
  //Debug.Log ("Firerate Power Up");
  break;
 case PowerUp.Turrets:
  sr.sprite = powerUpSprites [(int)powerUp];
  //Debug.Log ("Turret Power Up");
  break;
 }
}
}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Habs nur kurz überflogen, bin einfach schon zu K.O. mich damit jetzt noch richtig auseinanderzusetzen. ^^

Aber was mir sofort ins Auge fiel: "SendMessage", ich würde dir davon abraten die Funktion zu benutzen! "SendMessage" ist einfach verdammt langsam.

 

 

MfG Artery

Link zu diesem Kommentar
Auf anderen Seiten teilen

void OnTriggerEnter2D ()
{
 GameObject.FindGameObjectWithTag ("Player").SendMessage ("PowerUp", powerUp);
 gameObject.Recycle ();
}

 

Was machst du denn hier?

Übergib doch einen Collider2D Parameter und mach hier "GetComponent<Player>()...."

Sonst durchsuchst du nach jedem Einsammeln die komplette Szene nach dem Player ^^

 

Und in deinem CyclePowerUp bei dieser while(true) Schleife.. ^^

Ist das Absicht, dass du sobald bei einem PowerUp changing auf true ist, das permanent durchläuft? (selbst wenn changing wieder auf false gesetzt wird)

Bzw. wird changing überhaupt irgendwann benötigt? Ich sehe nicht, dass es jemals irgendeinen Nutzen hat, denn du setzt es default auf true, fragst es 1x direkt zum Start ab und danach wird es nie wieder benutzt ^^

 

Und zum Thema ob das sinnvoll ist:

Ja ich denke schon, ich würde das auch so machen ^^

Auch wenn sich mir noch nicht 100%ig erschließt wie du das mit dem Wechseln meinst, aber wenn du es so machst wie ich es mir denke dann ja ^^

Nur um sicher zu gehen.. du hast ein PowerUp das irgendwo in der Luft rumschwebt und dauernd sein Sprite wechselt und das kannst du einsammeln richtig?

Und je nachdem welches Sprite zum Zeitpunkt des Einsammelns aktiv war, aktivierst du das entsprechende PowerUp am Player.. oder? ^^

 

@edit:

SendMessage() würde ich hier auch nicht benutzen.

Was mir irgendwie auch jetzt erst auffällt..

Wieso hast du eigentlich überhaupt eine Switch-Case Verzweigung in "SwitchPowerUp" wenn du in jedem case das exakt gleiche machst? ^^

Link zu diesem Kommentar
Auf anderen Seiten teilen

void OnTriggerEnter2D ()
{
 GameObject.FindGameObjectWithTag ("Player").SendMessage ("PowerUp", powerUp);
 gameObject.Recycle ();
}

Das finde ich hier nicht so gut (mal abgesehen von SendMessage und FindGameObject usw). Hier entscheidet das PowerUp, dass ein anderes Objekt die Goodies bekommt. Normalerweise würde ich das dem Player zuordnen. Der Player rennt in einen Trigger. Hat der Collider eine Component "PowerUp", dann reagiert der Player entsprechend darauf. So wie du es geschrieben hast, bekommt der Player jedesmal den Powerup, wenn irgendwas den Trigger berührt. Wenn du später andere bewegliche Sachen einbaust und die zufällig in der Nähe von so nem Trigger sind -> gut für den Player.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Danke erstmal für die schnellen antworten :)

 

Aber was mir sofort ins Auge fiel: "SendMessage", ich würde dir davon abraten die Funktion zu benutzen! "SendMessage" ist einfach verdammt langsam.

 

OK, Danke! Also grundsätzlich ohne sendmessage? Habe das nun in mehreren Tutorials gesehn, meist für applydamage(), wie würde man das sonst machen?

 

Was machst du denn hier?

Übergib doch einen Collider2D Parameter und mach hier "GetComponent<Player>()...."

Sonst durchsuchst du nach jedem Einsammeln die komplette Szene nach dem Player ^^

 

Oh Gott stimmt, ich kann über den Collider ja direkt ans component kommen, danke dir! Wenn man programmiert sieht man manchmal den Wald vor lauter Bäumen nicht.

 

Und in deinem CyclePowerUp bei dieser while(true) Schleife.. ^^

Ist das Absicht, dass du sobald bei einem PowerUp changing auf true ist, das permanent durchläuft? (selbst wenn changing wieder auf false gesetzt wird)

Bzw. wird changing überhaupt irgendwann benötigt? Ich sehe nicht, dass es jemals irgendeinen Nutzen hat, denn du setzt es default auf true, fragst es 1x direkt zum Start ab und danach wird es nie wieder benutzt ^^

 

Ja, ist beabsichtigt, für den fall, dass ich ein PowerUp doch mal nicht durchiterieren möchte, sondern es bleiben soll wie es ist. Darum einmal der Check, falls true(was standard ist weils ja auch der normalfall sein soll) eben iterieren, falls false dann nicht.

 

Und zum Thema ob das sinnvoll ist:

Ja ich denke schon, ich würde das auch so machen ^^

Auch wenn sich mir noch nicht 100%ig erschließt wie du das mit dem Wechseln meinst, aber wenn du es so machst wie ich es mir denke dann ja ^^

Nur um sicher zu gehen.. du hast ein PowerUp das irgendwo in der Luft rumschwebt und dauernd sein Sprite wechselt und das kannst du einsammeln richtig?

Und je nachdem welches Sprite zum Zeitpunkt des Einsammelns aktiv war, aktivierst du das entsprechende PowerUp am Player.. oder? ^^

 

Jep, exakt so!

 

 

@edit:

SendMessage() würde ich hier auch nicht benutzen.

Was mir irgendwie auch jetzt erst auffällt..

Wieso hast du eigentlich überhaupt eine Switch-Case Verzweigung in "SwitchPowerUp" wenn du in jedem case das exakt gleiche machst? ^^

 

Ah ok SendMessage scheint echt ein Teufel zu sein, wusste ich bisher nicht :)

WIe gesagt, was soll ich stattdessen machen ?

 

@switch case

...

... *kopf -> wand*

ohje, ich hab mit nem switch case angefangen, weil ich dachte ich müsste jetzt für jede sprite Variante nen neuen Befehl machen. Dann kam mir aber die Idee enums zu verwenden und damit ein sprite array, was über den entsprechenden enum angesprochen wird. Ausserdem wusste ich noch nicht, dass ich auch einfach den enum im andern script als parameter empfangen kann. Daher dachte ich, ich müsste noch jedes mal eine Hilfsvariable auf den entsprechenden wert umstellen, um den Wert dann via sendmessage an den PowerUpManager weiterzuleiten. Habs dann aber einfach mal kurz ausprobiert mit dem enum als Parameter und es ging dann. Weiterhin konnte ich durch den Switch Case mit dem Debug, gut testen ob es tatsächlich wechselt. Und falls ich für die unterschiedlichen Fälle noch was anders machen würde, bräuchte ich das ja auch wieder.

Aber Hast recht, so wie es momentan da steht ist das natürlich völlig redundant und sollte noch geändert werden.

Bin halt noch Anfänger was eigene Scripte angeht, bisher hab ich eher nach Tutorial gearbeitet und die machen oft ähnlichen quatsch wie ich :D

 

Danke dir Tiwaz!!

 

void OnTriggerEnter2D ()
{
 GameObject.FindGameObjectWithTag ("Player").SendMessage ("PowerUp", powerUp);
 gameObject.Recycle ();
}

Das finde ich hier nicht so gut (mal abgesehen von SendMessage und FindGameObject usw). Hier entscheidet das PowerUp, dass ein anderes Objekt die Goodies bekommt. Normalerweise würde ich das dem Player zuordnen. Der Player rennt in einen Trigger. Hat der Collider eine Component "PowerUp", dann reagiert der Player entsprechend darauf. So wie du es geschrieben hast, bekommt der Player jedesmal den Powerup, wenn irgendwas den Trigger berührt. Wenn du später andere bewegliche Sachen einbaust und die zufällig in der Nähe von so nem Trigger sind -> gut für den Player.

 

Ich hab das PowerUp in ein eigenständiges Layer, dass nur mit dem Player Layer collidiert.

Ist das nicht ratsam?

 

Und warum würdest du es so rum machen, dass der Spieler reagiert wenn er in eine PowerUp komponente reinrennt?

Selbst wenn ich auf den zusätzlichen Layer verzichten würde, hätte ich es vermutlich trotzdem so gemacht, dass beim PowerUp Collider gecheckt wird ob das auslöende Objekt ein "Player" tag hat.

wäre das auch nicht gut?

 

 

 

Vielen Dank für eure Kritik, hoffe ihr könnt nochmal kurz was dazu sagen :)

Danke euch!

Link zu diesem Kommentar
Auf anderen Seiten teilen

Und warum würdest du es so rum machen, dass der Spieler reagiert wenn er in eine PowerUp komponente reinrennt?

 

Modelliere (Codiere) es doch so wie es in der Wirklichkeit wäre ^^

Wenn du auf der Straße eine Euromünze findest springt die ja auch nicht in deinen Geldbeutel sondern du nimmst sie auf ^^

 

Zumal es (finde ich) schöner und übersichtlicher ist wenn du in deine OnTriggerEnter Methode auf deinem Player schaust und direkt eine Übersicht bekommst womit dein Player wie reagiert.

 

Und zu dem Thema wie du das mit SendMessage anders machen kannst..

Öhm.. ruf doch einfach die Methode mit dem Parameter auf? :D

void OnTriggerEnter2D(Collider2D col){
  if(col.GetComponent<Player>()){
 col.GetComponent<Player>().PowerUp(powerUp);
  }
}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das mit der Euromünze war ein sehr guter Vergleich, Tiwaz.

 

Der Vorteil, wenn sich der Player drum kümmert, ist der, dass z.B. auch ein Gegner das Powerup aufheben kann und darauf reagiert (z.B. zerstören, umwandeln, selbst benutzen whatever). Auch wenn das bei deinem Spiel jetzt keine Rolle spielt, sollte die Verantwortlichkeit bei dem liegen, dem sie eigentlich zusteht.

 

Da gibts Powerups mit bestimmten Stats, und es gibt Objekte, die unterschiedlich mit den Powerups interagieren. Das ist logisch. Das das Powerup selbst die Sachen verwaltet, ist unlogisch. Die Euro-Münze hat einen Wert und ein Gewicht. Wenn der Player mit der Euro-Münze kollidiert, entscheidet er, was er damit macht. Einstecken, fortkicken, anmalen, ausgeben, je nach Tastendruck. Der Spieler kann vielleicht auch mal entscheiden, dass er das Powerup nicht will. Dem Powerup kann das egal sein.

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 2 years later...

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...