Jump to content
Unity Insider Forum

IEnumerator funktioniert nicht


Strooja0108

Recommended Posts

Hi Leute,

 

ich würde gerne dafür sorgen das ein Text sich nach einer Sekunde ändert.Also ein delay erstellen. Ich habe gelesen dafür ist IEnumerator am besten.Allerdings funktioniert das nicht bei mir.Muss man dafür noch etwas bestimmtes hinzufügen?

Als Beispiel habe ich das hier erstellt:

 

IEnumerator test()
    {


    }

 

Er meckert über das Wort test. Und als Hilfe sagt er mir " "test" durch Eigenschaft ersetzen." Weiss jemand was ich falsch mache oder was mir fehlt?

PS: Ich was das für die volle funktionsweise noch mehr benötigt wird aber hier bekomme ich immer den Fehler.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Moin, es ist einfacher, den Code der ganzen MonoBehaviour zu posten, damit man ein Bild vom Code bekommt. :)

Aber was Du möchtest, sollte eigentlich so ähnlich lösbar sein:

//über der klasse einbinden, damit man IEnumerator nutzen kann
using System.Collections;
//...
private WaitForSeconds waitForSeconds = new WaitForSeconds(1f);

void Start()
{
  //irgendwo musst du die Coroutine starten
  StartCoroutine(Test());
}

IEnumerator Test()
{
  yield return waitForSeconds; //IEnumerator erwartet einen Rückgabetypen, dieser wartet eine Sekunde
  //dein text = neuer text
}
//...

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi devandart vielen dank für deine Hilfe.Ich habe das yield return scheinbar vergessen weshalb ich diese Fehler bekam. Sehe ich es richtig das ich für ein simplen Delay jedes mal eine neue Methode erstellen muss(ich weiss nicht, ob dass das richtige Wort bei einem IEnumerator ist.)?In meinem Beispiel habe ich 2 Buttons jeder Button soll eine andere onversation starten. Die einzelnen Texte möchte ich halt durch kleine Delays ein wenig angenehmer lesbar machen. Ich wollte aber bei beiden Buttons die selbe Methode aufrufen und per mitgegebener variable entscheiden welche conversation gestartet wird. Z.B so:

public void motherAnswer(int answer)
    {
        
        if (answer==0)
        {
           blabla.text=Hallo

            delay
           blabla.text=wie gehts;
        }

  if (answer==1)
        {
           blabla.text=Moin

            delay
           blabla.text=na du;
        }

    }

 

könntest du mir erklären wie und ob das möglich ist ohne das ich dafür eine IEnumerator Methode aufrufen muss,oder ob es möglich ist die in meinem Beispiel einzuarbeiten? Das ist nur ein Beispiel, am Ende werde ich deutlich mehr Buttons haben weshalb es sehr angenehm wäre wenn ich das zu wenigen Methoden zusammenfassen kann,wie in meinem Beispiel.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Da gibt's verschiedene Varianten. Statt deine Texte in deine Methode einzubauen, kannst du auch direkt die strings übergeben:

private IEnumerator DoMonologue(string[] texts, float delay)
{
  var wait = new WaitForSeconds(delay);
  
  textComponent.text = texts[0];
  for (var i = 1; i < texts.Length; i++)
  {
    yield return wait;
    textComponent.text = texts[i];
  }
}

Auf lange Sicht kannst du auch eine Klasse für Monologe oder Dialoge schreiben, und die stattdessen da rein tun. Da kannst du dann beliebig schick werden und verschiedenste Erweiterungen einbauen. Sei es unterschiedlich lange Zeiten pro Satz oder ein wechselndes Charakter-Portrait je nach Situation.

P.S. Du kannst deinen Code auch so lesbar machen, und zwar mit dem <>-Knopf ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

ah ok du meinst also den ganzen Dialog in einem array speichern und dann aufrufen. Ich denke  so viel muss es garnicht sein.Sind halt immer nur die gleichen zwei Personen und wenige Zeilen.Ist allerdings das gleiche Problem wie schon in einen meiner alten Threads. Ich habe mehrere Konversations Szenarien auf die man immer nur mit Ja oder Nein antworten kann. Dafür möchte ich natürlich immer die selben Buttons benutzen. Wie gebe ich jetzt zum einen den Button weiter (zurzeit ja einfach mit einer variable entweder 1 oder 0) Aber wie gebe ich ausserdem eine Variable weiter um zu wissen um welche Konversation es sich handelt. Du hast oben in deinem Beispiel 2 Übergabevariablen .Ist es möglich das man eine durch den Button onclick mitgibt und die andere von einem anderen Script gesetzt und übergeben wird. Ich möchte zum Beispiel folgendes machen. Das die Mutter einen zum essen ruft zu bestimmten Uhrzeiten(Morgens,Mittags,Abends).Je nachdem soll natürlich ein anderer Satz angezeigt werden. Man soll darauf immer per Button nur mit Ja oder Nein antworten können. Nach dem Button klick sollen je nach Button und je nach Uhrzeit unterschiedliche Antworten in einem Textfeld ausgegeben werden. Ist das mit den 2 ÜBergabevariablen eine valide Idee oder geht das smarter?

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Auch dafür würde ich das hier empfehlen:

vor 16 Stunden schrieb Sascha:

eine Klasse für Monologe oder Dialoge

Da kannst du nämlich dann wiederum weitere Monologe referenzieren, die dann als Folgemonologe gelten. Könnte z.B. als ScriptableObject so aussehen:

[AddComponentMenu]
public class Monologue : ScriptableObject
{
  public string text;
  public Monologue nextMonologueIfYes;
  public Monologue nextMonologueIfNo;
}

Obwohl... naja, geht natürlich auch wieder simpler, und du ersetzt die beiden "Monologue"-Felder durch string-Felder. Aber auch dann hast du schön den Eingangstext und die beiden Folgetexte an einem Ort.

Link zu diesem Kommentar
Auf anderen Seiten teilen

okay dann probier ich das vielleicht mal mit einer klasse. Aber dann für jeden der beiden knöpfe eine eigene methode aufrufen und eine variable mitschicken um zu erkennen um welche konversation es sich handelt richtg?Dieses benutzen der selben buttons für unterschiedliche konversationen ist mein Problem. Kannst du mir den Befehl sagen wie ich den übergangsparameter eines onclick button events von einem andere script aus verändern kann(oder die methode die aufgerufen wird vom onclick event)? in meinem beispiel soll am morgen der "ja" button die zahl 1 übergeben,mittags dann 3 und abends 5 . So das ich dann in der aufgerufenden methode mit dieser variable unterscheiden kann um welche konversation es sich handelt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Irgendwelche Zahlencodes umherschieben brauchst du niemals, und davon würde ich auch abraten.

Ich würde auch nicht zu viel Semantik auf den Button selbst schmeißen wollen. Stattdessen kann der Button einfach von einer Komponente die "Ja wurde gedrückt"-Methode aufrufen, und innerhalb dieser Methode schaust du dann einfach nach der Tageszeit.

Link zu diesem Kommentar
Auf anderen Seiten teilen

uh mensch ist da kompliziert. Ich verstehe schon irgendwie was du meinst aber scheinbar fehlt mir das know how um es anders umzusetzen. Du hast auf jeden fall eine gute idee das ich die tageszeit einfach in der "ja antwort" methode abfrage,dann kann ich das übergeben von variablen vergessen. Das Problem ist das es bei diesen drei Fragen zu dem essen gehen nicht bleibt. Zurzeit habe ich die Idee das ich ein "Event" script erstelle wo zum beispiel diese 3 events mit dem essen drin sind,aber auch noch andere die unabhängig vom essen sind. Auf jedes dieser event kann man nur mit ja und nein antworten und bei jedem hat dann ja und nein etwas anderes zur folge. Deswegen funktioniert deine lösung wunderbar für die essens events aber bei den anderen befürchte ich wird das nichts.Hier einmal mein script was ich bis jetzt habe. Die methode "mothereat" wird zurzeit von meinem time script aufgerufen zu bestimmten zeiten und übergibt dann die variable. Man erkennt das problem das ich ganz unten nicht wirklich unterscheiden kann ob der "ja" button bei der breakfast frage oder der lunch frage gedrückt wurde. Das würde ich halt gerne lösen und zudem den delay einbauen können.

 

 public void mothereat(int mealtime)
    {
        mothermessagelabel.SetActive(true);
        switch (mealtime)
        {

            case 1:
                mothermessage.GetComponent<Text>().text = "Hey  do you come down for breakfast?";
                break;
            case 2:
                mothermessage.GetComponent<Text>().text = "Hey  do you come down for lunch?";
                break;
            case 3:
                mothermessage.GetComponent<Text>().text = "Hey  do you come down for dinner?";
                break;
        }

//hier hätte ich zum beispiel gern ein delay

        playermessagelabel.SetActive(true);
        btnplayeranswerno.SetActive(true);
        btnplayeransweryes.SetActive(true);
    }

    //diese methode soll von den buttons aufgerufen werden.Wobei ich ja jetzt soweit bin das in zwei methoden zu teilen für jeden button eine.(hier ist es noch eine methode)
  

  public void mothereatAnswer(int answer)           

if (answer==0)
        {

//hier auch ein delay
           playermessage.GetComponent<Text>().text = "Yes I come down for breakfast";

         //hier wird noch mehr passieren als nur den text anzeigen

        }
        else if(answer==1)
        {

//hier auch ein delay
            playermessage.GetComponent<Text>().text = "No, thank you";

            //hier wird auch noch mehr passieren als nur den text anzeigen

        }

    }

Link zu diesem Kommentar
Auf anderen Seiten teilen

Versuche wirklich mal den <>-Knopf über dem Textfeld ;)

Dröseln wir das mal ganz entspannt auf. Wie schon gesagt, sind solche Zahlencodes doof und wirklich nicht nötig. Bei der Antwortmethode ("ja oder nein gedrückt") meinte ich ja schon, dass du da einfach mehrere Methoden haben kannst. Statt

public void MotherEat(int answer)
{
  if (answer == 0)
  {
    FOO
  }
  else if (answer == 1)
  {
    BAR
  }
}

machst du

public void MotherEatYes()
{
  FOO
}

public void MotherEatNo()
{
  BAR
}

Wenn du willst, kannst du so weiterprogrammieren. Grundsätzlich kann ich dir aber sagen, dass es immer besser ist, solche Strukturen in Daten zu definieren als in Code. Statt also lauter Methoden anzulegen, die alle auf dieselbe Art funktionieren, ist es besser, nur eine einzelne zu haben, die je nach Zustand des Objekts anders arbeitet. Im Optimalfall hast du dann am Ende kein einziges String-Literal mehr in deinem Code. Aber... das muss ja auch nicht alles auf einmal passieren. Solange du einen Weg findest, der für dich funktioniert, ist das schonmal gut. Du darfst dich dann halt nur nicht wundern, wenn du immer mehr schwierig zu lösende Probleme kriegst, je mehr du auf solchem "funktioniert irgendwie"-Code aufbaust.

Was ich noch wichtig fände, wären private Hilfsmethoden. Hier mal ein Beispiel:

public void Foo()
{
  if (something)
  {
    // warte 1 sekunde
    // ändere den text zu "Eins"
    // warte 1 sekunde
    // buttons erscheinen
  }
  else
  {
    // warte 1 sekunde
    // ändere den text zu "Zwei"
    // warte 1 sekunde
    // buttons erscheinen
  }
}

Die Kommentare stehen hier für zwei sehr ähnliche Abläufe, die sich nur minimal unterscheiden. In so einem Fall solltest du eine private Hilfsmethode schreiben, die diesen Ablauf durchführt, und die Unterschiede über Parameter einstellbar hat:

public void Foo()
{
  if (something)
  {
    ShowTextAndButtons("Eins");
  }
  else
  {
    ShowTextAndButtons("Zwei");
  }
}

private void ShowTextAndButtons(string text)
{
  // warte 1 sekunde
  // ändere den text zum wert des text-Parameters
  // warte 1 sekunde
  // buttons erscheinen
}

Auf diese Weise musst du den Code nicht immer kopieren. Und wenn er sich in der Zukunft doch mal ändern soll, musst du nicht an vielen Stellen, sondern nur an einer einzigen diese Änderung vornehmen.

Genau so eine private Hilfsmethode hatte ich dir eingangs gepostet. Mit ein paar Parametern kannst du wunderbar eine Coroutine erstellen, die sich immer wieder verwenden lässt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

hey danke für die fixe antwort.Jepp wie ich geschrieben hatte war meinte idee auch das ich ja und nein in unterschiedliche methoden packe um das schonmal übersichtlicher zu machen.wenn ich dich richtig verstehe soll ich in der ja und nein methode dann weitere methoden benutzen um es übersichtlicher zu machen richtig?Das werde ich auf jeden fall versuchen, befürchte aber das ich nachher dann 30 methoden habe was auch nicht mehr super übersichtlich ist.Aber das ist erstmal nebensache denke ich.Denn ich habe noch immer nicht die Lösung gefunden wie ich erkenne zu welcher Konversation die Buttons gerade gehören.Sagen wir ich habe für den Ja und Nein button jeweils jetzt eine methode. Da ich aber immer die selben Buttons benutzen möchte jedoch unterschiedliche Sachen ausgeführt werden soll wenn ich "Ja" drücke , je nachdem welches Event gerade getriggerd wurde verstehe ich nicht wie ich das umsetzen soll. Ich dachte halt das die variable die der Ja button mitgibt  verändert wird, je nachdem welches event gestartet wurde. Ich weiss aber nicht wie das geht. Hab jetzt nur was von dem onclick listener gehört mit dem man die variable verändern soll über umwege.Ist das die einzige möglichkeit? Es ist leider nicht damit getan die strings oder variablen mitzugeben oder so.Ich habe oben nur ein Beispiel aufgezeigt aber je nach Event passieren wirklich komplett unterschiedliche Sachen wenn man auf den Ja Button klickt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Warum denn irgendetwas am Button ändern, wenn du's auch gleich da ändern kannst, wo es wichtig ist?

public enum TimeOfDay
{
  Morning, Noon, Evening
}

private TimeOfDay timeOfDay;

public void ChangeTimeOfDay(TimeOfDay newTimeOfDay)
{
  timeOfDay = newTimeOfDay;
  
  switch (timeOfDay)
  {
    case TimeOfDay.Morning:
      someText.text = "Guten Morgen";
      break;
    // ...
  }
}

public void AnswerYes()
{
  switch (timeOfDay)
  {
    case TimeOfDay.Morning:
      // Morgens ja gesagt
      break;
    // ...
  }
}

Mit so Monolog-Objekten geht das wie gesagt wesentlich hübscher, aber das ist erstmal das, was du willst. Statt den Button irgendeine andere Methode aufrufen zu lassen oder Parameter-Wert zu ändern, einfach den Zustand des Objekts ändern, an dem du die Methode aufrufst.

Link zu diesem Kommentar
Auf anderen Seiten teilen

puhhh okay .Also verstehe ich das richtig.Die idee ist,dass ich die buttons so lasse wie sie sind und jeder der buttons eine eigene methode aufruft. Um festzustellen welches event getriggerd wurde gebe ich eine variable dem event mit und überprüfe in der button methode um welches event es sich handelt richtig? Witzig die idee hatte ich auch schon dachte aber es geht bestimmt smarter :D . Aber das ist das was du meinst richtig???

 

Zu dem Delay: Anstatt dann eine ja und nein methode zu erstellen kann ich auch eine IEnumerator "methode" erstellen und die benutzen,damit ich das delay benutzen kann? Und zusätzlich natürlich StartCoroutine(Test()); in die Start methode.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 6 Stunden schrieb Strooja0108:

Um festzustellen welches event getriggerd wurde gebe ich eine variable dem event mit

Ne, eben nicht :)

Der Button gibt überhaupt nichts mit. Die Variable "timeOfDay" ist Teil des Zustands dieser Komponente und wird nicht als Parameter mitgegeben.

vor 6 Stunden schrieb Strooja0108:

Zu dem Delay:

Warum willst du dein Delay in "Start" starten? Du willst doch die Stoppuhr dann starten, wenn der Knopf gedrückt wurde?

Link zu diesem Kommentar
Auf anderen Seiten teilen

:D hab mich vielleicht falsch ausgedruckt.Nein der button gibt garnichts mit er startet nur eine methode. Welches event getriggerd wird, wird von einer variable eines anderen script übergeben. Wenn du  das nicht so meinst dann kapier ichs nicht ganz ^^.Könntest du dein beispiel vielleicht nochmal erklären. Jepp mit dem Delay hast du absolut recht hab es jetzt in einer der methoden gestartet und das funktioniert wunderbar.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...