Jump to content
Unity Insider Forum

Sascha

Administrators
  • Content Count

    11,343
  • Joined

  • Last visited

  • Days Won

    547

Sascha last won the day on August 14

Sascha had the most liked content!

Community Reputation

2,321 Excellent

6 Followers

About Sascha

  • Rank
    Community Manager
  • Birthday 08/13/1990

Contact Methods

  • Website URL
    http://www.indiepowered.net

Profile Information

  • Gender
    Male
  • Location
    Hamburg
  • Interests
    Programmierung

Recent Profile Visitors

38,805 profile views
  1. Ja doch, dann sind wir da auf einem Nenner
  2. Mach dir mal ein paar Zeilen davor, mit Debug.Log. Damit kannst du testen, welche der Variablen jetzt den Wert null hat. Kandidaten sind: TrainerStamm TrainerStamm TrainerStamm.Attributes TrainerStamm.Attributes.GetNamedItem("x") TrainerStamm.Attributes.GetNamedItem("y") Je nachdem, ob es sich hier um Objekte oder Struct-Werte handelt, kann jede dieser Variablen als Wert null haben und deshalb die Exception auslösen.
  3. Ne, eben nicht Der Button gibt überhaupt nichts mit. Die Variable "timeOfDay" ist Teil des Zustands dieser Komponente und wird nicht als Parameter mitgegeben. Warum willst du dein Delay in "Start" starten? Du willst doch die Stoppuhr dann starten, wenn der Knopf gedrückt wurde?
  4. 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.
  5. 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.
  6. Du kannst auch einfach deine Variablen statisch machen. Normale Variablen gibt's mit je einem Wert jeweils einmal pro Objekt (wenn du z.B. zwei Lichter hast, kann das eine blau und das andere rot sein, weil die "Farbe"-Variable des Lichts nicht statisch ist). Statische Variablen gibt's nur einmal pro Programm und sind an einem festen Ort, wo jeder Code ihn finden kann, wenn du das möchtest. Da statische Variablen nicht Teil von Objekten sind (also dem Ding im Inspektor, das auftaucht, wenn du da dein Script reinziehst), gehen deren Werte auch nicht flöten, wenn das Objekt durch einen Szenenwechsel zerstört wird. Die Variable existiert einfach einmalig von Anfang bis Ende des Programms. Du kannst das so machen: Statt public int deaths; machst du public static int deaths; Damit ist die Variable statisch. Nach dieser Änderung dürfte dir auffallen, dass "Deaths" auch nicht mehr im Inspektor auftaucht, wenn du dir ein GameObject mit deiner Komponente anschaust. Zugreifen kannst du auf die Variable genau wie vorher, aber zusätzlich auch noch so, wenn du das willst: DerNameDeinesScripts.deaths += 1; Denk aber eben daran, dass es die Variable "deaths" jetzt nur noch genau einmal gibt, also nicht mehr einmal pro Objekt. Wäre die Farbeigenschaft der Lichtkomponente statisch, dann hätten alle Lichter dieselbe Farbe, anstatt dass eines blau sein kann und das andere rot. Bei "wie oft ist der Spieler gestorben" ist das völlig okay, in vielen anderen Fällen natürlich nicht.
  7. Ne, viele Layer helfen da nicht. Ist aber so oder so keine ganz triviale Aufgabe. Du hast ja eine potentiell große Menge eigener Einheiten, die das Sichtfeld aufspannen, und mindestens eine gleich große potentielle Menge gegnerischer Einheiten, die jederzeit sichtbar oder unsichtbar werden können. Der ganz naive Ansatz wäre daher, in regelmäßigen Abständen (muss ja nicht bei jeden Update sein, kann auch seltener oder konsistenter sein) den Abstand von jeder deiner Einheiten zu jeder gegnerischen zu messen und entsprechend die Sichtbarkeit umzuschalten. Das kannst du zwar sogar machen, indem du Gegner auf einen "Unsichtbar"-Layer schiebst... kannst aber auch einfach den Renderer deaktivieren. Das Problem an diesem Ansatz ist, dass der Rechenaufwand exponentiell steigt. Für jede neu gebaute eigene Einheit muss jede existierende gegnerische Einheit also eine Abstandsmessung mehr machen. Bei 20 gegen 20 bist du also bei 20*20 = 400 Berechnungen, bei 30 gegen 30 bist du schon bei 30 * 30 = 900... 50% mehr Einheiten auf beiden Seiten, aber mehr als doppelt so viele resultierende Berechnungen. Das System skaliert also sehr schlecht nach oben hin. Und darum wird die ganze Sache knifflig. Bessere Ansätze bedeuten, dass du dir eine Beschleunigungsstruktur besorgst. Die kannst du dir entweder selber bauen, was eine sehr lehrreiche Sache wäre (kann ich deshalb mal empfehlen), oder du probierst, das zu nutzen, was PhysX (bzw. Box2D) dir mitgibt. Letzteres würde bedeuten, dass du deinen eigenen Einheiten SphereCollider gibst (CircleCollider2D wäre besser, ist aber vermutlich anstrengend umzusetzen, wenn deine Grafik 3D sein sollte). Diese Collider sind auf einem speziellen Layer (damit man ausschließlich gegen diese Gruppe checken kann), und alle gegnerischen Einheiten schauen, ob sie sich in einen solchen Collider hinein- oder hinausbewegen, um sich dann entsprechend sichtbar oder unsichtbar zu machen. Diesen Chack kannst du mit z.B. mit CheckSphere oder einem eigenen Collider machen. Ich denke, die Lösung mit der eingebauten Physikengine kann ganz gut funktionieren, aber nicht selten ist es schwierig, diese Gesamtpakete auf kleinere Jobs zu beschränken. Wenn da unvorhergesehene Probleme auftreten, die sich nur schwer lösen lassen... oder wenn die Performance am Ende nicht so gut ist wie erhofft, dann muss man da etwas selber bauen.
  8. Wenn das da oben wirklich der einzige Code ist und die Meldung bei der längeren Zeile auftritt und ganz sicher nicht woanders, dann ist trainerPrefab einfach nicht gesetzt. Der Code ist soweit nämlich okay, und eine andere Stelle gibt es da nicht, wo dieser Fehler entstehen kann. Wenn du dir ganz sicher bist, dass du da ein Objekt reingezogen hast, ist die wahrscheinlichste Fehlerursache, dass du irgendwo versehentlich mal eine zweite Instanz dieser Komponente irgendwo in deine Szene gesetzt hast, eventuell ohne es zu merken. Schau aber erstmal, ob die Fehlermeldung tatsächlich von genau dieser Zeile kommt und ob da nicht noch ein paar Zeilen mehr im Spiel sind.
  9. 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.
  10. Also... grau und blassgrün und beige sind keine guten Farben dafür. Wenn du nämlich die Straße anschaust, dann besteht dessen Graustufen-Ton zu gleichen Teilen aus rot, grün und blau; den additiven Grundfarben. Wenn du das tust, was Unity's Terrain-Shader (als Beispiel für so genannte Splatmap-Shader) tut: Dann kannst du diese vier Kanäle stattdessen benutzen, um mit ihnen Texturen zu kodieren. Rot steht für Alphalt, grün für Gras, blau für Sand. Da Texturen noch einen vierten Kanal, den Alpha-Kanal haben, kannst du den noch für etwas anderes benutzen. So oder so brauchst du für dieses Vorhaben einen Shader, der fünf Texturen akzeptiert: Die Splatmap, also die Daten, wo welche andere Textur zu sehen ist, und eben die anderen vier Texturen, eine für jeden der vier Kanäle der Splatmap. Du machst dann einen UV-Lookup für jede der fünf Texturen auf jedem Pixel und interpolierst dann die Pixelwerte der vier Texturen in Abhängigkeit vom entsprechenden Wert des Kanals in der Splatmap. Ich könnte da noch spezifischer werden... aber entweder, du kannst das so umsetzen... oder, wenn nicht, solltest du dir ein paar Shadergrundlagen anschauen und ein bisschen mit denen warm werden.
  11. Auch dafür würde ich das hier empfehlen: 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.
  12. 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
  13. Hah, manchmal kann's auch einfach sein Ich meine mich zu erinnern, dass es in den Project Settings beim Sound eine globale Einstellung dafür gibt. Wenn du die ausstellst, brauchst du nicht bei jeder AudioSource einzeln darauf zu achten.
  14. Sascha

    nebel

    Naja, dabei handelt es sich ja nur um "Pixel werden immer grauer (oder was man sonst als Farbe wählt), je weiter sie von der Kamera weg sind". Für so Lichteffekte im Nebel wird's schon etwas aufwendiger. Stichworte dazu wären "God Rays" oder "Sun Shafts", welche du im Standard-PostProcessing-Zeugs dabei hast. So gut wie in The Division sieht das aber auch nicht sofort aus. Wenn das so gut sein soll, würde ich tatsächlich eher mal im Asset Store schauen.
  15. Bleib da auf jeden Fall dabei und versuche das Problem dann zu lösen. Hast du deinen Canvas selbst denn schonmal auf "Pixel Perfect" gestellt?
×
×
  • Create New...