KaBau Geschrieben 31. März 2019 Melden Share Geschrieben 31. März 2019 Hi, ich habe häufig die Anforderung, dass am Anfang (beim Start oder beim Aktivieren des Script), sich der Wert einer Variable in einem definierten Zeitraum vom Wert "A" zu Wert "B" ändern soll. Im beigefügten, funktionierndem Beispiel soll die Drehgeschwindigkeit "backRotSpeed" von 0.0f auf 0.3f innerhalb von 5 Sekunden ansteigen: public class EnyBBackRotY : MonoBehaviour { float backRotY; [SerializeField] float backRotSpeed = 0.3f; float realBackRotSpeed = 0.0f; float slowBackRotEnd; float slowBackRotSlowDown; [SerializeField] float slowRotDuration = 5.0f; [SerializeField] Transform player; [SerializeField] float between = 1.0f; bool slowRotYes = true; private void Start() { backRotY = transform.eulerAngles.y; slowBackRotEnd = Time.time + slowRotDuration; slowBackRotSlowDown = backRotSpeed / slowRotDuration / 50; // durch 50 für die Durchläufe in der Fixupdate Methode } private void Update() { if (player.transform.position.x > between) { backRotY += 1 * realBackRotSpeed * (player.transform.position.x - between); } if (player.transform.position.x < -between) { backRotY += 1 * realBackRotSpeed * (player.transform.position.x + between); } } private void FixedUpdate() { if (slowRotYes && Time.time <= slowBackRotEnd) { realBackRotSpeed += slowBackRotSlowDown; } transform.eulerAngles = new Vector3(0, -backRotY, 0); } } Nur muss ist nun zum einem in der Start Methode zwei Zeilen eintragen und noch einmal in der FixedUpdate Methode. Somit habe ich für eine Sache (welche nur kurz benötigt wird) an zwei Stellen Eintragungen, was der Lesbarkeit des Code nicht zugute kommt. Gefühlt würde ich sagen, dass ich mit einer Coroutine arbeiten muss. Aber irgendwie fehlt mit hier noch der Ansatz, wie ich sagen kann, dass der Wert der Variable innerhalb der Coroutine von A nach B wechselt und das in der vorgegebenen Zeitvorgabe. Wie geschrieben: es funktioniert, sollte aber sicher übersichtlicher möglich sein. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Jomnitech Geschrieben 31. März 2019 Melden Share Geschrieben 31. März 2019 habs jetzt nicht getestet, aber ich meine du kannst auch einfach math.lerp verwenden: public class myScript : MonoBehaviour { public float speed = 1f; float backRotSpeed = 0.3f; float realBackRotSpeed = 0.0f; private void FixedUpdate() { while (realBackRotSpeed < backRotSpeed) { realBackRotSpeed = Mathf.Lerp(realBackRotSpeed, backRotSpeed, speed * Time.deltaTime); } } } Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 31. März 2019 Melden Share Geschrieben 31. März 2019 Am 31.3.2019 um 17:58 schrieb KaBau: Gefühlt würde ich sagen, dass ich mit einer Coroutine arbeiten muss Sehr gute Idee! Coroutinen funktioneren so: Du hast eine Methode, die ganz normal abläuft mit dem kleinen Unterschied, dass du eine Anweisung zur Hand hast, mit der du eine beliebige Anzahl an Frames warten kannst. Du kannst damit also dasselbe machen wie mit Update, aber eben als zusammenhängender Ablauf. Wenn du z.B. diesen Code hast: private int frameCounter = 0; private void Update() { if (frameCounter < 60) { frameCounter++; if (frameCounter == 60) { Debug.Log("Ich habe 60 Frames abgewartet."); } } } dann hast du genau die Probleme, die du bereits angemerkt hast. Deine Zählervariable ist irgendwo abseits des Codes, der damit arbeitet, und darüber hinaus läuft da eine Update-Methode, die die meiste Zeit über gar nichts sinnvolles macht. So sieht das Äquivalent in einer Coroutine aus: private IEnumerator CountToSixtyFrames() { for (var frameCounter = 0; frameCounter < 60; frameCounter++) { yield return null; // warte einen Frame } Debug.Log("Ich habe 60 Frames abgewartet."); } Es gibt hier nur zwei Dinge zu bemerken: Die Methode hat als Rückgabetyp "IEnumerator". Mit "yield return null" wird die Methode unterbrochen und im nächsten Schritt des Update-Zyklus an dieser stelle fortgesetzt. Statt null kann man auch andere Dinge zurück geben, Z.B. ein WaitForSeconds-Objekt, dann wird nicht einen Frame lang gewartet, sondern so viele Frames, dass die angegebene Zeit in Sekunden verstrichen ist. Gestartet wird eine Coroutine so: StartCoroutine(CountToSixtyFrames()); In deinem Fall kannst du also etwa so etwas machen: private IEnumerator AnimateRotationSpeed(float targetValue, float duration) { var startValue = rotationSpeed; for (var time = 0f; time < duration; time += Time.deltaTime) { var progress = time / duration; rotationSpeed = Mathf.Lerp(startValue, targetValue, progress); yield return null; } rotationSpeed = targetValue; } und dann in Start aufrufen: private void Start() { StartCoroutine(AnimateRotationSpeed(targetRotationSpeed, 1f)); } Kann man natürlich auch noch etwas modularer machen, statt fest rotationSpeed zu beeinflussen einfach einen ref-Parameter oder ein Callback anbieten und schon hat man sein eigenes Tweening-System Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
KaBau Geschrieben 1. April 2019 Autor Melden Share Geschrieben 1. April 2019 Hallo @Sascha und @Jomnitech, danke für die Tipps. Ich denke mir, dass der Tipp von Jomnitech auch funktioniert, nur schmirt mit in letzter Zeit bei einer "while" Schleife immer mein Unity (Version 2018.3.0f2) ab. Das hatte ich schon an anderer Stelle gehabt. Sascha: beim Aufrufen der Coroutine meinte Visual Studio, dass eine Klammer am Ende fehlt: StartCoroutine(AnimateRotationSpeed(backRotSpeed, slowRotDuration)); Die habe ich nachgetragen. Zudem hat Visual Studio bei "time += Time.deltaTime" gemeckert, weil der Typ "float" nicht in "int" konvertiert werden kann. Somit habe ich diese Zeile wie folgt abgeändert: for (var time = 0.0f; time < duration; time += Time.deltaTime) Der Unterschied ist im vordersten "time = 0.0f". Klappt wunderbar. Ich spare mir einige Variablen am Anfang (ist somit übersichtlicher), und die "Zeitschleife" ist aus der FixedUpdate Methode raus. Sollte der Code noch erweitert werden bleibt das somit übersichtlicher. Danke. So, und mit "Mathf.Lerp" muss ich mich nun dringend doch einmal auseinander setzen. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 2. April 2019 Melden Share Geschrieben 2. April 2019 Jau, danke für die Hinweise. Hatte das so runtergetippt und es jetzt ausgebessert 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.