Jump to content
Unity Insider Forum

Assign zur Laufzeit


nordseekrabe
 Share

Recommended Posts

Moin,

bin auch wieder einmal in einer Sackgasse. Problem: aus einer Liste mit Ortsnamen wird mittels Random ein Ort ausgewählt:

              System.Random random = new System.Random();    int index = random.Next(TheCities.Count);  int key = TheCities.Keys.ElementAt(index);  collectedOfAll = pair.Key.ToString();

              collectedOfAll = pair.Value; (entweder Zahl oder Ortsname möglich)

Zu jedem Ort gehört ein "geslicetes" Sprite. Auch diese Sliceparts sind wieder in einer Liste mit 9 Elementen (List<GameObject> partOfPictures). Es gelingt mir partout nicht, auf diese Pictureparts zuzugreifen, um sie auf dem Bildschirm darzustellen (mit z.B.picturePart2.SetActive(true)). Wenn ich es richtig verstehe, gelingt mir also nicht, zur Laufzeit die Teilbilder des passenden randomisierten Ortsbild dem Inspektor zuzuweisen. Der Inspektor zeigt 9 Elemente aus der Codierung "public List<GameObject> partOfPictures;) Möglicherweise ist es schwieriger, als man denkt, oder ich stehe nur (blöd) auf dem Schlauch. Ich bitte freundlichst um Hilfe (Tipps, Anregungen), falls meine Infos überhaupt ausreichen.

Grüße von der Ostseeküste

Peter

Link to comment
Share on other sites

Moin zusammen,

habe eine Idee, ob das klappt, mal ausprobieren. Habe in der Hierarchy für jeden Ort ein Empty GO erstellt, diesem als Children die 9 Teilbilder des Ortsbildes hineingeschoben. In einem Script jetzt für jeden Ort eine List<GameObject> partOfPicture erstellt; public natürlich...voila , im Inspector erscheinen diese und ich kann die richtigen Teilbilder von der Hierarchy im Inspector zuweisen. Soweit so gut, wie es mit der Codierung zum Aufruf des richtigen Zufallsteilbildes des Zufallsortes aussieht, ist ein nächster Schritt.

Beste Grüße von der regnerischen Ostseeküste

Peter

Link to comment
Share on other sites

Moin,

die Profis unter Euch haben natürlich gleich erkannt, dass mit obiger Idee mein Problem nicht gelöst ist. Denn im Inspector erscheinen die Teilbilder einer jeden Liste mit dem Ortsnamen. Völlig außen vor bleibt meine "List<GameObject> partOfPictures = new List<GameObject>(9);", die ich doch für das Randomisieren der 9 Teilbilder benötige. Entsprechend erhalte ich auch die Fehlermeldung, dass  "the variable partOfPictures has not been assigned". Also zeigt sich für mich die ungelöste Aufgabe, wie den Ortsnamen der Zufallssauswahl mit "seinen" 9 Teilbildern verknüpfen ? 

Hoffe auf einen Tipp, wie ich hier weiter vorgehen sollte... wollte mit meiner Anfrage eigentlich nicht nur "laut" denken.

Besten Dank

Peter

Link to comment
Share on other sites

Moin!

Ich hab bisher nicht geantwortet, weil ich nicht viel geschlafen habe und Schwierigkeiten hatte, dein Problem zu verstehen. Das sage ich jetzt auch, weil ich mir immer noch nicht so sicher bin :) Mir hilft's immer, wenn Posts gründlich formatiert sind. Code kannst du z.B. hübscher einfügen, indem du über dem Eingabefeld, neben dem Unity-Symbol auf den <>-Knopf drückst.

Aber mal zur Frage: Verstehe ich das richtig, dass du gerade eine Liste von Infos haben willst, und jeder Eintrag der Liste soll mehrere Daten miteinander verknüpfen? So nach dem Motto "diese Grafik(en) gehören zusammen bzw. zu jenem Stadtnamen"?

Link to comment
Share on other sites

Moin,

danke, Sascha, für Deine Reaktion. Ich verstehe, dass es oft schwierig ist, ein Problem nachvollziehbar darzustellen, insbesondere da man ja auch nicht das komplette Projekt übersenden will. Inzwischen habe ich noch weiter "gegrübelt" und versuche das Problem zu lösen, indem ich jedem Ortsnamen in der Hierarchy das Script, dass die "Liste<GameObject> partOfPictures" beinhaltet, zugewiesen habe. Jetzt habe ich tatsächlich für jeden Ort eine Liste mit 9 Elementen, die mit den 9 Bildteilen in der Hierarchy assigned werden. Mal sehen, ob das so klappt.

Stand: Ich habe ein Liste (besser ein Dictionary<int, string>) mit zahlreichen Orten und deren geslicten Sprites. Die Auswahl eines Ortes erfolgt über Random...dann habe ich einen Namen. Bis hierhin funktioniert es. Eine weitere Liste (List<GameObject> partOfPictures) hat 9 Elemente (für die 9 Teilbilder aus dem Slice). Jetzt habe ich das Problem, wie den erhaltenen Ortsnamen mit den passenden Bildteilen verbinden ? Wie oben beschrieben, versuche ich nun, mit Verknüpfung des Scriptes (List<GameObject> partOfPictures) zu jedem Ortsobjekt in der Hierachy die 9 Bildelemente korrekt zuzuweisen.

Melde mich natürlich, wenn mein Procedere so nicht funktioniert.

Erstmal besten Dank (und weiterhin gute Erholung, Sascha)

Peter    

Link to comment
Share on other sites

Die Antwort fand ich jetzt leider wieder etwas undeutlich, werte sie aber als "ja" :)

Du kannst selber Klassen oder Structs definieren, die einfach eine Ansammlung zusammengehöriger Daten beinhalten. Jede Instanz deiner Klasse/Struct ist dann ein Datensatz, und diese Datansätze kannst du dann in einer Tabelle sammeln.

[System.Serializable]
private struct City
{
  public string name;
  public Sprite[] sprites;
}

[SerializeField]
private City[] cities;

Ein Dictionary<int, T>, wo die Schlüssel direkt die Zahlen 0-N sind, braucht man nicht - einfach eine Liste oder ein Array stattdessen nehmen.

Wir haben jetzt also ein Array mit "City"-Instanzen. Und jede Davon enthält einen Namen und wiederum ein Array von Sprites.

Zugreifen kannst du dann so darauf:

cities[cityIndex].name
cities[cityIndex].sprites.Length
cities[cityIndex].sprites[spriteIndex]

Das [System.Serializable] bewirkt, dass Unity deine Struct-Instanzen serialisieren kann (also in Szenen oder Prefabs speichern kann). Das wiederum bewirkt, dass du die Dinger im Editor anlegen und editieren kannst.

Link to comment
Share on other sites

Moin, moin,

das ist wieder einmal superklasse... professionell, halt. Habe gleich in meinem Projekt umgebaut. Da ich nach der Randomisierung das ausgewählte Objekt entfernen möchte ( es soll ja nicht zufällig ständig derselbe Ort ausgewählt werden) muss ich statt Arrays Listen wählen ( cities.Add(new City() {name = "Aachen"});). Dann wird für die Ortsauswahl das so aussehen:    var collectedOne = cities[UityEngine.Random.Range(0, cities.Count)];  Für die Bildteile ergibt sich

                                                     var collectedPart = cities[collectedOne].sprites[UnityEngine.Random.Range(0, 9)];

Ein Problem bleibt, collectedPart ist kein GameObject, sollte es aber sein, da  "collectedPart.SetActive(true)" das Teilbild zur Darstellung bringen soll.

Ein ganz großes Stück weiter, dank Deiner Hilfe, Sascha. Werde natürlich nun weiter "basteln", laienhaft, versteht sich, mit Try and Error. Es fehlt halt als Basis ein komplettes Informatikstudium; bin/ war nur einfacher Mediziner.

Beste Grüße an alle

Peter

Link to comment
Share on other sites

Eine der Ideen bei Unity ist, dass du deine Daten von deinem Code trennst. Ist generell eine gute Idee. Deshalb hat ja Unity auch diese Funktionalität, dass du serialisierte Felder definieren kannst, dessen Werte du dann im Editor einstellst. Du kannst dich dann in deinem Code wunderbar auf die Daten beschränken, die sich während der Laufzeit ändern.

// Die Indices aller Städte, die noch nicht gezogen wurden, stehen hier drin
private readonly List<int> availableCityIndices = new List<int>();

private void Start()
{
  // Die Indices aller Städte werden in die Liste gefüllt
  for (var i = 0; i < cities.Length; i++)
  {
    availableCityIndices.Add(i);
  }
}

public void PickRandomCity()
{
  // Nimm einen zufälligen Index aus der Liste noch verfügbarer Indices
  var listIndex = Random.Range(0, availableCityIndices.Length);
  var cityIndex = availableCityIndices[listIndex];
  
  // Lösche den gezogenen Index aus der Liste, damit er nicht nochmal gezogen wird
  availableCityIndices.RemoveAt(listIndex);
  
  Display(cities[cityIndex]);
}

Der Code sieht vielleicht auf den ersten Blick komplizierter aus als deiner, aber glaub mir: Auf Dauer ersparst du dir ne Menge Kopfschmerzen, wenn du deine Daten im Editor einstellst statt im Code, und diese Daten dann auch nicht mehr von deinem Code durcheinander gebracht werden.

vor 4 Stunden schrieb nordseekrabe:

Ein Problem bleibt, collectedPart ist kein GameObject, sollte es aber sein, da  "collectedPart.SetActive(true)" das Teilbild zur Darstellung bringen soll.

Öh ja, geht im Zweifelsfall beides. Du kannst auch einfach 9 SpriteRenderer-GameObjects haben, und dein Script teilt jedem das korrekte Sprite der gezogenen Stadt zu.

Das hat den Vorteil, dass du nicht für jede Stadt erstmal durch den nervigen Prozess gehen musst, deine Szene um eine weitere Kopie deiner GameObject-Hierarchie zu erweitern.

[SerializeField]
private SpriteRenderer[] pictureParts;
private void Display(City city)
{
  for (var i = 0; i < pictureParts.Length; i++)
  {
    pictureParts[i].sprite = city.sprites[i];
    pictureParts[i].gameObject.SetActive(true);
  }
}

Ist halt etwas unschön, dass du immer darauf achten musst, dass du genau 9 Sprites hast und auch immer 9 GameObjects im "pictureParts"-Array sind. Aber das hübscher zu machen, würde die Komplexität deines Codes leider direkt ein bisschen explodieren lassen.

Link to comment
Share on other sites

Moin, 

das ist schon beeindruckend, was bei entsprechendem Wissen aus einem schlechten Code zu machen ist. Insgesamt konnte ich die Vorschläge gut umsetzen. Unklar bleibt nur SpriteRenderer[] pictureParts ? Was muss hier zugewiesen werden ? Für jeden Ort gibt es 9 SpriteElemente, die zugewiesen werden. PictureParts-Array gibt es nur einmal, wofür ? Und wo kann ich bei Deinem Code die passenden Koordinaten(x,y) für jedesTeilbild hinzufügen ?  

Es bleibt spannend, und  ich bei der Stange.

Schönen Abend für alle

Peter

Link to comment
Share on other sites

Hier kann es sein, dass ich nicht ganz verstanden habe, was dein Ziel ist, und dir entsprechend unpassenden Code gegeben habe.

Ich hab das so verstanden, dass du zu jedem Zeitpunkt immer maximal 9 Bilder anzeigen willst. Diese 9 Bilder werden von 9 SpriteRenderern angezeigt, die jeder auf jeweils einem GameObject sitzen.

Dein Ansatz war, soweit ich das verstanden habe, dass du diese 9 GameObjects jeweils ein Mal für jede Stadt in deiner Szene hast; also einen ganzen Haufen GameObjects. Mein Ansatz dagegen ist, dass du einfach nur einmalig neun GameObjects in deiner Szene hast, und die 9 SpriteRenderer darauf im richtigen Moment einfach neue Sprites zum Anzeigen in die Hand kriegen. Deshalb gibt es pictureParts nur ein Mal, und da kommen eben genau die 9 SpriteRenderer rein, die du in deiner Szene vorbereitet hast.

Wenn das nicht zu dem passt, wie dein Spiel funktionieren soll, dann müssen wir da noch was ändern :)

Link to comment
Share on other sites

Besser und einfacher ist es wohl, kurz den Spielablauf zu skizzieren:

         Der Spieler muss nach dem Start mit dem Button "Zeige Teilbild" das 1. Teilbild aufrufen. Dabei hat die Logik bereits die Auswahl des Ortes (ein Name aus ca. 100) ausgeführt, und es wird dieses 1. Teilbild von dem Auswahlort gezeigt. Jetzt kann der Spieler bereits den Ortsnamen im Inputfield eintragen, stimmt die Ansage, werden alle Teilbilder aktiviert, das komplette Ortsbild wird gezeigt. Durch den Button "Beschreibung" kann die dazu gehörige Description aufgerufen werden. Stimmt die Angabe des Spielers nicht, kann er mit "Zeige Teilbild" das nächste Teilbild aufrufen, bis er lösen kann oder alle 9 Teilbilder sichtbar sind. Die Auswahl eines Teilbildes erfogt natürlich auch nach Zufallsgenerator. Als zusätzliche Gestaltung kommt dann noch ein Score hinzu, der je nach benötigter Anzahl von Clicks mehr oder weniger Punkte hinzufügt. 

Mit Deinem vorgeschlagenen Code kommt man gut bis zur Zufallsauswahl des Ortes, jetzt muss dieser Ortsname mit den 9 Teilbildern verknüpft werden, die nach Zufall wiederum einzeln aufgezeigt werden. Dieser Schritt ist  auch bei meinem ursprünglichen Code das Problem gewesen.

Danke, Sascha, für Deine Zeit und Geduld.

Gruß von der Ostseeküste

Peter

Link to comment
Share on other sites

vor 4 Stunden schrieb nordseekrabe:

Danke, Sascha, für Deine Zeit und Geduld.

Kein Ding ;)

Dann stimmt meine Annahme ja aber. Du hast immer maximal 9 Bilder zur Zeit auf dem Bildschirm. In so einem Fall bringt es mehr Nach- als Vorteile, mehr als 9 SpriteRenderer in der Szene zu haben. Anstatt bei 100 Städten á 9 Bildern 900 Objekte in deine Szene zu schmeißen, mach dir nur die 9 Objekte und schreibe dein Script so, dass diesen Objekten immer die Sprites deiner aktuellen Stadt zugewiesen werden.

Genau das macht dieser Code von weiter oben:

private void Display(City city)
{
  for (var i = 0; i < pictureParts.Length; i++)
  {
    pictureParts[i].sprite = city.sprites[i];
    pictureParts[i].gameObject.SetActive(true);
  }
}

Du referenzierst deine 9 SpriteRenderer in "pictureParts", indem du sie aus der Hierarchie deiner Szene in den Inspektor ziehst.

Die zufällig ausgewählte Stadt enthält ja ein Array von 9 Sprites, und diese werden hier der Reihe nach jeder zu seinem jeweiligen SpriteRenderer zugewiesen.

Aber mal was anderes...

Wenn du 100 Bilder importierst (und wer weiß, vielleicht willst du ja irgendwann bauen, dass die Bilder von einem Server kommen, anstatt im Spiel als Assets integriert zu sein... ;))... dann wirst du vermutlich recht schnell deinen Verstand verlieren bei dem Versuch, die alle zu slicen und jeweils im Neunerpaket in den Inspektor zu ziehen.

Wie wäre es also stattdessen mit einem Ansatz, wo du immer nur das Bild selbst benutzt, bzw. ein Sprite, das das gesamte Bild darstellt?

Was hältst du davon, wenn du einfach nur dein Bild anzeigst, und dann neun "Karten", z.B. einfarbige Sprites, darüber legst? Anstatt, dass da ein Bildteil auftaucht, verschwindet stattdessen ein SpriteRenderer, der zuvor einen Teil des Bildes verdeckt hat. Dann kannst du einfach nur einmalig dein Stadt-Sprite dem großen SpriteRenderer zuweisen, die neun Karten mit SetActive(true) aktivieren und fertig.

Ich denke, dass es nicht doof wäre, den originalen Ansatz einmal verstanden und implementiert zu haben, einfach des Lerneffekts wegen. Aber für das Projekt wäre das vermutlich eine viel angenehmere Lösung.

Link to comment
Share on other sites

Moin,

sehr interessante Überlegungen, Sascha. Aber wie Du auch schon schreibst, versuche ich erst einmal, diese neue Version zu einem erfolgreichen Ende zu führen. Das mit der Abdeckung des Bildes klingt sehr gut, für später.

Was habe ich gemacht: in der Hierachy 9 (empty)Gameobjects mit einem SpriteRenderer versehen, die richtigen transform.position für jedes Teilbild eingetragen und diese GameObjects im Inspector in die Elementsslots von pictureParts hineingeschoben. Die o.g. Display-Funktion wollte ich als public Funktion dem ZeigeTeilbildButton zuweisen, diese Funktion erscheint aber nicht, obwohl im script als public deklariert. Wie geht das ?

Um die Description auf Buttonclick (BeschreibungButton) erscheinen zu lassen, muß ich die cities[cityIndex] (was ein int ist) mit meiner class Stadt, die ein "Dictionary<string, string> TheTargets" enthält, zusammenbringen. Mit cities[cityIndex].name sollte ich den Ortsnamen haben; mit dem als Key sollte derBeschreibungstext als Value zu finden sein. Ist der Gedanke so korrekt?

Für heute jetzt erst einmal genug. Ich wünsche allen einen schönen Abend und ein erholsames Wochenende

Gruß von der Ostsee

Peter

  

Link to comment
Share on other sites

vor 5 Stunden schrieb nordseekrabe:

Die o.g. Display-Funktion wollte ich als public Funktion dem ZeigeTeilbildButton zuweisen, diese Funktion erscheint aber nicht, obwohl im script als public deklariert. Wie geht das ?

Weiß nicht so recht, was du meinst - willst du die Funktion aufrufen? Hast du denn eine Referenz auf die Komponente, die die Display-Methode hat?

vor 5 Stunden schrieb nordseekrabe:

Um die Description auf Buttonclick (BeschreibungButton) erscheinen zu lassen, muß ich die cities[cityIndex] (was ein int ist) mit meiner class Stadt, die ein "Dictionary<string, string> TheTargets" enthält, zusammenbringen. Mit cities[cityIndex].name sollte ich den Ortsnamen haben; mit dem als Key sollte derBeschreibungstext als Value zu finden sein. Ist der Gedanke so korrekt?

Warum dir die Mühe machen, wenn du einfach dein City-Struct um ein Feld "description" erweitern kannst? ;)

Link to comment
Share on other sites

Moin , für alle ein gutes Wochende,

die Idee mit der Erweiterung des struct hatte ich auch, habe aber den Fehler gemacht, description als Text zu deklarieren; mit string funktioniert es so, wie gewünscht.

Natürlich kann ich Display(City city) nicht mit dem Button aufrufen, da habe ich völlig falsch gelegen. Habe die Funktion jetzt in "ShowPictureParts()" plaziert (Display(myCity.cities[cityIndex])). Der Parameter stimmt so nicht. Kämpfe weiter.

Gruß Peter

Link to comment
Share on other sites

Moin, eine kurze Frage zum Verständnis und zum Lernen:

Warum wird im o.g. Code neben der "List<City> cities" eine weitere "List<int> availableCityIndices" eingesetzt? Liesse sich nicht auch mit der Cityliste ein Random.Range ausführen ?

(Also    var cityIndex = UnityEngine.Random.Range(0, cities.Count). Etwas problematisch ist für mich, dass cityIndex in der Funktion "festgehalten" ist, wir aber doch immer wieder auf den ausgewählten Ort zugreifen wollen (z.B. stadtText.text = cities[cityIndex].description).  Hier ist cityIndex = 0, weil wir ja nicht cityIndex aus PickRandomCity() ansprechen.

Noch schönes Wochenende

Peter

Link to comment
Share on other sites

vor 2 Stunden schrieb nordseekrabe:

Warum wird im o.g. Code neben der "List<City> cities" eine weitere "List<int> availableCityIndices" eingesetzt? Liesse sich nicht auch mit der Cityliste ein Random.Range ausführen ?

Ich hatte es so verstanden, dass du verhindern willst, dass dieselbe Stadt zweimal ausgewählt wird. Ich empfehle wie gesagt, keine Elemente aus deiner Stadt-Liste zu entfernen, also habe ich stattdessen eine weitere Liste genommen, in der Indizes für die Städteliste enthalten sind - und die werden da raus genommen.

Du kannst stattdessen eine weitere List<City> machen und da anfangs alle Städte hinein füllen. Dann solltest du aber City als class und nicht als struct definieren. Die Erklärung dazu lasse ich jetzt aber mal absichtlich lieber sein. Würde den Code vermutlich etwas leichter lesbar machen.

vor 6 Stunden schrieb nordseekrabe:

Natürlich kann ich Display(City city) nicht mit dem Button aufrufen

Ne, aber du könntest einfach sowas bauen:

public void DisplayRandomCity()
{
  DisplayCity(cities[random.Range(0, cities.Length)]);
  // ...oder wie auch immer du das implementieren willst
}

und das geht dann.

Link to comment
Share on other sites

Moin, zusammen,

melde mich zu einem Zwischenbericht, wenn es jemand interessiert. Soweit klappt inzwischen die gesamte Spiellogik, alle Buttons bringen die richtigen Ergebnisse etc.

Doch leider sind da 2 Bugs: 1. die randomisierten Elemente werden nicht "removed" (availableCityIndices.RemoveAt(listIndex)). Natürlich spürt man das am meisten bei den Teilbildern, da es hier ja nur 9 Elemente sind und somit ständig Doppelte auftreten.

2. Leider liegen die Teilbilder nicht an ihrem richtigen Platz, obwohl transform.position jeweils bei den Bildelement0 bis 8 eingetragen sind. Die 9 Elemente der List<SpriteRenderer> PictureParts übernehmen also nicht die Transformeinträge der aus der Hierarchy  im Inspektor erscheinenden GameObjects. Dies zeigt sich wunderbar bei der Darstellung des kompletten Ortsbildes: alle 9 Bildteile völlig durcheinander und einige mehrfach ! Ist natürlich garnicht lustig.  Da aber die Bildchen erscheinen, müssen PictureParts0 und Bildelement0 "zusammenarbeiten".

Beide Fehler abzustellen, ist mir leider noch nicht gelungen (vielleicht ein kleiner Tipp erforderlich ?)

Bis bald, Grüße

Peter

Link to comment
Share on other sites

vor 11 Minuten schrieb nordseekrabe:

die randomisierten Elemente werden nicht "removed" (availableCityIndices.RemoveAt(listIndex)). Natürlich spürt man das am meisten bei den Teilbildern, da es hier ja nur 9 Elemente sind und somit ständig Doppelte auftreten.

Naja, die Elemente bleiben schön in ihrer Liste, aber die Indices, von denen immer einer gezogen wird, werden immer weniger.

Dasselbe Konzept kannst du auch bei den Teilbildern benutzen.

vor 15 Minuten schrieb nordseekrabe:

Leider liegen die Teilbilder nicht an ihrem richtigen Platz, obwohl transform.position jeweils bei den Bildelement0 bis 8 eingetragen sind. Die 9 Elemente der List<SpriteRenderer> PictureParts übernehmen also nicht die Transformeinträge der aus der Hierarchy  im Inspektor erscheinenden GameObjects. Dies zeigt sich wunderbar bei der Darstellung des kompletten Ortsbildes: alle 9 Bildteile völlig durcheinander und einige mehrfach ! Ist natürlich garnicht lustig.  Da aber die Bildchen erscheinen, müssen PictureParts0 und Bildelement0 "zusammenarbeiten".

Die Transform-Komponente sollte hier gar nicht betrachtet werden. Du hast 9 SpriteRenderer und willst jedem einen Sprite zuweisen. Wo sich diese SpriteRenderer in der Szene befinden, kann dir ja egal sein.

Ich hab hier mal eine Klasse für dich. So ein Ding zu basteln hab ich im ersten Semester Informatik als Aufgabe gehabt, darum behalte ich den Namen von damals bei :D

using UnityEngine;
using System.Collections.Generic;

public class BagOfNumbers
{
  private readonly List<int> numbers = new List<int>();
  private readonly int size;
  public bool hasNumbersLeft => numbers.Count > 0;
  
  public BagOfNumbers(int size)
  {
    this.size = size;
    Refill();
  }
  
  public void Refill()
  {
    numbers.Clear();
    
    for (var i = 0; i < size; i++)
    {
      numbers.Add(i);
    }
  }
  
  public int PullNumber()
  {
    if (!hasNumbersLeft) throw new System.Exception("There are no numbers left to pull, please Refill()");
    
    var index = Random.Range(0, numbers.Count);
    var result = numbers[index];
    numbers.RemoveAt(index);
    
    return result;
  }
}

Kannst du so 1:1 in eine Datei namens "BagOfNumbers.cs" in deine Assets packen.

Dann kannst du das so benutzen:

var bag = new BagOfNumbers(9);

Das baut einen neuen Zahlensack (so hieß das in der Übung) mit den Zahlen 0-8 (inklusive).

Dann kannst du 9-Mal PullNumber() aufrufen, und du wirst alle 9 dieser Zahlen in einer zufälligen Reihenfolge erhalten. Danach (oder, wenn du willst, schon vorher) kannst du den Sack mit Refill() wieder auf den Ausgangszustand setzen (alle Zahlen wieder da). Dann musst du nicht immer einen neuen Sack erzeugen.

Kannst du dann z.B. so benutzen:

bag.Refill();

for (var i = 0; i < pictureParts.Length; i++)
{
  var imageIndex = bag.PullNumber();
  pictureParts[i] = city.sprites[imageIndex];
}

 

Link to comment
Share on other sites

Gleich eine kurze Bemerkung dazu:

ad 1 : natürlich muß das ausgewählte Element raus aus der List; ich will das doppelte erscheinen doch vermeiden. Das gilt für die Orte insgesamt, aber ganz wichtig für die Teilbilder. Bei einer Ortsnachfrage muß sich das komplette Bild allmählich aufbauen, damit der Spieler zunehmend eher den Ort erraten kann.

ad 2: Daher ist es selbstverständlich wichtig, dass das Teilbild an der richtigen Stelle liegt ! Zumindest muss das Gesamtbild korrekt aufgebaut sein. Aber eigentlich ist die Basis dieses "Ratespiels", dem Spieler zunehmend die Chance zu geben, den richtigen Ort zu erkennen.

Da habe ich wohl den Spielaufbau und die Spiellogik nicht gut genug dargestellt.

Peter

Link to comment
Share on other sites

vor 1 Stunde schrieb nordseekrabe:

ad 1 : natürlich muß das ausgewählte Element raus aus der List; ich will das doppelte erscheinen doch vermeiden. Das gilt für die Orte insgesamt, aber ganz wichtig für die Teilbilder. Bei einer Ortsnachfrage muß sich das komplette Bild allmählich aufbauen, damit der Spieler zunehmend eher den Ort erraten kann.

Ne, muss es halt nicht. Du kannst stattdessen auch den Zahlensack benutzen, aus dem du die Indizes deiner Teilbilder ziehst. Wenn jeder Index nur einmal vorkommt, kommt auch jedes Teilbild nur einmal vor. Die Liste an Teilbildern kannst du dann unberührt lassen, was ich wie gesagt bei Daten, die im Editor eingestellt werden, auch empfehlen würde.

vor 2 Stunden schrieb nordseekrabe:

ad 2: Daher ist es selbstverständlich wichtig, dass das Teilbild an der richtigen Stelle liegt ! Zumindest muss das Gesamtbild korrekt aufgebaut sein. Aber eigentlich ist die Basis dieses "Ratespiels", dem Spieler zunehmend die Chance zu geben, den richtigen Ort zu erkennen.

Ich bin immer noch verunsichert, weil bei mir immer abwechseln das eine und dann wieder das andere ankommt. Also direkt gefragt: Willst du ein korrektes Gesamtbild anzeigen, oder willst du die 9 Teile des Bildes durcheinander würfeln, um es schwerer zu machen? Meine letzte Antwort ist darauf aufgebaut, dass ich letzteres vermutet habe. Wenn das nicht so sein soll, kannst du den Zahlensack für die Bildteile natürlich weg lassen, und ihn stattdessen nur noch für die Auswahl deiner Stadt benutzen. Die Zuweisung der 9 Sprites an die 9 SpriteRenderer machst du dann genau so, wie ich weiter oben schon geschrieben habe.

Link to comment
Share on other sites

Danke, für Deine Mühe. Die Bilder sollen schon korrekt aufgebaut werden. Man stelle sich vor, der Zufall nimmt x-mal das Teilbild 1, das ist nun gerade eine Himmeldarstellung,  wird schwer, einen Ort zu erkennen. Außerdem, wie gesagt, bei Klick auf den Beschreibung-Button wird zum einen die Description der Sehenswürdigkeit gezeigt, zum anderen das vollständige Ortsbild, sofern der Spieler nicht schon 9x ein Teilbild aufgerufen hat. Den o.g. Codeteil habe ich bereits eingesetzt. Der enthält nach meinem bescheidenen Wissen keinen Hinweis auf die Transform.Position des einzelnen Bildteils, wie ich sie in den GameObjects im Inspector jeweils eingetragen habe. Mit diesem Code wird tatsächlich ein komplettes Bild (also 9 Teilbilder) aufgebaut, aber völlig durcheinander und mit Bildteildoppelungen. Daher habe ich schon versucht, die PictureParts auch aus einem Struct mit Transform und Sprite aufzubauen. Das hat zwar geklappt, aber dann habe ich die weitere Verarbeitung von PictureParts nicht mehr geschafft. Ist halt doch nicht so einfach für einen Anfänger und Laien. Aber,  Weitermachen ist die Devise.

Peter

Link to comment
Share on other sites

vor 16 Minuten schrieb nordseekrabe:

Man stelle sich vor, der Zufall nimmt x-mal das Teilbild 1, das ist nun gerade eine Himmeldarstellung

Das ist das, was mich verwirrt hatte. Du willst ja keinen Zufall beim Anzeigen der Teilbilder haben, deshalb sollte hier gar nicht von Zufall die Rede sein. Du hast neun Sprites und neun SpriteRenderer, und jeder SpriteRenderer kriegt den Sprite mit demselben Index, fertig. Siehe Link :)

vor 17 Minuten schrieb nordseekrabe:

Der enthält nach meinem bescheidenen Wissen keinen Hinweis auf die Transform.Position des einzelnen Bildteils, wie ich sie in den GameObjects im Inspector jeweils eingetragen habe.

Wie gesagt, lass Transform da raus. Du ziehst deine SpriteRenderer in den Inspektor und hast sie dann im pictureParts-Array in genau der Reihenfolge, in der du sie reingezogen hast. Vermutlich ist 0 der Renderer oben links, 1 der mittlere oben usw. Und die Sprites, die du auch jeweils in einer Neunerliste drin hast, sind genauso geordnet.

Daher bekommt pictureParts[0] auch sprites[0] zugewiesen, pictureParts[1] kriegt sprites[1]. Genau das macht die Schleife in diesem Post.

Link to comment
Share on other sites

Ich traue mich kaum noch, zu antworten, da ich mit jedem Wort nur meine Unwissenheit dokumentiere. Aber es soll ja zu einem guten Ende kommen:

Die Display(City city) gibt für die Zeile "PictureParts[i].sprite = city.sprites[i]; eine Fehlermeldung: "Object reference not set to an instance". In der o.g. Form fehlt doch auch die Auswahl der darzustellenden Stadt, also in unserem Fall die listIndex, oder verstehe ich da was völlig falsch ?

Meine Variante ohne Schleife und mit folgender Änderung der Zeile  ("PictureParts[i].sprite = cities[listIndex].sprites[i]") führt zur Darstellung von 9 Bildteilen aus der ausgewählten (listIndex) Stadt, allerdings in falscher Lage und z.T. auch mehrfach. 

Peter

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...