Leaderboard
Popular Content
Showing content with the highest reputation since 03/02/2023 in all areas
-
Dein Problem könnte sein, dass ein Destroy nicht sofort passiert, sondern erst nach ablauf des Update-Loops. Du zerstörst also den letzten Level, welcher aber bis zum Ende des Loops noch da ist, instanzierst einen neuen Level, hast jetzt also 2 Level gleichzeitig drin, suchst nach deinen Punkten, die jetzt 2 Mal drin sind, und findest die alten, schon gefundenen, Punkte. Jetzt erst wird der alte Level aus der Szene raus genommen und deine gefundenen Punkte sind weg. Was dir helfen könnte, wäre ein DestroyImmediate. Das wird aber ausdrücklich nicht empfohlen! https://docs.unity3d.com/ScriptReference/Object.DestroyImmediate.html Suchen die Punkte doch einfach mal im LateUpdate und guck ob dann alles in Ordnung ist.2 points
-
Hallo, Welche Fehlermeldung du genau erhältst wäre schon hilfreich. Ich rate mal ins blaue. In der class MathQuestion hast du public List<int> fakeAnswers; eine Liste referenziert die aber noch auf null zeigt. In der anderen Classe greifst du mit question.fakeAnswers.Add(_result); auf die fakeAnswers Liste zu die noch nicht Initialisiert ist. In der class MathQuestion hättest du mit public List<int> fakeAnswers = new List<int>(); die Liste Initialisiert Sorry, Sascha war mal wie immer 1 Minute schneller😉 Gruß Jog2 points
-
Eigentlich wollte ich nur einen kleinen Retro-Plattformer erstellen. Jetzt wo ich damit begonnen habe, stellte sich schnell heraus, das es wohl doch ein etwas umfangreicheres Projekt werden wird. Daher bekommt es auch einen eigenen Kanal. Ich werde das Projekt diesmal englischsprachig halten. Da bekomme ich schon hin. Bekanntlicherweise halten sich ja die Dialoge in einem Plattformer in Grenzen. Nichtsdestotrotz werde ich die Spielbeschreibungen erstmal deutsch halten. Dann habe ich immer die Möglichkeit mich evtl. doch nur für eine rein deutsche Version zu entscheiden. Name: The cunning Fox Story: In einem dichten Wald voller Magie und Kreaturen lebte ein listiger Fuchs namens Max. Eines Tages hörte Max ein Gerücht über ein monströses Ungeheuer, das im Wald sein Unwesen trieb und alles verschlang, was ihm in den Weg kam. Max beschloss, das Ungeheuer zu finden und zu besiegen, aber er erkannte schnell, dass es nur eine Illusion war, die von einem Zauberer des Waldes erschaffen wurde. Max schmiedete einen Plan, um den Zauberer zu überlisten und seine Schätze zu stehlen. Hier ein Screen vom ersten Level:1 point
-
Korrekt! Aber du kannst Typen eben nicht nur über generische Parameter kommunizieren, sondern auch über einen normalen System.Type-Parameter. Statt public void Foo<T>() machst du public void Foo(System.Type type) Du kannst generische Parameter auch problemlos mit typeof() zu einem System.Type-Objekt umwandeln. So als Beispiel: public bool Foo<T>(System.Type type) { return typeof(t) == type; } Das gibt dann true zurück, wenn man das so aufruft: Foo<Light>(typeof(Light)) // oder Foo<Light>(GetComponent<Light>().GetType()) Umgekehrt braucht man halt leider Reflection und sollte das vermeiden. Aber man kann oft von der anderen Seite ankommen, z.B. so: class MyGenericClass<T> { public System.Type GenericType => typeof(T); } Objekte dieser Klasse geben die mit der Property "GenericType" den Typ zurück, den du beim Erstellen für T übergeben hast: var thing = new MyGenericClass<Light>(); Debug.Log(thing.GenericType.Name); // "Light" Damit geht eine ganze Menge. Du könntest zum Beispiel beim Start alle deine Objekte laden und sie in ein Dictionary packen. Das Dictionary kann so aussehen: private Dictionary<System.Type, List<MyGenericClass<>> genericClassObjectsByGenericType = new Dictionary<...>(); Und dann lädst du da alle geladenen Objekte rein und sortierst sie nach ihrem generischen Typ: foreach (var loadedObject in allLoadedObjects) { var type = loadedObject.GenericType; List<MyGenericClass<>> list; if (genericClassObjectByType.TryGetValue(type, out list)) { list.Add(loadedObject); } else { list = new List<MyGenericClass<>>(); list.Add(loadedObject); genericClassObjectByType.Add(type, list); } } Und wenn du dann alle Objekte eines bestimmten generischen Type haben willst, holst du sie dir einfach aus dem Dictionary: public List<MyGenericClass<>> GetAllObjectsForType(System.Type type) { return genericClassObjectsByType[type]; } Da fehlt noch die Ausnahmebehandlung, falls der Typ nicht gefunden wird. Und ich hab das jetzt so runtergetippt, kann sein dass die Syntax mit <> nicht ganz richtig verwendet wird. Aber ich hoffe, die Idee ist einigermaßen klar. Ja schon, aber eine Datenstruktur wachsen zu lassen ist besserer Stil als ein switch-case, das ständig erweitert werden muss. Vor allem, weil du bei einem Dictionary einfach mit der Schleife über alle Typen gehen kannst (siehe oben), anstatt deinen switch-case-Code jedes Mal anzufassen.1 point
-
Moin! Dafür, dass das gar nicht so einfach passieren dürfte, habe ich dieses Problem, dass beim zweiten Mal Laden etwas anders ist als beim ersten Mal, schon echt oft gesehen. Hast du irgendwo DontDestroyOnLoad drin, z.B. in deinem Spawn- und Endpunkt-Scripts oder so?1 point
-
Hallo, ich hatte in der letzten Zeit Lust, neben meinen größeren Projekten, etwas „Kleines“ zu erstellen. Dabei ist die Wahl auf einen vertikal Space-Shooter gefallen. Wie gesagt, nichts umfangreiches, eher etwas für Zwischendurch mal etwas rumballern. Daher sind es auch nur 10 Level und wenn man alles durchgespielt hat, dann sind es evtl. 30 Minuten Spielzeit. Das kleine Projekt nennt sich Boreas Nebula und ist wieder mit Unity umgesetzt. Ganz fertig ist es noch nicht, aber schon mal komplett spielbar. Hier der Download, falls ihr mal reinschauen wollt. Boreas 0.9.1 Hier ein paar Screens:1 point
-
Hallo, ein paar Neuigkeiten zu meinem Aufbauspiel Orfayas Besiedlung. Insgesamt sind es acht Mission geworden. Dazu werde ich noch zwei Freispielmissionen zur Verfügung stellen. Es wird jetzt nicht nur eine Bevölkerungsschicht geben. Neben den Siedlern gibt es Bauern, Arbeiter und Gelehrte. Die Gebäude, die der Spieler errichtet, werden unterschiedliche Gruppen von Bewohnern benötigen. So benötigt z.B. eine Kartoffelfarm Bauern und eine Kohlemine Arbeiter. Der Spieler muss für eine Gleichgewicht sorgen, damit alle Gebäude mit den benötigten Bewohnern versorgt werden. Das UI habe ich diesbezüglich überarbeitet. Somit kann der Spieler jederzeit sehen wie viele Siedler oder Arbeiter er aktuell hat. Hier ist der Download zur Version 0.7.0.: https://www.pchobbyspieleschmiede.de/besiedlung/BSO_0.7.0.rar Discord: https://discord.gg/PHZFBptfxJ In dieser Version sind es nur sieben Missionen, die spielbar sind. Die einzelnen Missionen sind auch noch nicht komplett fehlerfrei. Vom Gameplay her schon, aber ggf. sind noch ein paar Fehler im grafischen Aufbau vorhanden. Die werde ich aber noch mal konkret überarbeiten, wenn ich alle Missionen im Spiel habe.1 point
-
Moin! Ich bin mir nicht ganz sicher mit "teilen sich dasselbe Material" meinst. Anhand der folgenden Fragen vermute ich, du meinst, dass da eine fortlaufende Textur zu sehen ist, die sich über mehrere Tiles erstreckt? Der Ansatz mit dem Mesh könnte theoretisch funktionieren, aber ich stelle mir das schwierig vor, das performant zu halten. Ich denke, der bessere Weg sind World Space-Texturkoordinaten. Shader haben ja Koordinaten, mit denen sie das Pixel der Textur finden, das sie an eine gegebene Stelle rendern wollen. Da das für die meisten Fälle Sinn ergibt, nehmen die meisten Shader dafür die UV-Map des 3D-Modells. Ein 2D-Objekt ist hierbei auch nur ein flaches 3D-Modell. Jedenfalls muss man dabei aber nicht bleiben - man kann den Shader beliebige Zahlen verwenden, nachschauen oder ausrechnen lassen, um diese als Texturkoordinaten zu verwenden. So kannst du z.B. auch einfach die World Space-Koordinate eines Pixels nehmen und diese als Textur-Koordinate nutzen. Ist zwar 3D, aber hier kannst du dir das mal ansehen: Wie du siehst, ist die Textur immer an derselben Stelle der Welt und nicht, wie sonst, des Objekts. Wenn er hier den Würfel kopiert und die Kopie neben das Original packt, dann passen die beiden Würfel direkt aneinander. Mit dieser Technik kannst du deine Tiles völlig beliebig in die Welt klatschen, und die Textur ist immer gleich. Wenn du dir mal deinen zweiten Screenshot genauer ansiehst, siehst du auch, dass das so gemacht sein dürfte. Denn die Textur wiederholt sich nach 16-order-so Tiles: Also, lange Rede, kurzer Sinn: Baue dir oder finde einen Sprite Shader mit World Space-Texturkoordinaten.1 point
-
Ja ...aber jetzt verstehe ich deine Problematik besser und verstehe deinen Gedankengang und muss dir Recht geben. Es ist eine Überlegung wert.....🙄1 point
-
Nein Dein Projekt ist auch nur ein ganz normales C#-Programm, das von der darunter liegenden C++-Engine gestartet wird. Du hast keinen Zugriff auf die übliche Main-Methode und einen ganzen Haufen Engine-interner Dinge, aber abgesehen davon hast du da nicht so wirklich nennenswerte Einschränkungen. Wenn du diesen Satz also so meinst, dass der Code zum Erstellen von Objekten in einem MonoBehaviour stecken muss, dann: Nein. Objekte können Objekte können Objekte erstellen. Gar kein Problem. Wenn du den Satz aber so meinst, dass der initiale Impuls, dass irgendetwas passiert, aus Unity heraus kommen muss, dann hast du damit sogar Recht. Wenn du daraus aber wiederum ableitest, dass das in einem MonoBehaviour passieren muss, dann stimmt die Behauptung auch wieder nicht. Unity hat einen solchen Impuls, der einfach nur zum Programmstart irgendeinen Code ausführt - ähnlich einer Main-Methode. Dafür brauchst du dieses Attribut: [RuntimeInitializeOnLoadMethod] private static void InitializeStuff() { Debug.Log("Hello, World!"); } Das kannst du über eine parameterlose, statische Methode in einer beliebigen Klasse packen und ab dafür. Das Attribut hat auch noch einen optionalen Parameter, mit dem du bestimmen kannst, ob das vor dem Laden der ersten Szene passieren soll oder danach... oder noch woanders. In dieser Methode kannst du dann auch wunderbar auch verschiedene Events subscriben, z.B. auf das Wechseln zu einer anderen Szene. Du kannst auch mit dem PlayerLoopSystem deine eigene Update-Methode schreiben, die kein MonoBehaviour braucht, wobei es für simple Fälle meiner Meinung nach entspannter ist, einfach ein Gameobject zu bauen. Nachdem all das gesagt ist, finde ich es aber wichtig, zu erwähnen, dass das nicht heißt, dass du ab jetzt MonoBehaviour meiden solltest, solange etwas nicht sichtbar ist oder so. Ein GameObject definiert ein Stück weit, wie eine Szene funktioniert. Und das darfst du auch genau so nutzen. So als Beispiel: Ich habe ein Beispiel-Projekt für Soda (ein Asset-Store-Paket von mir) gebaut. Als Hinweis: Gerne anschauen, ich benutze es auch als Best Practices-Showcase, aber ohne Soda wird es nicht kompilieren. Dort habe ich jedenfalls ein Musik-System. In diesem System benutze ich das [RuntimeInitializeOnLoadMethod]-Attribut, um direkt bei Spielstart ein GameObject zu erzeugen. Dieses mache ich mit HideFlags unsichtbar, damit es im Editor nicht weiter auffällt, und mit DontDestroyOnLoad mache ich es "unverwundbar" gegen Szenenwechsel. Damit habe ich ein (wenn man nicht danach sucht...) unsichtbares GameObject, das von Anfang bis Ende der Laufzeit existiert. Diesem GameObject gebe ich eine AudioSource, das die Hintergrundmusik abspielt. Nun habe ich aber auch eine Komponente, die einen AudioClip referenzieren kann und die sich, solange sie enabled ist, in eine Liste einträgt. Wann immer sich eine solche Komponente einträgt, wird der AudioClip des letzten Elements der Liste von dieser AudioSource abgespielt. Wenn ich also eine neue Szene mache und da ist nichts drin, dann habe ich da Musik laufen, sofern der Player da etwas brauchbares in der Liste hat. Und damit komme ich endlich zu meinem Punkt: Wenn ich eine Musik-Komponente in meine leere Szene packe, dann habe ich eine leere Szene, die ihre eigene Musik vom globalen Musik-Player abspielen lässt. Diese Komponente ist für den Spieler unsichtbar, sie stellt keine unsichtbare Wand dar, gar nichts. Und trotzdem hat sie, in der Szene und als MonoBehaviour, ihre Daseinsberechtigung, weil sie dazu beiträgt, zu definieren, was genau in dieser Szene passiert. Es ist also völlig okay, eine MonoBehaviour-Klasse zu schreiben, um irgendwelche Dinge zu initialisieren oder um Daten einzutragen, die in der Szene relevant sein können. Es ist aber trotzdem sehr empfehlenswert, sich von der Idee zu lösen, die Unity einem initial leider vermittelt: Dass alles irgendwie in MonoBehaviours passieren muss.1 point
-
Ohne jetzt viel darüber nachzudenken, direkt einmal der Hinweis: Bei TextMeshPro immer als Komponententyp TMP_Blub nehmen. Wenn's nicht mit "TMP_" anfängt, kann es immer Probleme geben. Hier also statt TextMeshProUGUI bitte "TMP_Text" nehmen. @gombolo Nö, oben steht ja "using TMPro;", damit geht's auch.1 point
-
Naja, "sichtbar" ist eine der Arten, in der man in einer Szene eine Rolle erfüllen kann. Eine unsichtbare Wand, um den Spieler daran zu hindern irgendwo lang zu hüpfen, oder eine AudioSource, aus der Windgeräusche kommen, dürfen genauso in die Szene. Aber davon abgesehen: Genau. Nö. Ein Objekt gehört niemals einem anderen Objekt. Wir lassen Structs da gerade mal außen vor, aber Objekte sind auf dem "Heap", einer Datenstruktur, die dein Spiel im Arbeitsspeicher anlegt. Und die ist genau so organisiert, wie der Name suggeriert: Es ist ein "Haufen". Da sind einfach alle Objekte draufgeschmissen und fertig. Jeder kann dein Objekt referenzieren, jeder kann damit arbeiten. Das einzige, was hier einschränkend wirkt, ist die Kontrolle über die Referenz. Wenn irgendein Code nicht weiß, an welcher Speicheradresse dein Objekt ist, dann kann er es auch nicht finden. Sobald du die Referenz aber hast, kann dein Code alles mit dem Objekt tun, was man eben so damit tun kann. Auch, wenn das Objekt, dass dein Einwohner-Objekt erzeugt hat, aufhört zu existieren, ist das egal. So eine Art Verbindung zwischen einem Objekt und wo es herkommt, oder überall schonmal benutzt wurde, gibt es einfach nicht.1 point
-
ScriptableObjects sind dafür da, um etwas im Editor zu definieren, das dann im Spiel landet. Wenn du irgendetwas hast, das nur zur Laufzeit existiert, dann bringt es dir keine Vorteile, dieses Ding von einem SO repräsentieren zu lassen. ScriptableObjects zur Laufzeit zu erzeugen, anstatt sie im Editor anzulegen, ist ein recht klares Zeichen dafür, dass was nicht ganz rund läuft. Nimm stattdessen einfach ganz normale Objekte. ScriptableObjects nehmen einfach nur mehr Arbeitsspeicher weg. Wobei du auch nicht unbedingt für jeden Einwohner gleich ein ganzes Objekt brauchst. Wenn du einfach pro Firma x Angestellte hast, dann kann es auch reichen, ein int in das Firma-Objekt zu packen. Dann wird die Berechnung irgendwelcher Kosten auch viel harmloser. Individuelle Sachen wie Namen kannst du dann immer noch prozedural generieren, ohne sie zu speichern. Davon abgesehen... Ist jeder angestellte ein GameObject? Da hast du mit 10.000 Stück sowieso eigentlich direkt verloren. Für so eine Menge von Akteuren brauchst du ECS. Wenn es aber nur um simple Datenobjekte geht, dann kannst du durchaus ein paar Tausend Stück haben... und die auch in eine Liste tun. Aber wie gesagt, das muss vielleicht gar nicht unbedingt sein. Zum Thema Events: Events sind dazu da, dass der Auslöser und der Reagierende sich nicht kennen. Wenn der Spieler stirbt löst er ein Event aus, und als Reaktion erscheint ein Game-Over-Bildschirm. Dass das Spieler-Leben-System und das Game-Over-Bildschirm-System sich nicht kennen, ist eine gute Idee. In deinem Fall aber ist es durchaus logisch, dass die Firma ihre angestellten kennt. Wie @chrische5 also schon sagt: Da kann die Firma einfach über die Liste iterieren, die sie sowieso schon rumliegen hat. Und eine Liste von Firmen, über die man iteriert, um über die Gehaltskürzung zu informieren, klingt auch erst mal nicht falsch.1 point
-
Hallo Also entweder haben die Angestellten ja gespeichert, bei welchem Unternehmen sie sind oder die Unternehmen haben gespeichert, wer bei Ihnen arbeitet. Beim zweiten Fall kann das betroffene Unternehmen ja einfach seine Angestellte informieren und bei denen eine entsprechende Funktion aufrufen. Wenn die Angestellten sich ihr Unternehmen gemerkt haben, dann sende doch den Event, dass ein Unternehmen Lohnkürzungen vornimmt und entweder gibst du dem Event das Unternehmen als Parameter mit und iterierst dann durch alle Angestellten und schaust, ob deren Unternehmen mit dem des Events übereinstimmt. Wenn dies der Fall ist, rufst die Lohnkürzungsfunktion auf. Du kannst auch den Event ohne Parameter feuern und dabei eine globale Variable (kann natürlich auch So sein) setzen, in welchem das entsprechende Unternehmen hinterlegt wird. So mache ich das meist. Christoph1 point
-
Moin! Die "fakeAnswers"-Variable wird vermutlich null als Wert haben, also keine Liste referenzieren. Du musst irgendwo mit so etwas wie fakeAnswers = new List<int>(); ein neues List-Objekt erstellen und die Referenz der Variable zuweisen. P.S.: Um's anderen weniger schwer zu machen, bitte statt "eine Fehlermeldung" immer die Fehlermeldung posten. Der Inhalt ist ja nicht gerade unwichtig1 point
-
https://groups.google.com/g/google-admob-ads-sdk und hier mal gefragt?1 point