ShV Geschrieben 22. November 2020 Melden Share Geschrieben 22. November 2020 Ich möchte, dass mein Objekt, sobald es keinen Kontakt mehr zum Boden hat, 2 Sekunden auf der y- Achse steigt. Hat jemand eine Idee, wie ich das machen kann? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
chrische5 Geschrieben 22. November 2020 Melden Share Geschrieben 22. November 2020 Hallo ja, du musst ab dem Zeitpunkt,Wonder Kontakt verloren geht, einen Timer starten. Ohne dein Aufbau zu kennen, würde ich oncollionsexit abfangen und dann zu einer Variable immer deltaTime addieren. In jedem Frame fragst du ab, die Variable größer als zwei ist. christoph Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
devandart Geschrieben 23. November 2020 Melden Share Geschrieben 23. November 2020 Die Erkennung, ob das Objekt nicht mehr auf dem Boden ist, kannst Du mit OnCollisionExit machen, wie @chrische5 schon schreibt. Wenn dieses Ereignis eintritt, kannst Du in eine Variable die aktuelle Zeit schreiben und im Update dann prüfen ob die aktuelle Zeit - die gespeicherte Zeit 2 Sekunden ergibt bzw. darunter liegt. Solange eben das Objekt bewegen. Beispiel Pseudo Code private float groundExitTime; private const float moveUpDuration = 2f; void OnCollisionExit(Collision collisionInfo) { groundExitTime = Time.timeSinceLevelLoad; } void Update() { if(Time.timeSinceLevelLoad - groundExitTime <= moveUpDuration) { //move up } } Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Cxyda83 Geschrieben 23. November 2020 Melden Share Geschrieben 23. November 2020 mit dem OnCollisionExit stimme ich zu allerdings kommt das auf deinen Anwendungsfall an, da gibt es sicher noch andere / leichtere lösungen für von der Lösung die @devandart vorgeschlagen hat würde ich jedoch abraten ... bei diesem Code wird das objekt sobald das level geladen ist erstmal direkt 2 sekunden steigen wenn nicht gleich OnCollisionExit aufgerufen wird. Besser ist es eine bool variable z.b. isGrounded = true und eine timerVariable zu haben. Wenn OnCollisionEnter eintritt setzt du die timerVariable auf 2f und isGrounded auf false. In der Update() funktion machste dann private bool isGrounded = true; private float moveUpTimer; private const float moveUpDuration = 2f; void OnCollisionEnter(Collision collisionInfo) { // Wenn collision mit ground isGrounded = true; } void OnCollisionExit(Collision collisionInfo) { // wenn keine collision mehr mit ground moveUpTimer = moveUpDuration; isGrounded = false; } public void Update() { if(isGrounded) return; moveUpTimer -= Time.deltaTime; if(moveUpTimer > 0f) { // move up } } gruß Cxyda Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 23. November 2020 Melden Share Geschrieben 23. November 2020 Hatte dieses Mal initial keine Lust, den "das geht auch soundso"-Typen rauszuholen, aber da jetzt hier lauter Varianten aufgezählt werden, mach ich's halt doch Man kann in Update hoch- oder runterzählen oder auch Timestamps vergleichen. Man kann aber auch eine Coroutine benutzen: private void OnCollisionExit() { StopAllCoroutines(); StartCoroutine(MoveUp(2f)); } private IEnumerator MoveUp(float duration) { for (var time = 0f; time < duration; time += Time.deltaTime) { transform.Translate(Vector3.up * speed * Time.deltaTime); yield return null; } } Man kann auch so etwas machen: private bool moving; private void OnCollisionExit() { StartCoroutine(MoveUp(2f)); } private IEnumerator MoveUp(float duration) { moving = true; yield return new WaitForSeconds(duration); moving = false; } private void Update() { if (moving) { transform.Translate(Vector3.up * speed * Time.deltaTime); } } Oder man nutzt Invoke für diese Variante. Invoke ist aber doof, lieber meinen Invoker benutzen : private bool moving; private void OnCollisionExit() { StopAllCoroutines(); moving = true; StartCoroutine(Invoker.Invoke(() => moving = false, 2f)); } private void Update() { if (moving) { transform.Translate(Vector3.up * speed * Time.deltaTime); } } Oder du nimmst die eine Tween-Bibliothek. Tweens sind genau für so etwas ("mach mal etwas X Sekunden lang") und mehr da. Auch dafür hab ich ne kleine Klasse, aber Tween-Frameworks gibt's lauter verschiedene, kannst du dir ja mal ansehen. Mit meiner Klasse würde das so aussehen: private void OnCollisionExit() { // Hier wird distance statt speed benutzt, das eine kann man aber durch das andere ausrechenen var targetPosition = transform.position + Vector3.up * distance; StartCoroutine(CorouTweens.Interpolate(transform.position, // von wo targetPosition, // nach wo duration, // wie lange CorouTweens.linear, // welche Kurve (z.B. erst schneller, dann langsamer, hier aber gleichbleibend) pos => transform.position = pos)); } Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Cxyda83 Geschrieben 23. November 2020 Melden Share Geschrieben 23. November 2020 😉 @Sascha also nur um nach X Zeit eine funktion zu callen brauchst keine Coroutine da reicht auch ein einfaches Invoke(nameOf(MyStopFunction), 2f); ... und in deiner ersten coroutine fehlt ein "yield return" 🤓 aber ja... du bekommst den Keks für die ausführlichste Antwort ! 👍 Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 23. November 2020 Melden Share Geschrieben 23. November 2020 vor 5 Stunden schrieb Cxyda83: ... und in deiner ersten coroutine fehlt ein "yield return" 🤓 Na, das stimmt. Hab's korrigiert., danke! vor 5 Stunden schrieb Cxyda83: Invoke(nameOf(MyStopFunction), 2f); Oha.... auf die Idee bin ich nicht gekommen. Empfehle immer, Invoke wegen des String-Parameters nicht zu benutzen, aber so ist's ja wieder sicher. Die Doku sagt allerdings selbst Zitat For better performance and maintability, use Coroutines instead. Ich nehme an, dass da Reflection passiert ist nicht so prickelnd. Hab's mal durch den Benchmark laufen lassen: MonoBehaviour.Invoke braucht bei mir 230ns beim Aufruf, die Coroutine mit dem Invoker nur 2µs. Mit "maintability" (maintainability...) meinen die vermutlich genau das String-Problem, das man mit nameof ja umgeht. Reicht also in der Tat, aber ich werde weiterhin den Invoker empfehlen Oh, und Nachtrag: Beim Invoker muss man keine Methode definieren, sondern kann einfach einen Lambda-Ausdruck reinknallen. Finde ich jetzt auch nicht unwichtig 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.