Jump to content
Unity Insider Forum

Sascha

Administrators
  • Posts

    13,611
  • Joined

  • Last visited

  • Days Won

    780

Everything posted by Sascha

  1. Nicht unbedingt. Der Ressourcen-Ordner ist, wenn du mich fragst, auch für 98% der Probleme eine schlechte Lösung. Einfach schon, weil man Strings zum Identifizieren der Assets benutzt. Meistens besser: Ein serialisiertes Feld anlegen (wenn nicht bekannt: einfach "public GameObject prefab;") und da dein Prefab im Inspektor rein ziehen. So ein GameObject hat, wenn du nicht Shakespeare in eine Komponente rein pastest, nicht mal ein KB groß. Mach dir mal nicht wegen drei GameObjects um deinen Speicher Sorgen. Tatsächlich gibt es eine Technik Namens "Pooling", die Objekte recycelt, also deaktiviert und dann wieder re-aktiviert, anstatt ein neues Objekt zu instanziieren, weil Zerstören und Instanziieren weitaus schlechter für die Performance ist als zeitweises Deaktivieren. Nicht, dass das für dich einen Unterschied machen sollte, daher einfach weiter im Kurs - aber ich konnte das nicht stehen lassen, ohne den Samen des Zweifels an dieser Ansicht zu sähen
  2. Mach dir bloß nicht zu viel Hoffnung, dass Unity in nächster Zeit an irgendeiner Front in irgendeiner Weise aufholen wird. Der Firma geht's im Moment gar nicht gut. Die kriegen seit vielen Jahren dieselbe Handvoll Baustellen nicht vernünftig gebacken, und die nächsten Jahre werden noch härter werden, weil bei denen gerade alles drunter und drüber läuft.
  3. Wenn ein Script nicht kompiliert, hast du immer (mindestens) eine Fehlermeldung in deiner Konsole. Die kannst du oben über "Windows -> General -> Console" öffnen. Einmal darin auf Clear drücken, dann verschwinden alle Meldungen, die nicht Compilerfehler sind (also die Fehler, die in deinem Code sind und Unity daran hindern, ihn zu kompilieren und zu benutzen). Wenn du uns den/die Fehler hier hinkopierst, machst du uns damit das Leben viel einfacher Davon mal abgesehen hast du mehrere Male Zeilen in der Form "a - b" im Code. Zwei Dinge voneinander abziehen ist aber keine vollständige Anweisung. Du musst das Ergebnis auch in irgendeiner Weise benutzen, z.B. indem du es in eine Variable schreibst. Ich nehme aber an, dass du in Wirklichkeit einfach nur "=" schreiben wolltest und nicht "-".
  4. Sascha

    Collider

    Moin! "greifen nicht" heißt, dass die Objekte durcheinander fallen ohne zu kollidieren? Sind beide Collider 3D-Collider oder ist einer von beiden 2D? Hast du einen Screenshot von deiner Szene für uns?
  5. Hallo, Willkommen und viel Erfolg!
  6. Moin! Ich hatte schon versucht, das Problem zu erfassen, aber ohne Screenshots klappt's nicht. -200 klingt wie das Gegenteil von "okay", aber mehr weiß ich auch nicht Kannst du sonst nochmal auf irgendeinem anderen Bildhoster hochladen und verlinken?
  7. Moin! Gizmos (also Linien und Icons und so) müssen in der Scene View angeschaltet werden. Der Knopf dafür ist der ganz oben rechts:
  8. Da gibt's viele Ansätze. Ich denke an Dungeon Keeper und dergleichen: Erstmal sind das vom Rendern her gar keine Cubes. Du siehst ja nur die Oberseite, ein Wandmodell oder den Boden. Du kannst also statt Würfeln Quads nehmen. Darüber hinaus kannst du größere Flächen auch partitionieren: Wenn dein Spiel irgendwo 5x5 unangetastete Felder findet, kann es eine 5x5-Fläche rendern statt 25 1x1-er. Wenn du noch weiter gehst, kannst du auch in Echtzeit Chunk-Meshes generieren. Also alle 8x8 (oder was auch immer für Werte gut für dich funktionieren) Felder als ein Mesh rendern, das in Echtzeit generiert wird, wenn sich darin etwas ändert.
  9. There is no way we can help you without any kind of information. We'd need to at least look at your relevant code.
  10. Da kannst du ja direkt ansetzen. public float acceleration = 5f; public float minSpeed = 0f; public float maxSpeed = 10f; void Update() { speed += Input.GetAxis("Vertical") * acceleration * Time.deltaTime; speed = Mathf.Clamp(speed, minSpeed, maxSpeed); distanceTravelled += speed * Time.deltaTime; ... Input.GetAxis ist eine Möglichkeit. Je nach Input-System gibt's dann andere. In jedem Fall kannst du einfach speed anpassen und dadurch ändert sich... naja, deine Geschwindigkeit
  11. Moin! Wie hast du denn deinen Pfad implementiert? Irgendwo in deinem Code müsste dann ja eine Geschwindigkeit drin stehen, mit der du dich den Pfad entlang bewegst. Diese Geschwindigkeit kannst du variabel machen und über Input abändern lassen.
  12. Moin! Der Code hat ein paar Merlwürdigkeiten, ist aber prinzipiell so richtig. (später - früher).Days ist die abgerundete Anzahl an Tagen zwischen später und früher. Hast du dir denn mal deine beiden DateTimes vor dem Verrechnen ausgeben lassen?
  13. Das hier stimmt auf jeden Fall noch nicht. Deine Beschreibung klingt aber so, als wäre das nicht das einzige übrige Problem. Solltest du trotzdem erstmal lösen.
  14. Du hast immer noch genau dasselbe Problem drin. Wenn kein Paket rein kommt, berechnest du trotzdem distanceX neu, wobei immer 0 heraus kommen wird.
  15. Moin! Ich würde vermuten, dass du nicht in jedem Update eine neue Position rein bekommst. Wenn das der Fall ist, hast du mehrere Updates in Folge dieselbe Position, und der Abstand ist entsprechend immer 0. Pack diesen Code am besten direkt hinter den Code, der die neue Position entgegen nimmt und auf den virtuelles Objekt anwendet. Dann musst du natürlich auch statt Time.deltaTime einen eigenen deltaTime-Wert nehmen, der genauso berechnet wird wie distanceX.
  16. Vielleicht mag Unity es nicht, dass das Objekt noch keine Meta-Datei hat, sei es direkt oder eben vom Parent-SO. Wenn du keine Kombination/Reihenfolge findest, solltest du sonst auch jederzeit ein neues SerializedObject erstellen können. Ist wie gesagt nur ein Wrapper zum Bearbeiten. var serializedObject = new SerializedObject(entity);
  17. Moin, ich bin mir nicht ganz sicher, woher das kommt, aber rein von der Logik her würde ich vermuten, dass jede einzelne dieser vier Zeilen AssetDatabase.AddObjectToAsset(newAttribute, this.entity); AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(newAttribute)); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); das Potential hat, das SerializedObject zu disposen. Ein SerializedObject ist ein Wrapper um ein UnityEngine.Object, der für das Editieren dieses Objekts da ist. Deswegen kennt es auch die SerializedPropertys des Objekts. Solange das SerializedObject existiert, soll da auch am besten nicht noch jemand anderes an dem Objekt herum fummeln. Die erste dieser Zeilen editiert halt das Asset, die zweite Importiert es (nach AddObjectToAsset haben ja beide Assets denselben Pfad), und SaveAssets und Refresh sind auch beide von der Idee her nicht damit kompatibel, dass da noch Bearbeitung offen ist. Lange Rede, kurzer Sinn: Versuch mal, mehrere (wenn nicht alle) dieser vier Zeilen unter das letzte ApplyModifiedProperties() zu packen.
  18. Naja, du hast ja zwei Arten von Objekten hier. Das eine ist nach deiner Beschreibung "statisch" (wie gesagt: voll okay, solche Begriffe zu nutzen, auch wenn sie anderswo schon eine feste Bedeutung haben, solange man es erklärt). Das andere Objekt wird instanziiert (oder auch nicht, je nach dem) und reagiert darauf, angeklickt zu werden. Ich sehe da auf jeden Fall zwei Scripts. In dem Fall: ItemPosition public class ItemPosition : MonoBehaviour { public Item item; public ItemRepresentation spawnedItemPrefab; private ItemRepresentation spawnedItem; private void SpawnItem() { // Wenn ich schon ein Item in der Szene habe, dann lass mal if (spawnedItem) return; spawnedItem = Instantiate(spawnedItemPrefab, ...); spawnedItem.item = item; } } ItemRepresentation public class ItemRepresentation : MonoBehaviour { public Item item; private void OnMouseDown() { Inventory.AddItem(item); Destroy(gameObject); } } Ist jetzt nur ein minimales Beispiel, wo sich ein Item immer ins Inventar packt und dann selbst aus der Szene löscht. Was aber auch geht: Du packst den Collider und damit die "Anklickbarkeit" auf das "statische" Objekt. Kann ich mir auch gut vorstellen. Dann brauchst du nur ein Script, weil die Prefab-Kopie nix macht außer hübsch auszusehen. ItemPosition würde sich dann um Inventory.AddItem und Destroy kümmern.
  19. Ja, keine Sorge - ist nix neues. Aber entsprechend muss ich das ansprechen, wenn die Kommunikation uns daran hindert, eine Lösung zu finden. Und vielleicht hast du ja auch auf Dauer was davon, mehr korrekte Begriffe zu kennen Entsprechend auch etwas Terminologie für das, was du geschrieben hast: Ein Prefab ist ein GameObject, das nicht in einer Szene existiert. Instantiate kopiert ein GameObject in die aktuell aktive Szene. (Du kannst damit in der Tat auch GameObjects kopieren, die schon in der Szene sind - es muss kein Prefab sein). Da es in der Tat möglich ist, ein Prefab zu ändern, ist es wichtig, zwischen Prefabs und ihren in der Szene existierenden Kopien zu unterscheiden. Wenn du nämlich "ein Prefab änderst", dann hat das je nach Kontext einige sehr... "interessante" Nebeneffekte. Man redet bei dem, was in der Szene landet, wenn man ein Prefab hinein zieht, daher von einer Prefab-Instanz. Bei dem, was Instantiate zur Laufzeit produziert, übrigens eher nicht. Der entscheidende Punkt, dass geänderte Eigenschaften im Prefab auch in dessen Instanzen übernommen werden, fehlt da nämlich. Dann etwas worüber ich jetzt schon mehrfach gestolpert bin: Es ist völlig okay, dass du auch Begriffe benutzt, die woanders eine feste Bedeutung haben. Aber du solltest hier nicht von "statischen Objekten" reden, ohne einmal kurz zu erklären, was das bedeutet. Meinst du damit einfach nur, dass das Objekt nicht zur Laufzeit erstellt oder zerstört wird, sondern immer vorhanden ist? Also verstehe ich das richtig, dass du ein Script hast, das ein Prefab instanziiert, und das resultierende Objekt hat wiederum ein Script, welches darauf reagiert, dass es angeklickt wurde? Du solltest dringend die Namen deiner Klassen überarbeiten. Es ist zwar schön einfach, die Dinger "IrgendwasManager" zu nennen; aber genau solche Zusammenhänge gehen durch solche Namen verloren. Wenn ich dir als Namen z.B. "ItemPosition" und "ItemRepresentation" vorschlage, dann weißt du sofort, welche Klasse welche wäre. Und so als Tipp: Deine eigene Denkweise kannst du damit auch beeinflussen. Wenn du deine Namen sorgfältig wählst, fällt es dir einfacher, über die Zusammenhänge nachzudenken, in denen sie vorkommen. Wenn deine Annahme jetzt jedenfalls korrekt ist und du den Grund für das Problem gefunden hast, habe ich hier die Lösung für dich: Instantiate gibt dir eine Referenz auf das Objekt zurück, das es erstellt hat. Du kannst also dein neues Objekt direkt bearbeiten. var itemInstance = Instantiate(itemPrefab); itemInstance.representedItem = myItem; Was ich hier übrigens mache, ist bei "itemPrefab" als Typ nicht GameObject, sondern den Typ der relevantesten Komponente zu nehmen: public ItemRepresentation itemPrefab; // oder wie auch immer das bei dir heißt. Da kann man dann alle GameObjects rein ziehen, die diese Komponente haben. Und Instantiate gibt direkt eine Referenz auf diese Komponente auf der erstellten Kopie zurück, sodass man sich ein GetComponent sparen kann.
  20. Liegt vielleicht daran, dass ich echt müde bin, aber hier verstehe ich nix. SOs erzeugst du nicht - zumindest nicht über Runtime-Code. Also... kannst du, aber... machst du nicht. Was heißt "übernommen"?
  21. Joa, da kann eine NRE definitiv her kommen Was denn für ein neues Script? Warum baust du deinen Code nicht einfach so, dass das Objekt nur dann verwendet wird, wenn es auch Relevanz hat? Du kannst doch wunderbar schreiben, dass etwas anderes (z.B. auch "gar nichts") passieren soll, wenn kein Item da ist: public class TreasureChest : MonoBehaviour { public Item loot; public void Open() { if (loot != null) { PlayerInventory.Add(loot); loot = null; } else { Debug.Log("Ich bin leer :("); } } } Wenn "Mein klickbares Objekt hat nix mit irgendeinem Item zu tun, weil es z.B. eine Tür ist" ein valider Fall in deinem Gamedesign ist, dann sollte dein Code diesen Fall auch unterstützen. Der Code wird nicht neu kompiliert. Das passiert nur, wenn sich etwas im Code ändert - und dann siehst du das unten rechts am sich drehenden Ladekreis, und evtl. auch am Dialog mit Fortschrittsbalken. Wenn du in den Play Mode gehst, wird die offene Szene einmal entladen, das Programm neu gestartet und die Szene neu deserialisiert (geladen). Dass da durch das Starten des Spiels ohne dein Zutun irgendwelche Referenzen verloren gehen, kannst du im Normalfall ausschließen.
  22. Dann ist es sehr unwahrscheinlich, dass das Item irgendwo gelöscht wurde - geht ja bei Assets nicht mal eben mit Destroy(). So oder so heißt das aber, dass da ein ObjectManager herumfliegt, der kein Item referenziert. Das müsstest du eigentlich über den Inspektor nachvollziehen können. Also einmal in die Szene navigieren und die ObjectManager-Instanzen durchgehen. Dann weißt du schonmal, welches Objekt da Probleme macht. Anschließend kannst du das Objekt außerhalb des Play Modes anschauen und sehen, ob das schon falsch im Editor eingestellt ist oder die Referenz zur Laufzeit flöten geht.
  23. Du solltest niemals einfach blind irgendwas rauskürzen, in der Hoffnung, das der Fehler verschwindet. Der Code, der dann übrig bleibt, wird mit allerhöchster Wahrscheinlichkeit nicht das tun, was du willst. Und das ist auch nicht wirklich mehr Wert als Code, der nicht kompiliert. "Item" ist also eine ScriptableObject-Klasse, richtig? Und deine Items existieren alle in den Assets? Und du ziehst sie dann in deine "ObjectManager"-Instanzen in der Szene?
  24. Genau - ein bool ist ein "Value Type", zu denen auch Zahlen, Chars und Structs (z.B. Vector3) gehören. Value Type-Variablen können nicht null als Wert annehmen und entsprechend nie diese Exception auslösen. Unabhängig von deinem spezifischen Problem und dessen Lösung ist es sinnvoll, dass du dir Werkzeuge aneignest, mit denen du sie sehen kannst. Debug.Log ist schon ganz nett, aber gerade bei noch nicht richtig lokalisierten Problemen etwas unpraktisch. Schau dir mal an, wie du mit deiner IDE den Debugger benutzt. Du setzt einen Breakpoint auf die von der Fehlermeldung genannten Zeile, verbindest den Debugger mit Unity "spielst" bis zum Problem-Moment. Dann kannst du dir schön den Zustand deines ObjectManager-Objekts und aller relevanten Variablen ansehen. Eine Variable, die null als Wert hat, sticht dann schnell heraus. Mit dem Debugger kannst du spätestens im nächsten Schritt auch früher ansetzen und schauen, wie es dazu kommt, dass da null steht.
  25. Moin! NullReferenceExceptions (NREs) sind nicht annähernd so undurchsichtig, wie man vielleicht initial glaubt. Erstmal wäre in der Konsole die Zeile zu finden, in der die Exception geflogen ist. Damit weißt du schonmal mehr. Dann kann eine NRE immer nur davon kommen, dass vor einem Punkt oder einer eckigen Klammer etwas den Wert null hat. Wenn du also z.B. irgendwas.Zeug().liste[5] hast, dann könnte "irgendwas" null sein, "Zeug()" null zurück geben, oder "liste" ist null. Damit solltest du das Problem schonmal stark eingrenzen können.
×
×
  • Create New...