Jump to content
Unity Insider Forum

nordseekrabe

Members
  • Posts

    147
  • Joined

  • Last visited

  • Days Won

    2

nordseekrabe last won the day on November 9 2023

nordseekrabe had the most liked content!

Recent Profile Visitors

1,611 profile views

nordseekrabe's Achievements

Advanced Member

Advanced Member (3/3)

2

Reputation

  1. Erstmal Dank an beide Autoren = Helfer, zunächst schwirrt mir der Kopf, aber Eure Kommentare kann ich ja mehrfach lesen. malzbie, Du hast natürlich nicht das Thema verfehlt; vielmehr ist das Thema ScriptableObjects versus Prefabs für mich noch längst nicht verdaut. Aber peu a peu werde ich mich mit diesem Kapitel von c# vertraut machen (wollen). "Ein statisches Objekt" ist in der Informatik wohl anders vorgesehen; ich wollte als Erklärung damit zum Ausdruck bringen, dass diese Objekte Teil des Szenenbildes sind, somit unveränderbar und auch nicht aufnehmbar. Sie werden von mir mit einem BoxCollider und einem Objectmanager-Skript versorgt. Damit können sie vom Spieler lediglich "Untersucht" werden und erhalten als Infotext (entsprechend einem Tooltip) interessante Aspekte zum Geschehen an dieser Stelle und mit "Benutzen" wird hier ein Instantiate aufgerufen. Im Gegensatz dazu plaziere ich in die Szenen einzelne Objekte (Puzzleteile, Werkzeuge oder was auch immer), die vom Spieler zunächst gefunden werden müssen, um dann ins Inventory aufgenommen zu werden. Der Spieler kann dann z.B. mit einem Schlüssel, den er gefunden hat, eine Tür öffnen und somit in die nächste Szene gelangen. Der Nullfehler entstand dadurch, dass ich nicht erkannt habe, zweierlei Objekte angesprochen zu haben : myItem ist SO, der Aufruf Instantiate(myItem.itemPrefab, etc.) kopiert ein GameObject in die "aktuell aktive Szene"; dieses Objekt habe ich mit "Nimm" angesprochen (Inventory.Instance.AddItem(myItem)....myItem ist SO und kein GameObject, somit war der Fehler nachvollziehbar. Der obige Hinweis auf var itemInstance ist phantastisch; klar ist mir noch nicht, wie die Klasse ItemRepresentation aussehen könnte ? Das war eine sympathische Lektion, die nicht nur mir im Beschäftigen mit c# und Unity weiterhelfen konnte. Tausend Dank, Euch beiden. Beste Grüße Peter
  2. Moin an alle, sorry, meine Sprache ist nicht die eines Informatikfachmannes; meine Erläuterungsversuche mit vielen fachlichen Fehlern sind äußerst laienhaft. Und so ist natürlich auch meine Denke; ich denke nicht in Informatik Semantik, dazu bedarf es eines Fachstudiums und Erfahrung. Das ist, glaube ich, in den meisten Fächern so, besonders deutlich bei den Juristen, wo der Laie oft deren Denkensart nicht verstehen kann. In einer wachen Stunde ist mir heute Nacht der Fehler aufgegangen: Meine SOs weise ich mit meinem Objectmanager-Skript im Inspektor einem "statischen" Objekt zu. Dieses klicke ich mit "Benutze" an und die instanziierung wird ausgeführt, das Prefab des SO wird in der Szene dargestellt. Wenn ich jetzt (fehlerhaft) dieses Prefab mit "Nimm" anklicke, ist myItem natürlich null. Wenn ich aber erneut das statische Objekt nun mit "Nimm" anklicke, ist das SO (vermutlich als Prefab) im Inventory. Keine Fehlermeldung, alles paletti. Leider ist das nur nicht das, was ich will, weil nicht realistisch: der Spieler klickt nicht ein (statisches) Objekt an, das erwünschte Spielobjekt erscheint in der Szene, und um das dann zu erhalten, klickt er dann nochmals das statische Objekt der Szene an, nein, macht keinen Sinn. Also muss ich ereichen, dass nach Instanziierung eines Objektes durch Anklicken eben dieses die Aufnahme ins Inventory erfolgen kann. Das sollte möglich sein, indem ich 1. ins Inventory ein Gameobject (prefab) aufnehmen kann (derzeit ist es ein SO) und 2. indem ich die Übernahme durch Anklicken des statischen Objektes blockiere. Nicht einfach, zu erklären, aber das sind die Forumsmitglieder vermutlich gewohnt. Also geht es dann erst einmal in diesem Sinne weiter. Zunächst besten Dank, Sascha, für die Geduld (trotz Müdigkeit); bei erneuter Sackgasse melde ich mich gerne wieder. Einen schönen Nikolaustag wünscht Euch allen Peter
  3. Eine weitere Ergänzung kurz vor dem Feierabend, habe wie oben beschrieben den Objectmanager korrigiert, also in diesem ergänzt public void WorkWithObject() { if (myItem != null && myItem.isTaken == false) { Inventory.Instance.AddItem(myItem); myItem.isTaken = true; if (myItem.stackable == true) { PuzzleScore.instance.AddPuzzle(); } myItem = null; } else { Debug.Log("myItem ist leer"); } } Natürlich dann auch geändert else if (am.aktuelleAktion == "Nimm" { WorkWithObject() } Wie gehabt : Instantiate() funktioniert, "Nimm" landet bei Debug.Log("myItem ist leer"); Dabei allerdings bereits in der Szene 1. Da wir ja "myItem = null" abgefangen haben, kommt es nicht zur Fehlermeldung. Zuvor führen wir doch erfolgreich "Instantiate(myItem.itemPrefab, myItem.itemPosition, Quaternion.identy)" aus, Debug.Log gibt mit myItem.itemName das richtige SO an. Dieses instanziierte Objekt wird aber nicht mehr für "Nimm" übernommen, weil ja kein SO erzeugt wird, sondern ein Prefab. Daher ist "myItem" leer. Müßte ich dann nicht mit dem Inventory ein Prefab aufnehmen (inventory umschreiben)? moin zusammen Peter
  4. Kurze Antwort auf Deine Fragen: Objekte, die in die Szene gelegt werde, um sie zu benutzen etc. sind SO und enthalten Objectmanager.cs Objekte, die Teil des Hintergrundbildes und damit der Szene sind (wie Möbel oder ähnliches), aber doch auch vom Spieler untersucht und vom Code beschrieben werden sollen, dachte ich vom "public Item myItem" zu befreien und mit einem StaticobjectManager(das wäre das neue Skript) zu versorgen. (Das sind die meisten Objekte dieses Projekts...Objekte für Inventory sind lediglich ca. 60). Dann sollte doch "myItem = null" wegfallen ? Mit Deinem Supervorschlag ist es für mich wohl einfacher, weil ich nicht alle Staticobjekte mit einem neuen Skript versorgen muss, sondern nur den vorhandenen Objectmanager.cs ändern muss. Also, wieder einmal, ein große Hilfe und eine geöffnete Sackgasse; weitermachen Peter. Schönen Abend allen und Gruß von der Ostseeküste Peter
  5. Besten Dank, lieber Sascha, bin halt für jede Anregung dankbar. Deinen Hinweis habe ich zunächst so verstanden, dass im Inspektor in jedem "myItem" ein ScriptableObject eingetragen sein muss. Da ich aber jedem Objekt in der Szene, das ich in irgendeiner Form ansprechen möchte, ein ObjectManager-Skript angehängt habe, gibt es natürlich einige (statische) Objekt, die zwar das Objectmanager-Skript tragen, aber kein SO zugewiesen bekommen. So, dachte ich, das könnte der Fehler sein !? Habe nun allen sog. statischen Objekten, also alle in der Szene dargestellten Bildteile (Schrank, Stuhl Tür, Fenster) die ja nur "untersucht", also betrachtet und kommentiert werden sollen, mit einem neuen, eigenen Skript belegt, sodaß nun tatsächlich alle beweglichen (in die Szene eingefügten) Objekte ein Objectmanager-Skript mit zugewiesenem SO im Inspektor tragen. Doch leider... gleiche Fehlermeldung bei o.g. Zeile. Das konnte ich bislang natürlich nur in 2 Szenen ändern. In den anderen Szenen fliegen dann noch Objectmanager an Objekten aller Art mit "public Item myItem" ohne Zuweisung im Inspektor herum. Werden denn beim Starten des Projekts jedesmal alle(!) Szenen, also der komplette Code compiliert ? Das zunächst mal als Rückmeldung. Eine schöne Woche wünscht Euch allen Peter
  6. Davor habe ich mich bisher immer gedrückt, mich mit dem Debugging zu beschäftigen. Mit einer Kurzbeschäftigung scheint es mir aber immerhin gelungen zu sein, die Info zu erhalten, dass "myItem" = null sein dürfte.; zumindest in der if-Schleife (myItem.isTaken == false). Daher habe ich nochmals den o.g. Code um "&& myItem.isTaken == false" und "myItem.IsTaken = true" gekürzt. Die Fehlermeldung kommt dennoch, natürlich über "Inventory.Instance.AddItem(myItem), denn myItem ist wohl null. Aber warum ? Beim Instanziieren ist myItem doch auch nicht null, im Gegenteil, das Objekt wird in der Szene sichtbar, was dann Debug.Log() bestätigt. Und die gleiche Codierung erfolgt doch auch für "myItem.isInstantiated" in Szene 1 und 2 und funktioniert ? Muss ich das verstehen ? Kann man das verstehen ? Peter
  7. Moin, Sascha, danke für die rasche Reaktion, konnte gestern Abend nicht mehr antworten, war nicht "frei". Habe im Internet schon mit dieser NRE-Geschichte reichlich studiert, habe auch schon verstanden, dass ein Objekt mit null eine Fehlermeldung auslöst. Aber jetzt... In meinem Fall wird der Fehler mit der Zeile (49) im ObjectManager Script ausgelöst. else if (am.aktuelleAktion == "Nimm" && myItem.isTaken == false) // "am" ist die Reference zu Aktionsmanager-Skript Nochmals der Hinweis: beim 1. Aufruf (in Szene 1) keine Fehlermeldung, mit Debug.Log wird angezeigt, dass "Puzzle16" aufgenommen wurde, erscheint dann auch im Inventory. Gehe ich nun weiter in Szene 2 und instanziiere mit "Benutze" wie oben mit Code erkennbar, zeigt Debug.Log den Objektname "Vierkant" und das Objekt wird in der Szene sichtbar; will ich jetzt mit "Nimm" das Objekt(Vierkant) nehmen, kommt es zur Fehlermeldung. Wenn ich nun die zweite Hälfte der Zeile auskommentiere (also && myItem.isTaken == false) erscheint der Null-Fehler auch. Nach meinem Verständnis ist also "myItem" nicht null (wird ja auch von Debug.Log benannt), ein bool sollte nicht null sein, oder ? Also bleiben nur "am" und "aktuelleAktion" als Null-Kandidaten. "Am" wird deklariert mit "Actionsmanager am" und in Start() mit "am = GameObject.Find("Actionsmanager").GetComponent<Actionsmanager>();" referenziert(?). "AktuelleAktion" ist ein string aus dem Actionsmanager-Skript. Könnte die Fehlermeldung sich auch auf die spätere Zeile "Inventory.Instance.AddItem(myItem)" beziehen, auch wenn die Zeilenangabe anders lautet ? Und das ist mein Dilemma, ich sehe kein "Nullobjekt", und ich verstehe nicht, dass der Code einmal durchläuft und beim 2. mal eine Fehlermeldung auswirft. Da ist halt das laienhafte Denken und nicht das Fachdenken, was man eben auch lernen muss. Gruß und eine gute Woche für alle Peter ObjectManager.cs
  8. Moin zusammen und einen schönen 1. Advent, wieder einmal eine Verständnisfrage, die die Profis hoffentlich nicht als sehr dämlich erachten. In meinem Projekt gibt es eine Klasse "Item" als ScriptableObjects mit u.a. den Eigenschaften "public bool isInstantiated" und "public bool isTaken". Im ersten Raum nehme ich ein Puzzle (ScriptableObject) ins Inventar; beim Aufnehmen eines Vierkant(ScriptableObject) im nächsten Raum erscheint die Fehlermeldung "Object reference not set to an instance of an object". Beide Objekte müssen zunächst als Instanz aufgerufen werden. Code hierzu siehe unten. Meine Frage ist, warum erfolgt die Instanziierung bei beiden Objekten anstandslos, aber das Aufnehmen nicht ? public class ObjectManager : MonoBehaviour public Item myItem; // reference to scriptableobject private void OnMouseDown() { If...... else if (am.aktuelleAktion == "Nimm" && myItem.isTaken == false) { Inventory.Instance.AddItem(myItem); myItem.isTaken = true; Destroy(this.gameObject); if (myItem.stackable == true) PuzzleScore.instance.AddPuzzle(); } else if (am.aktuelleAktion == "Benutze" && myItem.isInstantiated == false) { Instantiate(myItem.itemPrefab, myItem.itemPosition, Quaternion.identity); myItem.isInstantiated = true; } Ich hoffe, die Codeschnipsel reichen zum Verständnis. Also nochmal: bei beiden Objekten funktioniert das Instantiate(), beide erscheinen in der Szene; im 1.Raum funktioniert auch Inventory.Instance.AddItem(myItem) -> das Objekt erscheint im Inventory; das 2.Objekt im nächsten Raum erzeugt die Fehlermeldung. Beide Objekte haben das Skript "ObjectManager" (mit o.g. Code) zugewiesen. Noch einen schönen winterlichen Adventssonntag wünscht Peter von der Ostseeküste
  9. Donnerwetter, echt unglaublich, alle Probleme aufgelöst im Nichts. Alle Logik klappt, das Ratespiel kann ausgeführt werden. Habe intensiv studiert, um alle Abläufe zu verstehen und die Neuerungen richtig einzubauen. Besonders erstaunlich finde ich, dass nun plötzlich die Teilbilder richtig platziert sind, was wohl darin begründet sein könnte, dass das Programm die Teilbilder 0 bis 8 automatisch auf dem Display richtig verteilt, wenn man sie alle mit Schleife aufruft und, wie in Deiner Lösung, dann auf Buttonklick einzeln aktiviert (SetActive(true)). Das ist in dieser Form natürlich alles noch zig Nummern zu hoch, um selbständig zu solchen Lösungen zu kommen. Dennoch zeigt sich an diesem Dialog mit Sascha, wie wichtig so ein Forum und die damit aktiven Helfer, für einen Anfänger sind. Ohne dies wäre ich frustriert in der Sackgasse hängen geblieben und hätte resignierend abgebrochen. Habe so dabei nicht nur ein Projekt beenden können, sondern auch sehr viel gelernt, was bei nächsten Versuchen Anwendung finden kann. Also, habe tausend Dank, Sascha, für Geduld und Ausdauer, mit mir hierbei zu einem guten Ende gekommen zu sein. Bis zu einer nächsten Gelegenheit Peter
  10. Besten Dank. Nebenbei gesagt, glaube erkannt zu haben, warum es beim Random zu Doppelten kommt: mit jedem Aufruf von ShowPicturePart() (bei Buttonklick) wird jeweils stets die OriginalList von PictureParts genommen und nicht die durch RemoveAt veränderte. Oder sehe ich das falsch ? Peter GameProcedure.cs Spielstart.cs
  11. Habe das mal ausgeführt mit [serializable] private struct Picture {public Transform picturePos; public SpriteRenderer sprite;} und dann eine List<Picture> PictureParts; erstellt. Konnte damit im Inspector sehr gut jedem einzelnen Element sowohl Transform als auch SpriteRenderer zuweisen. Leider konnte ich die Sinnhaftigkeit nicht testen. Erhalte eine Fehlermeldung: "der Rückgabewert von List<Picture>.this[int] ist keine Variable und kann daher nicht geändert werden" für die Zeile PictureParts[collectedOne].sprite = cities[listIndex].sprites[collectedOne]; der Fehler bezieht sich auf die linke Hälfte der Zeile. Was habe ich denn da falsch gemacht ? Ein kleiner Tipp wäre hilfreich, auch wenn die Codeidee ein grundsätzlicher Strukturfehler sein sollte. Peter
  12. Nein, absolut nicht die Reihenfolge. Wie oben von Dir selbst zitiert: korrekt aufgebaut, damit , wenn 9 Teilbilder plaziert sind, ein korrektes Bild zu sehen ist. In welcher Reihenfolge, also ob erst PicturePart0 oder PicturePart8 ist wurscht. Nicht wurscht ist, wo PicturePart0 landet (nämlich links oben) und das die Wahl, welches Teilbild nun drankommt, nicht der Reihenfolge 0 bis 8 gezollt ist, sondern einem Zufallsgenerator. Also zufällig macht PictionPart0 den Anfang, wird zufällig von PicturePart5 gefolgt, etc. aber immer an der richtigen Position im Bild. Deswegen habe ich ja von Anfang das Problem des Transform.position der SpriteRenderer/PictureParts angesprochen. Und wie schon schon mal angedacht, ob man mit z.B. struct Picture { public Transform picturePos; public SpriteRenderer sprite} und dann einer List<Picture> PictureParts weiter kommen könnte? Aber Moin, moin sollte nicht vergessen werden Gruß Peter
  13. Entschuldige, dass ich widerspreche. Genau das will ich nämlich auch: neben der Zufallsauswahl aus 100 Orten soll auch bei der Darstellung eines Teilbildes aus den 9 verschiedenen eines zufällig gewählt werden. Hat u.a. den Sinn, dass das Raten hierdurch etwas komplizierter wird. Also noch mal die Spiellogik: nach dem Start ruft der Spieler mit dem Button "Teilbild zeigen" das 1.Teilstück aus dem Gesamtbild des durch Zufall aus 100 Orten ausgewählten Ortes auf. Ist ihm die Stadt bekannt, kann er im Inputfield seine Vermutung eintragen. Stimmt diese, erscheint das komplette Bild; zusätzlich erhält der Spieler eine Punktebewertung im Score. Ist die Eingabe im Inputfield aber falsch, tut sich nichts und der Spieler ruft mit dem Button "Teilbild zeigen" das 2.Teilbild auf. Auch das natürlich wieder per Random aus den noch verbliebenen 8 Teilbildern. etc.etc. Zusätzlich kann man mit dem Button "Beschreibung" eine textliche Erläuterung zu dem dargestellten Objekt aufrufen; dabei wird natürlich auch das Gesamtbild vervollständigt. Das funktioniert im Prinzip auch alles. Lediglich die korrekte Plazierung der Teilbilder ist nicht möglich und die Teilbilder treten mehrfach auf. Ich hoffe, dass ich nicht nerve ! Peter
  14. Danke für die ausführliche Erläuterung, die ich soweit verstanden haben sollte. Bleibt für mich allerdings weiterhin unklar, warum es zur Mehrfachauswahl von PictureParts kommt wenn wir sie entfernt haben. collectedOne = UnityEngine.Random.Range.Range(0, PictureParts.Count); Debug.Log("Teilbild: " + collectedOne); // es wird tatsächlich immer eine Zahl zwischen 0 und8 angezeigt, aber eben auch mehrfach diesselbe PictureParts[collectedOne].sprite = cities[listIndex].sprites[collectedOne; PictureParts[collectedOne].gameObject.SetActive(true); PictureParts.RemoveAt(collectedOne);
×
×
  • Create New...