Leaderboard
Popular Content
Showing content with the highest reputation since 03/15/2023 in Posts
-
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
-
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ß Jog1 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