Jump to content
Unity Insider Forum
  • Announcements

    • Lars

      Allgemeine Forenregeln   03/13/2017

      Forenregeln Nimm dir bitte einen Moment um die nachfolgenden Regeln durchzulesen. Wenn du diese Regeln akzeptierst und die Registration fortsetzen willst, klick einfach auf den "Mit der Registrierung fortfahren"-Button. Um diese Registration abzubrechen, klick bitte einfach auf den "Zurück" Button deines Browsers. Wir garantieren nicht für die Richtigkeit, Vollständigkeit und Brauchbarkeit der Nachrichten und sind auch nicht dafür verantwortlich. Die Beiträge drücken die Meinung des Autors des Beitrags aus, nicht zwangsläufig das, wofür die Forensoftware steht. Jeder Nutzer, der denkt, dass ein veröffentlichter Beitrag unzulässig bzw. störend ist, ist aufgefordert uns unverzüglich per E-Mail zu kontaktieren. Wir haben das Recht störende Beiträge zu löschen und bemühen uns, das in einem realistischem Zeitraum zu erledigen (sofern wir beschlossen haben, dass die Löschung notwendig ist). Du akzeptierst, durchgehend während der Nutzung dieses Services, dass du dieses Forum nicht dazu missbrauchen wirst, Inhalte zu veröffentlichen, welche bewusst falsch und/oder verleumderisch, ungenau, beleidigend, vulgär, hasserfüllt, belästigend, obszön, sexuell belästigend, bedrohlich, die Privatsphäre einer Person verletzend oder in irgend einer Art und Weise das Gesetz verletzen. Des Weiteren akzeptierst du, dass du keine urheberrechtlich geschützte Inhalte ohne Erlaubnis des Besitzers in diesem Forum veröffentlichst. Mit dem Klick auf den "Mit der Registrierung fortfahren"-Button, akzeptierst du zudem unsere Datenschutzerklärung und stimmst der Speicherung deiner IP-Adresse und personenbezogenen Daten zu, die dafür benötigt werden, um dich im Falle einer rechtswidrigen Tat zurückverfolgen zu können bzw. permanent oder temporär aus dem Forum ausschließen zu können. Es besteht keine Pflicht zur Abgabe der Einwilligung, dies erfolgt alles auf freiwilliger Basis.   Zusatzinformationen Der Forenbetreiber hat das Recht, Nutzer ohne Angabe von Gründen permanent aus dem Forum auszuschließen. Des Weiteren hat er das Recht, Beiträge, Dateianhänge, Umfrage, Blogeinträge, Galleriebilder oder Signaturen ohne Angabe von Gründen zu entfernen. Mit der Registrierung verzichtest du auf alle Rechte an den von dir erstellten Inhalten, bzw. treten diese an das Unity-Insider.de und Unity-Community.de ab. Dies bedeutet im Klartext, dass das Unity-Insider.de und Unity-Community.de frei über deine Texte verfügen kann, sofern diese nicht wiederum die Rechte anderer verletzen. Es besteht weiterhin kein Anspruch von registrierten Nutzern bzw. ehemaligen registrierten Nutzern darauf, dass erstellte Inhalte und/oder die Mitgliedschaft (User) wieder gelöscht werden (Erhaltung der Konsistenz dieses Forums).   Einwilligungserklärung Wenn du mit der Speicherung deiner personenbezogenen Daten sowie den vorstehenden Regeln und Bestimmungen einverstanden bist, kannst du mit einem Klick auf den Mit der Registrierung fortfahren-Button unten fortfahren. Ansonsten drücke bitte Zurück. Stand: 07.03.2011

Sascha

Administrators
  • Content count

    10,112
  • Joined

  • Last visited

  • Days Won

    417

Sascha last won the day on November 5

Sascha had the most liked content!

Community Reputation

2,003 Excellent

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

26,498 profile views
  1. Wert kontinuierlich erhöhen

    Du kannst fürs Erste davon ausgehen, dass Update 60 Mal pro Sekunde aufgerufen wird. Das bedeutet hier, dass du 60 Mal pro Sekunde checkst, ob currentPoints kleiner als maxPoints ist und wenn das der Fall ist, startest du die Coroutine. Da die Coroutine genau zehn Sekunden (= Wert von plusPoints) braucht, damit currentPoints um eins erhöht wird, wird in der Zwischenzeit, bis es soweit ist, weiterhin 60 Mal die Sekunde festgestellt, dass currentPoints größer sein müsste. Du startest also 10 Sekunden lang 60 Mal pro Sekunde, also insgesamt 600 Mal diese Coroutine. Und die bricht natürlich nicht ab, nur weil currentPoints jetzt den Zielwert erreicht hat. Einmal gestartet, läuft die weiter, es sei denn, du brichst sie ab. Und das tust du nicht. Das heißt wiederum: Wenn du wirklich nur einen Punkt unter dem Ziel lagst, dann hast du dank 600-Maligen starten der Coroutine immer noch 599 Punkte zu viel am Ende, weil der Punktestand nach den ersten 10 Sekunden 60 Punkte pro Sekunde hochzählt - weil die Coroutinen jetzt alle ihre 10 Sekunden fertig haben. Soviel zum "Was hier alles falsch ist". Jetzt aber Mal zur Lösung. Du willst auf keinen Fall in Update ständig dieselbe Coroutine starten - sonst landest du ziemlich schnell bei dem, was ich gerade beschrieben habe. Du willst entweder eine Coroutine dauerhaft am Laufen haben - oder gar keine, und das ganze in Update klären. Ich denke, die Update-Variante ist hier erstmal einfacher und unproblematischer. Je nach Anwendungsfall kann aber immer mal etwas anderes sinnvoll sein. Du baust dafür einfach eine neue private float-Variable, die den Wert einer Stoppuhr annimmt: private float pointRegenTimer = 0; public float pointRegenDelay = 10; "pointRegenDelay" ist deine Variable "plusPoints", nur umbenannt, damit der Variablenname aussagekräftiger ist. In Update hast du ja deinen Check, ob Punkte aufgefüllt werden müssten. Diesen benutzt du jetzt nicht mehr, um deine Coroutine zu starten (die kommt ganz weg), sondern, um den Timer weiterlaufen zu lassen: if (currentPoints < maxPoints) { pointRegenTimer += Time.deltaTime; Time.deltaTime ist immer die jeweilige Zeit seit dem letzten Frame, also bei 60 FPS 0.16666... . Damit zählst du immer ziemlich gneau 1 pro Sekunde hoch. Dann kannst du nach dem hochzählen direkt mal checken, ob der Timerwert über dem Delaywert ist: if(pointRegenTimer > pointRegenDelay) { und wenn das der Fall ist, den Timer um ein delay zurücksetzen: pointRegenTimer -= pointRegenDelay; und gleich im Anschluss das tun, was auch immer du nach abgelaufenem Timer machen willst: currentPoints++; Dann noch Klammern zu: } } und fertig. Jetzt gibt es noch eine kleine Verbesserung für Extremfälle. Sollte dein delay sehr klein und/oder dein Time.deltaTime wegen niedriger FPS sehr groß sein, dann könnte es ja passieren, dass der Timer zweimal in einem Frame durchläuft. Komisches Beispiel: Wenn du also etwas 50 Mal pro Sekunde haben willst, aber das Spiel gerade leider nur auf 30 FPS läuft. Für diesen Fall solltest du die if-Abfrage noch in eine while-Schleife abändern. Eine while-Schleife funktioniert genau wie eine if-Abfrage, außer dass die so lange wiederholt, bis die Bedingung nicht mehr zutrifft. Der fertige Update-Code sieht dann so aus: void Update() { if (Input.GetButtonDown("Mouse1")) { currentPoints -= 1; } if (currentPoints < maxPoints) { pointRegenTimer += Time.deltaTime; while(pointRegenTimer > pointRegenDelay && currentPoints < maxPoints) { pointRegenTimer -= pointRegenDelay; currentPoints++; } } } Bemerke, dass die while-Schleife jetzt noch prüft, ob wir schon maxPoints erreicht haben. Wenn ja, kann sie direkt aufhören, die Punkte zu erhöhen - egal, ob der Timer weit genug durchgelaufen ist. Wenn du es richtig schick haben willst, kannst du noch nach der while-Schleife eine kleine Abfrage machen, die dafür sorgt, dass der Timer, wenn wir das erste Mal wieder unter maxPoints gehen, wieder genau bei 0 zu zählen anfängt: if(currentPoints == maxPoints) { pointRegenTimer = 0; }
  2. Editor

    Du hast nicht ernsthaft gerade den gesamten Inhalt des Themas geändert? Nächstes Mal bitte einfach darum bitten, dass einer von uns das Thema für dich verschiebt und dann ein neues Thema aufmachen, danke.
  3. Falk stellt sich vor

    Wenn du sogar die Nerven für Arma-Modding hast, dann wirst du mit Unity weit kommen
  4. Willkommen! So ein Third Person Controller ist irgendwie sowas wie die Aufnahmeprüfung zum fortgeschrittenen Scripting. Nicht die schwerste Übung, aber auch nichts was man als allererstes problemlos hinkriegt. Prinzipiell bist du am Anfang mit allgemeineren Lektionen gut bedient (z.B. die Scripting Tutorials von Unity oder meinem C#-Einsteigerkurs). Wenn du die Grundkonzepte (Kontrollstrukturen, Komponenten, Component Caching, Input Manager, FixedUpdate, Vektoren, öffentliche Variablen als Eigenschaften im Editor, ...) dann drauf hast, kannst du dich an den TPS-Controller wagen. Für sich bewegende menschenartige Figuren eignen sich je nach Situation Rigidbody oder CharacterController. In den meisten Fällen, denke ich, hat man mit Rigidbodys viel zu viele Features am laufen, die man gar nicht braucht oder gegen die man sogar ankämpfen muss, um ein Verhalten zu erzeugen, das sich gut anfühlt. Daher bleibe ich mal beim CharacterController. Zuerst einmal machst du dir ein Grundgerüst: Ein Script, das sich einen CharacterController cached und damit in FixedUpdate arbeiten kann: using UnityEngine; public class TPSController : MonoBehaviour { private CharacterController controller; void Awake() { controller = GetComponent<CharacterController>(); } void FixedUpdate() { // Bewegung! } } Dieses Script muss dan logischerweise auf ein GameObject, das ebenfalls eine CharacterController-Komponente besitzt. In FixedUpdate kommt jetzt dein Bewegungs-Code. Irgendwie sowas: var input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); // Input-Vektor basteln input = Vector3.ClampMagnitude(input, 1); // Auf Länge 1 begrenzen controller.Move(input * Time.deltaTime); Damit kann das Ding jetzt schomal durch die Gegend laufen, aber besonders dolle ist das noch nicht. Mit 1m/s ist die Figur nicht sonderlich schnell unterwegs. Sie fällt auch nicht runter, weil CCs im Gegensatz zu Rigidbodys nicht von alleine runterfallen. Also bauen wir erstmal oben (unter "private CharacterController controller;") ein paar sinnvolle öffentliche Variablen und einen velocity-Vektor zum Dran-rumspielen: private Vector3 velocity; public float speed = 10; public float gravity = 10; und ändern den Code damit: var input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); // Input-Vektor basteln input = Vector3.ClampMagnitude(input, 1); // Auf Länge 1 begrenzen if(controller.isGrounded) { velocity = movement; velocity.y = -1; } else { velocity.y -= gravity * Time.deltaTime; } controller.Move(velocity * Time.deltaTime); // nicht mehr "input"! Wir fragen in FixedUpdate ab, ob der CharacterController Bodenkontakt hat (isGrounded) und wenn ja, laufen wir in die Richtung des Input-Vektors. Wenn wir allerdings in der Luft sind, dann beschleunigen wir mit der angegebenen Gravitation. Bevor ich jetzt aber noch weiter gehe und anfange, über Kamera-Kontrolle und dessen Einfluss auf die Laufrichtung der Figur zu erzählen... hilft dir das irgendwie? Ich kann nicht so richtig einschätzen, wie viel Grundlagenwissen du schon angesammelt hast. Wenn du bei meinem Kram da oben nur Bahnhof verstehen solltest, dann fang einfach an, die verlinkten Tutorials durchzuarbeiten. Keine Sorge - mit denen wird nach und nach klar, was ich hier geschrieben habe. Wenn du allerdings schon weiter bist und mit dem Code hier klarkommst, dann sag bescheid - dann erzähle ich gerne weiter!
  5. Game View wird plötzlich grau

    Jenes. Habe den Thread gerade erst gesehen, aber das ist auch schon das einzige Problem. Der Editor kann sich immer mal wieder nicht entscheiden, ob er gerade das Spiel abspielt oder das Licht neu berechnen soll, wofür er existierende Lightmap-Infos erstmal über den Haufen wirft. Danach baut er aber keine neuen Infos, weil ja der Play Mode an ist.
  6. Leveleditor mit Sprites und deren Priorität

    Warum nicht einfach mehrere SpriteRenderer nehmen und die Teile, die hinten sein sollen, auch nach hinten packen? Wird doch sowieso ge-batch-ed.
  7. Unity Remote 5 für Unity 2017

    Ich meine nicht die Performance, sondern ob deine Auflösung vielleicht "komisch" ist. "Komisch" ist eine sehr schlecht einzuschätzende Größe, aber ich hab manchmal das Gefühl, dass es daran scheitern kann. Dass es am Handy liegt, halte ich aber auch für wahrscheinlicher. Kannst du den mit "Build & Run" direkt auf das Gerät pushen?
  8. Unity Remote 5 für Unity 2017

    Wie sieht denn deine Game View aus? Die ganze Remote-Pipeline läuft ja darüber, dass das in der Game View gerenderte Bild verpackt und über USB verschickt wird. Wenn deine Game View jetzt irgendwie merkwürdig klein oder so ist, kann das schonmal problematisch sein. Hatte ich zumndest das Gefühl. So instabil, wie das läuft, ist es manchmal schwer zu erkennen, warum genau es das tut. Im schlimmsten Fall kann's auch an deinem Handy liegen. Ich meine mich zu erinnern, dass ich für mein Motorola komische Software installieren musste, bevor die Kommunikation zwischen Unity und Android einigermaßen reibungslos lief.
  9. GetComponents Frage

    Ja ne, da denk mal lieber nochmal drüber nach.
  10. GetComponents Frage

    Was machst du denn da eigentlich, wird das ein Editor-Tool? In den allermeisten Fällen stimmt nämlich irgendetwas ganz und gar nicht, wenn man zu Reflection greift.
  11. Unity Remote 5 für Unity 2017

    Hab's gerade nochmal getsetet - bei mir funktioniert das. Etwas wackelig, aber ich glaube, das liegt an meinem Kabel, das einen leichten Wackelkontakt hat. Meiner Erfahrung nach ist man immer auf der sichersten Seite, wenn man den Unity-Editor überhaupt erst startet, wenn Unity Remote bereits auf dem Handy offen ist. Edit: Vielleicht ist's auch nicht das Kabel. Das Ding ist immer noch ziemlich instabil. Es hängt z.B. davon ab, wie's deiner Game View geht - wenn du sie resized, während die Verbindung steht, friert die App erstmal ein. Hab's jetzt ein paar mal auch nicht zum Laufen gekriegt, aber als ich dann alles genau Schritt für Schritt gemacht habe, ging's: Unity Editor auf Remote eingestellt haben Unity Editor aus, App aus, Handy abstöpseln. Handy anschließen App öffnen, warten bis geöffnet Editor starten Play Mode starten
  12. Gegner bewegung

    Freut mich!
  13. Gegner bewegung

    Jau. Keine Ahnung, was da schief gelaufen sein könnte. Aber in der Regel sagt die Fehlermeldung ja recht spezifisch aus, warum das nicht geht - dann muss man nicht blind rumexperimentieren Ne, umgekehrt. if(hit.collider) { print("Getroffen: " + hit.collider.gameObject.name); } else { print("Nichts getroffen."); } Viel Erfolg!
  14. Hm... vielleicht sollte ich meine Klasse mal auf Github als Gist hochladen.
  15. Gegner bewegung

    Dein Code, wie du ihn da hast, kann eigentlich gar nicht kompilieren. Naja, nicht alleine. Der Grund: Variablen leben nur innerhalb des Rumpfs (der Bereich zwischen den { } ), in dem sie deklariert werden. { int zahl = 5; print(zahl); // Alles ok. "zahl" existiert hier noch. } print(zahl); // Fehler! "zahl" existiert hier nicht mehr. Wozu genau dieser Rumpf gehört (if, while, for, garnix, Methode...), ist dabei völlig wurscht. Dein "hit" der da in der if-Abfrage abgefragt wird exsitiert also gar nicht, es sei denn, du hast noch eine Variable, die so heißt. int zahl = 5; void Start() { { int zahl = 10; } print(zahl); // Wird 5 ausgeben, weil es sich auf die obere Deklaration bezieht } Dieser Fall stellt keinen Syntaxfehler dar, ist aber aus offensichtlichen Gründen potentieller Verwirrung zu vermeiden. Wir haben hier zwei Variablen namens "zahl". Die "zahl"-Variable, deren Wert 10 ist, existiert nur innerhalb ihres kleinen Rumpfes. Das "print" danach kann sich deshalb nur auf die andere Variable desselben Namens beziehen. Daher wird 5 ausgegeben. Ich denke mal, genau das passiert hier. Du hast irgendwo weiter oben einen RaycastHit2D deklariert und dein if bezieht sich darauf. Diese andere "hit"-Variable muss weg. Und damit deine richtige Variable angesprochen werden kann, muss sie außerhalb des if-Rumpfes deklariert werden, damit sie nach dem if noch existiert. Der Trick: Den Wert zuweisen kannst du trotzdem im if-Rumpf, denn dieses ganze Lebensdauer-Gedöns gilt nur für Deklarationen, nicht Werte. RaycastHit2D hit; if(foo) { hit = Physics2D.Raycast( ... ); } else { hit = Physics2D.Raycast( ... ); } if(hit.collider && laufen) { ... } Bemerke übrigens, dass Physics2D.Raycast niemals null zurückgibt. Daher wird if(hit) // was dasselbe ist wie if(hit != null) immer den Rumpf darunter ausführen. Wenn du abfragen willst, ob ein 2D-Raycast etwas getroffen hat, musst du "hit.collider" checken. Steht so in der Anleitung if(hit.collider) Was die Visualisierung angeht: Ja, das geht. Dafür hat Unity die Events OnDrawGizmos und OnDrawGizmosSelected. Das erste malt Debug-Dinge in die Szene View (nicht ins Spiel selbst!), das zweite ebenso, aber nur, wenn das Objekt, auf dem das Skript liegt, markiert ist. Oder einer seiner Parents. Innerhalb dieser Methoden kannst du die Gizmos-Klasse benutzen, um alles mögliche zu zeichnen. Beispiel: void OnDrawGizmosSelected() { Gizmos.color = Color.blue; // Warum nicht Gizmos.DrawRay(transform.position, new Vector2(0.2f, 0)); } Zuletzt noch: Deine Parameter im Raycast sind etwas verwirrend. Du hast: origin: Bei dir transform.position. Das heißt, der Raycast geht genau beim Pivot des Objekts los. Das klingt erstmal okay. direction: Bei dir jeweils ein Vector3 nach links oder rechts, mit der Länge 0.03f. Das ist etwas komisch, weil die Länge dieses Vektors egal ist. Die maximale Reichweite des Raycasts bestimmst du mit dem nächsten Parameter: distance: 0.1f oder 0.5f. Warum schaut deine Figur nach links und rechts unterschiedlich weit?
×