minuschki Geschrieben 28. Februar 2020 Melden Share Geschrieben 28. Februar 2020 Hallo zusammen Ich möchte ein Bild um 90° drehen lassen, sobald man es anklickt. Dabei soll die Drehung animiert sichtbar sein und nicht direkt auf 90° springen. Wenn ich die schrittweise Rotation in eine for-Schleife einbaue, wird diese wohl 90 mal durchlaufen aber man sieht die Zwischenschritte der Rotation nicht. Gibt es einen Befehl, um innerhalb der for-Schleife ein frame update zu erzwingen, damit die Animation auch tatsächlich angezeigt wird oder löst man das ganze Drehproblem anders? Danke für eure Hilfe! for (int i=0; i=<90; i++) transform.rotation = i; Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 28. Februar 2020 Melden Share Geschrieben 28. Februar 2020 Für so etwas sind Coroutinen super geeignet. Es geht auch in Update (und manchmal, je nach Situation, ist das sogar die bessere Variante), aber Coroutinen sollte man sich so oder so mal anschauen. Kurz: Coroutinen sind Methoden, die an beliebigen Stellen in ihrem Code einen oder mehrere Frames warten können. Sie werden dann unterbrochen und beim nächsten Update weiter von der Zeile ausgeführt, wo sie unterbrochen wurden. Das ganze funktioniert so: public void StartRotation() { // StartCoroutine ist wichtig, sonst hört die Coroutine beim ersten Warten auf und wird NICHT mehr fortgesetzt StartCoroutine(Rotation()); } private IEnumerator Rotation() // IEnumerator als Rückgabetyp { const float duration = 1f; // Ausgangsrotation var from = transform.localRotation; // Zielrotation (90° weiter) var to = from * Quaternion.Euler(0, 0, 90); // So eine Schleife ist praktsich, um etwas über x Sekunden laufen zu lassen, aber kein nötiger Teil einer Coroutine for (var time = Time.deltaTime; time < duration; time += Time.deltaTime) { var progress = time / duration; // Geht im Verlauf von 0 bis 1 transform.localRotation = Quaternion.Slerp(from, to, progress); yield return null; // Einen Frame warten } transform.localRotation = to; } Wichtig sind hier: StartCoroutine um den Aufruf der Methode herum. IEnumerator als Rückgabetyp. Dafür musst du oben "using System.Collections;" drinhaben. "yield return null;" Das ist die Zeile, die einen Frame lang wartet - der Rest deines Spiels läuft weiter und beim nächsten Update wird die Coroutine hier fortgesetzt, was in diesem Fall heißt: Der nächste Durchlauf der For-Schleife beginnt. Du kannst deiner Coroutine-Methode auch Parameter geben: public void StartRotation() { StartCoroutine(Rotation(90f, 1f)); } private IEnumerator Rotation(float angle, float duration) { var from = transform.localRotation; var to = from * Quaternion.Euler(0, 0, angle); // ... Und statt "null" kannst du auch andere Dinge in "yield return" reinstecken. Bekanntestes Beispiel ist: yield return new WaitForSeconds(2f); // Warte 2 Sekunden Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
minuschki Geschrieben 28. Februar 2020 Autor Melden Share Geschrieben 28. Februar 2020 Besten Dank! Funktioniert wunderbar. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
minuschki Geschrieben 28. Februar 2020 Autor Melden Share Geschrieben 28. Februar 2020 Es gibt doch noch ein Problem! Wenn die Animation in 2 Sekunden ablaufen soll, der Anwender aber innerhalb der laufenden Animationen nochmals auf das Bild klick, wird die Coroutine neu gestartet, was zu unerwünschten Winkeln führt. Anstatt 90°, 180° oder 270° bleibt das Bild z.B. auf 127° stehen! public void OnMouseDown() { // Hier müsste noch eine Bedingung stehen, die einen Neustart der Coroutine erst erlaubt, wenn eine 90° Drehung abgeschlossen ist! if () { StartCoroutine(drehen(90f, 2f));//Drehwinkel und Dauer in Sekunden } } Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 28. Februar 2020 Melden Share Geschrieben 28. Februar 2020 Jau, das ergibt Sinn, weil die Coroutine am Anfang den aktuellen Winkel nimmt und da 90° draufrechnet. Die erste Frage ist jetzt: Willst du, dass ein Klick, der während einer Laufenden Drehung kommt, ignoriert wird, oder willst du dann direkt noch einmal 90° dazu haben? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
minuschki Geschrieben 29. Februar 2020 Autor Melden Share Geschrieben 29. Februar 2020 Variante 2 wäre in diesem Fall erwünscht. Will heissen: Weitere Klicks innerhalb einer laufenden Animation sollen registriert werden und zu weiteren 90°-Drehungen führen. 3 Klicks würden also eine Drehung um 270° erzeugen. Natürlich wäre es für mich auch interessant zu wissen, wie man einen Klick ignorieren könnte, falls das nicht zu viel Mühe bedeutet. Danke für die Geduld! Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 29. Februar 2020 Melden Share Geschrieben 29. Februar 2020 Direkt die nächste Frage: Soll das Objekt dann auf das Ziel springen und von dort aus 90° weiterdrehen? Oder soll man zehn Mal klicken können und dann dreht sich das Ding ne Minute lang? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
minuschki Geschrieben 1. März 2020 Autor Melden Share Geschrieben 1. März 2020 Hallo Sascha Ich habe das nun mal versucht so zu lösen, wie es im Code steht. Das heisst: Ein Klick startet die Coroutine nur, wenn gerade keine Drehung ausgeführt wird. Bei Beendigung der Drehung wird aktion wieder auf false gesetzt. Das hat zur Folge, dass keine "ungeraden" Winkel entstehen, sondern immer 0°, 90°, 180° oder 270°. Allerdings hat das den Nachteil, dass Klicks innerhalb der Drehbewegung ignoriert werden. Ziel wäre eigentlich, dass wenn der Anwender zum Beispiel einen Doppelklick innerhalb der 2 Sekunden ausführt, sich das Bild um 180° drehen würde, aber ohne direkten Spung auf das Ziel. So das eine fliessende Drehbewegung ablaufen würde. Meine Vermutung ist, dass man eine Art Klickzähler einbauen müsste, der dann "abgearbeitet" wird. public void OnMouseDown()// Mit linker Maustaste drehen { if (aktion == false) { StartCoroutine (drehen (-90f, 2.0f));//Drehwinkel und Dauer in Sekunden aktion = true; } } Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 1. März 2020 Melden Share Geschrieben 1. März 2020 Alles klar. Für das, was es aktuell macht, ist dein Ansatz genau richtig. Wenn du immer weiter drehen willst, würde ich eventuell von Coroutinen wieder weggehen, da die Vorteile etwas weniger werden; du hast dann keinen festen Ablauf mit bestimmtem Anfang und Ende mehr. Das kriegen Coroutinen zwar auch hin, aber du hast weniger davon. So oder so denke ich, dass es eine gute Idee war, dass du sie dir angeschaut hast Die größte Herausforderung an der Sache ist, zu verhindern, dass dein Pfeil nicht den kürzesten Weg nimmt und dafür einfach gegen den Uhrzeigersinn dreht, und auch mehrere Runden läuft wenn oft genug gedrückt wurde. Basisidee, jetzt wieder mit Update, wäre so etwas: (weg damit, besserer Code weiter unten) Ist leider etwas komplizierter Code für so etwas scheinbar einfaches, aber wie gesagt... soll sich ja nicht rückwärts drehen oder eine ganze Runde zu früh Schluss machen oder so. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
minuschki Geschrieben 4. März 2020 Autor Melden Share Geschrieben 4. März 2020 Danke für deine Antwort! Es funktioniert aber nicht richtig! Wenn ich den Code einfüge, beginnt das Bild direkt nach dem Start von alleine an zu drehen. Ein Mausklick auf das Bild lässt es auf 0° springen und es beginnt von Neuem sich zu drehen. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 4. März 2020 Melden Share Geschrieben 4. März 2020 Öh ja, das letzte else war falsch. Hatte das so runtergetippt. Hab's mal repariert, aber immer noch nicht getestet Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
minuschki Geschrieben 6. März 2020 Autor Melden Share Geschrieben 6. März 2020 Sorry Sascha Nun macht es keinen Mucks mehr. Das Bild dreht sich zwar nicht mehr von alleine, aber eben auch nicht, wenn ich auf das Bild klicke! Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 6. März 2020 Melden Share Geschrieben 6. März 2020 Bin nach wie vor nicht dazu gekommen, das auch mal zu testen, hatte jetzt aber ein paar Minuten in Unity dafür. Hab's übern Haufen geworfen und was ganz neues gebaut. Das hier ist wesentlich kürzer... und funktioniert sogar private float remainingAngle = 0f; public float speed = 10f; private void OnMouseDown() { remainingAngle += 90f; } private void Update() { if (remainingAngle <= 0f) return; var amount = speed * Time.deltaTime; remainingAngle -= amount; transform.Rotate(0, 0, amount); if (remainingAngle <= 0f) { remainingAngle = 0f; var euler = transform.localEulerAngles; euler.z = 90f * Mathf.Round(euler.z / 90f); transform.localEulerAngles = euler; } } Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
minuschki Geschrieben 7. März 2020 Autor Melden Share Geschrieben 7. März 2020 Yep! Jetzt funktioniert es super! Ich habe nun versucht aus der Linksdrehung eine Rechtsdrehung zu machen. Könntest du mal einen Blick drauf werfen, ob die vorgenommenen 4 Änderungen (kommentiert) korrekt sind? Ansonsten besten Dank für deine Bemühungen und den Tipp mit der Coroutine! private float remainingAngle = 0f; private float speed = 200f; private void OnMouseDown() { remainingAngle += -90f; // Hier einen negativen Winkel eingeben } private void Update() { if (remainingAngle >= 0f) return; // Hier grössergleich anstatt kleinergleich var amount = -speed * Time.deltaTime; // Hier speed auf minus setzen remainingAngle -= amount; transform.Rotate(0, 0, amount); if (remainingAngle >= 0f) // Hier grössergleich anstatt kleinergleich { remainingAngle = 0f; var euler = transform.localEulerAngles; euler.z = 90f * Mathf.Round(euler.z / 90f); transform.localEulerAngles = euler; } } Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 7. März 2020 Melden Share Geschrieben 7. März 2020 Ich würde ehrlich gesagt alle Änderungen streichen, da der Code aktuell einfach sagt "es sind noch x° zu drehen". "-x° übrig" ergibt dabei keinen Sinn. Und obwohl es funktionieren dürfte, sind Dinge, die nicht für einen normal Denkenden unlogisch sind, immer potentielle Fehlerquellen. Als einzige Änderung würde ich daher machen: transform.Rotate(0, 0, -amount); und der Rest bleibt, wie es ist: runterzählend. vor 5 Stunden schrieb minuschki: Ansonsten besten Dank für deine Bemühungen und den Tipp mit der Coroutine! Gerne Früher oder später wird das sowieso nützlich Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Recommended Posts
Archiviert
Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.