Wie man den Spieler bewegt und gleichzeitig zulässt, dass Kräfte ihn beeinflussen


7

Im Moment bewege ich den Spieler so:

rb.velocity = Vector2.right * input.x;

Und ich treffe ihn mit einer Kraft, während er von einer Entität beschädigt wird:

rb.AddForce(Vector2.right * force);

Es funktioniert gut, bis ich versuche, mich zu bewegen, während ich von einer Entität beschädigt werde. Da meine Geschwindigkeit = input.x ist, während ich mich bewege, kann ich keine Kräfte darauf auswirken. Ich habe versucht, die Geschwindigkeit zusammenzufassen:

rb.velocity+=Vector2.right * input.x;

Aber dann muss ich die Geschwindigkeit klemmen und wenn ich sie klemme, wird auch meine Kraft, die auf den Spieler wirkt, geklemmt.

Wie kann ich dieses Problem lösen?

Antworten:


5

Du bist auf dem richtigen Weg! Dies ist etwas, für das normalerweise der Controller verantwortlich ist. Wenn Sie in einen Plattformer springen, verwenden Sie eine "isGrounded" -Variable, um das Verhalten der Steuerelemente in der Luft zu ändern, oder? Sie benötigen einen ähnlichen Status für isKnockback. In den meisten Spielen, in denen ein Spieler zurückgestoßen wird, wird ihm für eine bestimmte Zeit die Kontrolle entzogen. Das oder du behandelst es wie in der Luft, wo anstatt die Geschwindigkeit einzustellen, nur eine Kraft angewendet wird, um die Geschwindigkeit anzupassen. Wie Sie dieses Steuerelement implementieren möchten, ist eine Entwurfsentscheidung, aber es gibt keine echte physikbasierte Antwort. Die wahre physikbasierte Antwort besteht darin, die Fortbewegung in den Beinen des Charakters zu implementieren, und das ist für die Spielphysik nicht wirklich nützlich. Eine andere Lösung könnte sein, anstatt eine Kraft anzuwenden, ist es, mit Rückstoß auf einer Geschwindigkeitsstufe wie Ihrer Bewegung zu arbeiten. Wenden Sie eine Geschwindigkeit an und reduzieren Sie sie bei jedem festen Update um einen gewissen Betrag, um einen Rückstoß-ähnlichen Effekt zu simulieren. Dies ist eine weitere in der Branche übliche Lösung.

Bearbeiten: Nur um die anderen Antworten hier zu würdigen, erwähnen sie, dass Ihre Bewegung Beschleunigung / Kraft basiert. Dies ist auch eine Option, abhängig von der Art der gewünschten Bewegung. Dieser Ansatz ist weitaus intuitiver, bietet Ihnen jedoch ein geringeres Maß an Kontrolle. Es hängt alles davon ab, was Sie wollen, und es ist wichtig, dass Sie diese Entscheidung frühzeitig treffen (oder experimentieren, wenn Sie sich nicht sicher sind), da dies Auswirkungen auf Entscheidungen in der Zukunft hat. Wenn Sie sehen möchten, wie verrückt Plattform-Code werden kann, hat Matt den Code für Madeline von Celeste veröffentlicht. Sie verwenden eine andere Engine (eigentlich Framework), aber Sie können sich ein Bild davon machen, wie viele Variablen und Pseudophysik verwendet wurden, um dieses Gefühl zu erreichen. https://github.com/NoelFB/Celeste/blob/master/Source/Player/Player.cs


Vielen Dank, es wird durch Aktivieren von true isKnockback ausgeführt, wenn Kraft angewendet wird, und durch Überprüfen von false, wenn der Spieler das nächste Mal mit dem Boden kollidiert. Es funktioniert sehr gut
Basea Basilia

Froh das zu hören. Im Allgemeinen haben Sie keine Angst davor, Physik in Ihren Spielen zu fälschen. Viele Engines haben diese fantastische realistische Physik, aber in vielen Spielszenarien fälschen die Leute das meiste davon :)
gjh33

9

Ich habe vor ein paar Tagen ein kleines Demo-Spiel erstellt, das verschiedene Möglichkeiten zeigt, einen Spielercharakter zu bewegen. Es könnte Ihnen helfen, besser zu verstehen, welche Art der Bewegung für Ihr bestimmtes Spiel die richtige ist.

Im Allgemeinen sollten Sie verwenden, rigidbody.AddForcewann immer dies möglich ist. Es kümmert sich automatisch um die Verwaltung mehrerer überlappender Kräfte und stellt sicher, dass die Impulsübertragung bei Kollisionen physikalisch korrekt ist.

Wenn Sie nicht möchten, dass Ihr Charakter unbegrenzt beschleunigen kann, erhöhen Sie den Wert für "Linear Drag" des starren Körpers. Die Widerstandskraft nimmt quadratisch mit der Geschwindigkeit zu, sodass sie irgendwann die Beschleunigung aufhebt und die Höchstgeschwindigkeit effektiv begrenzt. Ein größerer Widerstandswert führt zu kürzeren Beschleunigungs- und Verzögerungszeiten, wodurch sich die Steuerelemente "enger" anfühlen, aber auch die Auswirkung von Kollisionen stark einschränken.

Wenn Sie möchten, dass der Charakter strenge Kontrollen hat, aber auch von Kollisionen betroffen ist, können Sie damit so umgehen, wie es die Antwort von gjh33 vorschlägt. Haben Sie zwei verschiedene Zustände in Ihrem Player-Controller. Ein regulärer Zustand, in dem der starre Körper einen hohen Luftwiderstand hat und der Spieler die volle Kontrollkraft hat, und ein Zustand, in dem Sie den Luftwiderstand und die Kontrollkraft vorübergehend reduzieren, um den Charakter in einem vorübergehenden Zustand unkontrollierter Hilflosigkeit herumfliegen zu lassen .

Ich freue mich darauf, Ihr Spiel zu spielen.


4

Ich selbst löse dieses Problem gerne, indem ich mir alle Spielerbewegungen als beschleunigungsbasiert vorstelle.

Ich wähle eine Zielgeschwindigkeit unter Verwendung einer beliebigen komplizierten Steuerlogik und fordere den Spieler-Avatar auf, auf dieses Ziel zu beschleunigen, wobei ich die von mir festgelegten maximalen Beschleunigungsraten einhalte.

Abhängig vom Zustand des Avatars (am Boden, auf Eis, in der Luft, in einem Rückstoßzustand) kann ich diese Beschleunigungsraten ändern, damit die Steuereingabe einen schärferen oder weniger ausgeprägten Einfluss hat.

Rigidbody2D body;

void AccelerateTowards(Vector2 targetVelocity, float maxAccel, float maxDecel) {
    // Compute desired velocity change.
    var velocity = body.velocity;
    var deltaV = targetVelocity - velocity;

    // Convert our velocity change to a desired acceleration,
    // aiming to complete the change in a single time step.

    // (For best consistency, call this in FixedUpdate,
    //  and deltaTime will automatically give fixedDeltaTime)
    var accel = deltaV / Time.deltaTime;

    // Choose an acceleration limit depending on whether we're
    // accelerating further in a similar direction, or braking.
    var limit = Dot(deltaV, velocity) > 0f ? maxAccel : maxDecel;

    // Enforce our acceleration limit, so we never exceed it.    
    var force = body.mass * Vector2.ClampMagnitude(accel, limit);

    // Apply the computed force to our body.
    body.AddForce(force, ForceMode2D.Force);
}

Wenn ich die Beschleunigungs- und Verzögerungsraten wie diese trenne, kann ich eine schärfere Bremskraft erzeugen, die dazu beiträgt, dass sich die Bedienelemente beim Anhalten oder Ändern der Richtung straff und reaktionsschnell anfühlen, während eine gleichmäßige Beschleunigung beibehalten wird, um auf die Geschwindigkeit zu kommen. Außerdem können Sie das Bremsen besonders dann bestrafen, wenn Sie sich auf Eis befinden oder zurückgestoßen werden.

Wir können ein Steuerzustandsparameterobjekt erstellen, um die Höchstgeschwindigkeit, Beschleunigungs- und Verzögerungsraten für unsere Luft-, Boden-, Eis-, Rückstoßzustände usw. zu halten, und dies verwenden, um unser Steuerungshandling sehr flexibel anzupassen:

// Choose our current speed / acceleration parameters based on our state.
var controlState = GetCurrentControlState();

// Compute desired velocity.
var velocity = GetDesiredVelocityFromInput(controlState.maxSpeed);

// Try our best to reach that velocity, with our current parameters.
AccelerateTowards(
     velocity,
     controlState.maxAccel,
     controlState.maxDecel
);

Gibt deltatime automatisch fixedDeltaTime in der fixedUpdate-Schleife aus? Das ist echt cool! Ich weiß, dass ich früher darum herum programmieren musste. Weißt du, wann sie das hinzugefügt haben?
gjh33

Ich habe es mir angesehen, du hast recht. Das ist sehr nützlich. Ich erinnere mich nicht daran, dass es die Wiederverwendung von Funktionen in verschiedenen Update-Schleifen viel einfacher macht, als ich anfing, in Unity zu arbeiten.
gjh33
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.