Jump to content
Unity Insider Forum

Springen


Kojote

Recommended Posts

Grüße!

Ich grübel schon den gesamten Nachmittag wie ich Springen realisieren könnte. Geplant ist das der Charakter/ das Objekt eine bestimmte Entfernung springen soll, dies entweder auf der X- oder Z- Achse. In einem besondern fall soll auch die Y-Koordinate verändert werden. Ich hab nun schon einiges gelesen und alle machen es über einen Rigidbody:

gameObject.GetComponent<Rigidbody>().velocity = new Vector3(0, 2, 2);

Problem wäre nun bei diesem Script Code, dass das Objekt schräg nach oben geht und nie wieder landet. Könnt ihr mir da weiter helfen?

Kojote

Link zu diesem Kommentar
Auf anderen Seiten teilen

Eigentlich recht einfach da die velocity die Geschwindigkeit ist die das Objekt hat, du willst aber nur einen Kraftimpuls auf das Objekt ausführen. Das würde ich so machen:

 

gameObject.GetComponent<Rigidbody>().AddForce(x, y, z, ForceMode.Impulse);

Dann einfach für x,y,z die entsprechenden Variablen einfügen oder feste Werte eingeben.

Nochmal zum lachlesen Rigidbody.AddForce

Link zu diesem Kommentar
Auf anderen Seiten teilen

Erst mal Danke für die Antwort, jedoch mit Add Force bewegt er sich ja nur in eine bestimmte Richtung, die man vorgibt. Ich wollte gern das er eine bestimmte Distanz in einer Prabel springt. So in etwa:

Springe mit Geschwindigkeit auf Position X=0, Y=2, Z= 3 in einer Parabel.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Eine Parabel entsteht über das Zusammenspiel einer nach vorn oben gerichteten Kraft + der Schwerkraft. Die nach vorn oben gerichtete Kraft würdest du beispielsweise über AddForce((transform.forward + transform.up)*jumpforce)  hinzufügen und die Schwerkraft würde über die "eingeschaltete" Schwerkraft des RB wirken.

Normalerweise steuert man den RB eines Spieler über Richtungstasten und fügt bei einem Jump dann einfach eine nach oben gerichtete Kraft hinzu: AddForce(transform.up*jumpforce)
Die Bewegung nach vorn für den Sprung wird dann meistens über die Richtungstasten hinzuaddiert. Die Schwerkraft des RBs sorgt dann dafür, daß der Spieler auch wieder landet.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 2 Stunden schrieb Wattsefakk:

Eigentlich recht einfach da die velocity die Geschwindigkeit ist die das Objekt hat, du willst aber nur einen Kraftimpuls auf das Objekt ausführen.

 

vor 19 Minuten schrieb Zer0Cool:

Normalerweise steuert man den RB eines Spieler über Richtungstasten und fügt bei einem Jump dann einfach eine nach oben gerichtete Kraft hinzu: AddForce(transform.up*jumpforce)

Ehrlich gesagt würde ich da jederzeit dringend von abraten. Ein Spieler erwartet, einen Sprung, der einmal geschafft wurde, erneut zu schaffen und wird es nicht begrüßen, wenn aufgrund derartiger Implementationen die Sprunghöhe nicht konstant ist.

Das mit der Parabel ist so oder so jedenfalls kein Selbstgänger. Du wirst eine Startgeschwindigkeit und konstante Kraft, die auf die Figur wirkt, und die bilden die Flugbahn. Entweder, du berechnest da eine Menge um vom Einen auf das Andere zu schließen, oder du implementierst den Sprung als Animation, die nicht von der Physik berechnet wird, so wie z.B. bei Alien Swarm.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 15 Minuten schrieb Sascha:

Ehrlich gesagt würde ich da jederzeit dringend von abraten. Ein Spieler erwartet, einen Sprung, der einmal geschafft wurde, erneut zu schaffen und wird es nicht begrüßen, wenn aufgrund derartiger Implementationen die Sprunghöhe nicht konstant ist.

 

Wieso, die Kraft die du hinzufügst ist jedesmal die Gleiche und daher ist auch die Sprunghöhe die Gleiche. Springen kann der Spieler ja erst, wenn er auf dem Boden ist und da ein Spieler normalerweise nicht vom Boden abfedert, kann sich die Sprunghöhe auch nicht aufsummieren. Zudem springt man in der Natur auch nicht immer gleich weit und hoch, das wäre unrealistisch, von daher würde ich hier sogar noch extra eine zufällige Toleranzsprungkraft hinzufügen (aber das ist Geschmackssache).

Link zu diesem Kommentar
Auf anderen Seiten teilen

Gerade eben schrieb Zer0Cool:

Wieso, die Kraft die du hinzufügst ist jedesmal die Gleiche und daher ist auch die Sprunghöhe die Gleiche

Das gilt nur, wenn die Ausgangsgeschwindigkeit immer die gleiche ist. Davon darf man aber nicht ausgehen.

vor 1 Minute schrieb Zer0Cool:

Springen kann der Spieler ja erst, wenn er auf dem Boden ist und da ein Spieler normalerweise nicht vom Boden abfedert, kann sich die Sprunghöhe auch nicht aufsummieren.

Die vertikale Geschwindigkeit ist halt nicht gleich null. Beim CharacterController, wo die vertikale Geschwindigkeit vom selbstgeschriebenen Script abhängt, ist dein Ansatz tödlich, und auch beim Rigidbody kann es damit Probleme geben. Allein schon bei Steigungen.

vor 1 Minute schrieb Zer0Cool:

Zudem springt man in der Natur auch nicht immer gleich weit und hoch, das wäre unrealistisch, von daher würde ich hier sogar noch extra eine zufällige Toleranzsprungkraft hinzufügen.

Das ändert nichts daran, dass der Spieler das in seinem Spiel nicht möchte :)

Die zufällige Sprunghöhe darfst du gerne Mal implementieren und eine kleine Studie dazu durchführen - da werden dir die Testpersonen aber was erzählen :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich vermute wir verstehen uns hier irgendwie falsch. Die Sprunghöhe hat mit der Ausgangsgeschwindigkeit in XZ nichts zu tun, die Sprunghöhe wird nur über den Kraftvektor in Y-Richtung definiert.
Wenn der Spieler auf dem Boden steht ist die vertikale Geschwindigkeit = 0 und ich spreche hier nur über einen Charaktercontroller mit einem RB. Und bei einem Charaktercontroller mit einem RB einen Sprung über AddForce nach oben zu implementieren ist nicht meine Idee und auch nicht neu.
Und zum letzten Punkt, das finde ich wie gesagt "Geschmackssache", ich fände eine gewisse Toleranz bei der Sprunghöhe realistisch (+ - 10%) und eine 100% konstante Sprunghöhe eher langweilig ...

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 8 Minuten schrieb Zer0Cool:

Wenn der Spieler auf dem Boden steht ist die vertikale Geschwindigkeit = 0

Nope :)

Rigodbodys und funktionierend gescriptete CharacterController kollidieren in jedem (fixed) Frame mit dem Boden. Das geht nicht, ohne sich auf den Boden zuzubewegen.

vor 8 Minuten schrieb Zer0Cool:

Und bei einem Charaktercontroller mit einem RB einen Sprung über AddForce nach oben zu implementieren ist nicht meine Idee und auch nicht neu.

Das eine große Menge an Leuten das macht, heißt nicht, dass es richtig ist. Gibt auch viele, die in jedem Frame GetComponent aufrufen. Zeig mir mal ein Spiel, das deine Sprunghöhe vom Zufall abhängig macht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Sollte sie aber, sonst stände der Spieler nicht auf dem Boden, sondern würde abheben....
Die Toleranz einzubauen war ja nur ein Beispiel (und so fände ich es gut), hatte ja mit dem Ausgangsproblem nix zu tun. Und das andere Spiele die Sprunghöhe exakt gleich halten heißt auch nicht automatisch das es gut ist (es ist nur am simpelsten umzusetzen). zudem man die Sprunghöhe auch noch über andere Sachen variabel gestalten kann, z.b. wie lange eine Taste gedrückt wird und ähnliches. Ich glaube man kann eine Sprungmechanik beliebig komplex gestalten, da denke ich alles ist besser als 0815 und es so zu machen wie alle anderen Spiele.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 3 Minuten schrieb Zer0Cool:

Sollte sie aber, sonst stände der Spieler nicht auf dem Boden, sondern würde abheben....

Die Rede ist hier nicht von y > 0, sondern y < 0.

Variable Sprunghöhe ist selbstverständlich durchaus okay, aber zufällige ist es nicht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Die sollte "eigentlich" gelöscht werden, sobald der RB auf den Bodencollider "aufschlägt" (es sei denn wir haben einen federnden Boden und oder einen federnden RB [physikalisches Material], was aber bei einem "normalen" Spieler-RB nicht sein sollte). Ich habe es aber ehrlich gesagt noch nie kontrolliert, ich hoffe aber nicht das Unity die Aufprallbeschleunigung gegen einen anderen Collider "speichert", sobald eine Collision abgeschlossen ist.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 1 Minute schrieb Zer0Cool:

Die sollte "eigentlich" gelöscht werden, sobald der RB auf den Bodencollider "aufschlägt".

Wird sie. Und anschließend addiert die Schwerkraft wieder etwas drauf. In der Regel negativ, versteht sich. Wie ich bereits sagte:

vor 16 Minuten schrieb Sascha:

Rigodbodys und funktionierend gescriptete CharacterController kollidieren in jedem (fixed) Frame mit dem Boden. Das geht nicht, ohne sich auf den Boden zuzubewegen.

Wir hatten schon oft Threads, in denen Leute merkten, dass ihr CharacterController nicht durchgehend isGrounded war, obwohl er es hätte sein müssen. Das Problem war jedes Mal, dass sie in ihrem Script y = 0 hielten, und die Lösung entsprechend, bei isGrounded y auf einen konstanten, negativen Wert zu setzen. Rigidbodys machen das genauso, und das kannst du gerne nachprüfen:

using UnityEngine;

public class RBVTest : MonoBehaviour
{
    void FixedUpdate()
    {
        var rb = GetComponent<Rigidbody>(); // Do not do at home, kids
        var r = GetComponent<Renderer>();

        r.material.color = rb.velocity.y < 0 ? Color.green : Color.blue;

        if(rb.IsSleeping())
        {
            rb.WakeUp();
        }
    }
}

Der letzte Teil ist interessant: Rigidbody.veloctiy ist tatächlich (0,0,0), wenn der Rigidbody schläft. Daher muss er zum Testen aufgeweckt werden. Bei einer ständig laufenden Spielfigur ist das natürlich weniger nötig.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor einer Stunde schrieb Zer0Cool:

Normalerweise steuert man den RB eines Spieler über Richtungstasten und fügt bei einem Jump dann einfach eine nach oben gerichtete Kraft hinzu: AddForce(transform.up*jumpforce)
Die Bewegung nach vorn für den Sprung wird dann meistens über die Richtungstasten hinzuaddiert. Die Schwerkraft des RBs sorgt dann dafür, daß der Spieler auch wieder landet.

Bei mir gibt es leider in dem Sinne keine Richtungstasten die abgefragt werden können. Der Charakter hat eine Standardgeschwindigkeit. Wäre ein Sprung aus dem Stand möglich bzw. wie müsste denn die Anweisung lauten?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja das stimmt,  aber die über die Gravitation addierte Kraft sollte aber immer gleich sein und damit haben wir wieder die gleiche Sprunghöhe bei hinzugefügter konstanter Kraft in Richtung Y.
Mhh das mit dem einschlafenden RB ist in der Tat gefährlich für solche Abfragen und ein  guter Hinweis :) .. ok dann ist der Sprung evtl. leicht höher wenn der RB vorher schläft, es kann aber auch sein das AddForce() den RB vorher aufweckt ... das ist schwer zu sagen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 1 Minute schrieb Zer0Cool:

ok dann ist der Sprung evtl. leicht höher wenn der RB vorher schläft, es kann aber auch sein das AddForce() den RB vorher aufweckt

Ob dann zwischen AddForce und Bewegungsupdate die Gravitation den Vektor wieder beeinflusst, ist die nächste Frage. Ich empfehle daher, sich einfach nicht darauf zu verlassen, was da passiert, und velocity.y = foo zu machen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wir waren auch ein bisschen am abschweifen :)

Also... du hast einen Rigidbody und möchtest ihn springen lassen. Ich habe gerade erst dein ursprüngliches Problem gesehen:

vor 4 Stunden schrieb Kojote:

Problem wäre nun bei diesem Script Code, dass das Objekt schräg nach oben geht und nie wieder landet. Könnt ihr mir da weiter helfen?

Eigentlich wirkt jeden fixed Frame eine konstante Schwerkraft auf jeden Rigidbody, welche standardmäßig erdnorm hat, also (0,-9.81,0) entspricht. Einstellen kann man das in "Edit/Project Settings/Physics". Beim Rigidbody muss das Häckchen bei "Use Gravity" gesetzt sein.

Wenn das alles der Fall ist, dann liegt es daran, dass du deine Zeile aus dem Ersten Post immer wieder, also in jedem Frame ausführst. Dann setzt du die Geschwindigkeit auf einen konstanten Wert und entsprechend hast du eine konstante Bewegung. Du willst den Sprungimpuls nur ein einziges Mal pro Sprung ausführen und danach die Physikengine ihre Arbeit machen lassen:

private bool jump;

void Update()
{
  if(Input.GetKeyDown(KeyCode.Space))
  {
    jump = true;
  }
}

void FixedUpdate()
{
  if(jump)
  {
    rigidbody.velocity = new Vector3(0,2,2);
    jump = false;
  }
}

In diesem Code fehlt jetzt noch einiges. Zum Beispiel kann man auch dann springen, wenn man schon in der Luft ist, weil nicht überprüft wird, ob man auf dem Boden ist. Auch ist fraglich, ob der Vektor (0,2,2) auf lange Sicht das ist, was du willst. Aber damit sollte es schonmal laufen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich würde den Code von Sascha nehmen und es mal mit folgendem Vektor probieren. Macht eigentlich auch nicht viel anderes als AddForce, aber du kontrollierst den Beschleunigungsvektor direkt:

jumpVelocity = 2.0f;
rigidbody.velocity = new Vector3(rigidbody.velocity.x, jumpVelocity, rigidbody.velocity.z);


Hier ist auch eine vollständige Klasse, die macht einige spezielle Sachen mit der Gravitation, aber ich denke man kann sich einiges abschauen, unter anderem auch wie du feststellen kannst, ob der RB am Boden ist:
http://wiki.unity3d.com/index.php?title=RigidbodyFPSWalker

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 3 weeks later...

Also ich grübel jetzt schon wieder seit zwei Tagen an dem Problem und irgendwie wirds nicht, dabei ist es nicht viel Code und rein logisch müsste es funktionieren.

Die Schwerkraft ist eingestellt, 9.81. Es ist ein Ridgidbody vorhanden mit einer Masse von 100 und UseGravity ist aktiv.

Nutze ich nun dies:

jumpVelocity = 2.0f;
rigidbody.velocity = new Vector3(rigidbody.velocity.x, jumpVelocity, rigidbody.velocity.z);

Springt er gerade nach oben, nutze ich dies:

private bool jump;

void Update()
{
  if(Input.GetKeyDown(KeyCode.Space))
  {
    jump = true;
  }
}

void FixedUpdate()
{
  if(jump)
  {
    rigidbody.velocity = new Vector3(0,2,2);
    jump = false;
  }
}

Habe ich wieder mein Schrägenproblem

Eventuell liegt der Knackpunkt an einer anderen Stelle. Ich gebe die Geschwindigkeit fest vor. Es wird keine Eingabe registriert oder der gleichen. Der Charakter läuft allein und soll allein einen Sprung ausführen, ohne das der Spieler eine Taste betätigt.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du hast als Richtungsvektor für die Velocity ja auch einen Vektor genommen, der Schräg nach oben zeigt (0,2,2).

Wenn du willst, dass der Sprung gerade nach oben verläuft, so darfst du nur die y-Achse verändern. Also statt new Vector3(0,2,2) nimmst du einfach new Vector3(0,2,0).

Jetzt sollte dein Character gerade nach oben Springen, da die Velocity deines Spielers jetzt mit einer Stärke von 2 in Y-Richtung "gedrückt" wird, in dem moment wo du die Taste drückst. Wenn du jetzt natürlich deinen Character bewegst und in der Bewegung einen Sprung ausführen willst, so darfst du XZ beim Sprung nicht auf 0 setzen. Du müsstest also deine momentane Bewegung übernehmen. Also Sprich: new Vector3(rigidbody.velocity.x, 2, rigidbody.velocity.z)

Allerdings weiß ich nicht so recht wie du das meinst, dass der Spieler springen soll, ohne dass du eine Taste drückst.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Zitat

Allerdings weiß ich nicht so recht wie du das meinst, dass der Spieler springen soll, ohne dass du eine Taste drückst.

Mein Spiel ist in dem SInne kein Jump and Run, sondern eine Brettspiel. Ich lasse also mehrere Figuren, damit es für den Spieler interaktiv wird. Der Spieler gibt zwar vor, wie sich ein Charakter bewegen soll. Jedoch wird beim Start der Objektbewegung keine Taste mehr abgefragt. Ist das Objekt an einem bestimmten Punkt, hat es die Geschwindigkeit X und soll springen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Warum ist die Vorwärtsbewegung in Z = 0 wenn du:

jumpVelocity = 2.0f;
rigidbody.velocity = new Vector3(rigidbody.velocity.x, jumpVelocity, rigidbody.velocity.z);

verwendest. Ich bin davon ausgegangen, daß dein Charakter eine Vorwärtsbewegung in Z ausführt (Z<>0). Wenn du aber nun sagst, er springt nur nach oben, dann steht dein Charakter quasi auf der Stelle ..

und was meinst du mit "Schrägenproblem" ...? Wenn du Vektor3(0,,2,2) verwendest sollte der Charakter seitlich nach oben springen (nur für den Fall das der Vorwärtsvektor deines Charakters in Richtung Z zeigt!) und über die Schwerkraft wieder nach unten fallen (Parabel)

Ich sehe also 2 Probleme:
a.) Warum steht dein Charakter auf der Stelle kurz bevor er springen soll und
b.) In welche Richtung soll sich dein Charaker eigentlich bewegen (und auch ein ein Sprung beinhaltet meistens eine Vorwärtsbewegung) 

Wenn dein Charakter (aus dem Stand) in eine bestimmte Richtung springen soll, dann brauchst du also 2 Vektoren:

// Sprung aus dem Stand in eine bestimmte Richtung
jumpForce = 2.0f;
jumpVector = new Vector3(0, jumpForce, 0); // Vektor für die Sprunghöhe
jumpDirectionForce = 2.0f;
jumpDirection = transform.forward * jumpDirectionForce; // Vektor für die Sprungrichtung
rigidbody.velocity = jumpVector + jumpDirection;

Der obige Code nimmt als Sprungrichtung den Vorwärtsvektor deines Charakters (d.h. die Richtung in die dein Charakter blickt = die lokale blaue Achse des Transforms deines Charakters).

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...