Jump to content
Unity Insider Forum
Sign in to follow this  
Lightstorm

Rigidbody rutscht auf beweglichen Plattformen

Recommended Posts

Der Player Charakter hat ein Rigidbody2D (Dynamic). Damit hüpfe ich auf eine Plattform die über rigidbody2D.MovePosition() bewegt wird. Dabei rutscht der Player Charakter auf dem Plattform weil diese sich bewegt. Wie kann ich das verhindern?

Mit Physik Material und Friction Wert 1 entsteht das Problem dass der Player Charakter auch an den Seiten des Plattforms hängen bleibt statt runter zu rutschen. So gehts also nicht.

Share this post


Link to post
Share on other sites

Nur Brainstorming:

Eine Idee wäre, den Rigidbody vom Charakter bei Kollision auf Kinematic zu setzen und der Plattform als Child unterzuordnen, solange bis ein Player (oder anderer) Input kommt. Eine andere, den Rigidbody über einen Joint mit der Plattform zu "verknoten". Auch bis ein Input oder sonstiges dieses unterbricht.

Mal schauen, was noch für schöne Vorschläge kommen oder was Du herausfindest. :)

Share this post


Link to post
Share on other sites

Danke für den Vorschlag. Ich probiere gerade mehrere Möglichkeiten und irgendwie gefällt mir keines wirklich gut.

Damit der Player Charakter nicht einfach beim bloßen Kontakt an allen Seiten des Plattform hängen bleibt, muss man dafür sorgen dass das binden nur passiert wenn der Charakter auf der Oberseite der Plattform steht. Dafür musste ich der Plattform ein child GameObject hinzufügen und einen Trigger Collider. Das binden passiert nur wenn der Charakter diesen Trigger auf der Oberseite der Plattform berührt.

Die Berührung der Oberseite erfasse ich mit OnTriggerStay2D im Player Charakter GameObject.

private void OnTriggerStay2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "MovedPlatform")
        {
            if (!playerFixed)
            {
                transform.parent = collision.gameObject.transform;
                rigidbody2D.isKinematic = true;
                playerFixed = true;
            }
        }
    }

Ein anderes Problem ist dass der Spieler frei werden muss sobald man sich horizontal bewegt oder springt. Das mache ich so:

if (Input.GetAxis("Horizontal") != 0.0f || Input.GetButtonDown("Jump"))
        {
            transform.parent = null;
            rigidbody2D.isKinematic = false;
            playerFixed = false;
        }

plattform.thumb.jpg.2de1bb7ed16fbd98c380d360a7b35bc2.jpg

Funktioniert. Aber habe irgendwie das Gefühl dass das besser geht.

Ich habe es auch mit einem Fixed Joint 2D probiert. Funktioniert ja im Prinzip genau so. Ich weiß nicht warum, aber beim entbinden vom Joint hat der Player Charakter immer eine kleine komische Bewegung in die Plattform hinein vollführt und sich dann normal weiter bewegt. Deswegen habe ich es mit dem Joint gelassen.

Dann habe ich es noch so probiert:

private void FixedUpdate()
    {
        Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, 0.02f, whatIsGround);
        for (int i = 0; i < colliders.Length; i++)
        {
            if (colliders[i].gameObject.tag == "MovedPlatform" && !move)
            {
                transform.parent.gameObject.transform.parent = colliders[i].gameObject.transform;
                rigidbody2D.isKinematic = true;
            }
        }
    }

An meinem Player Charakter ist ein GroundCheck GameObject als child vorhanden, mit dem erfasst wird wann der Charakter auf dem Boden steht. Ich dachte mir ich kann mit dem selben Prinzip erfassen wann der Charakter auf einem Boden mit dem tag "MovedPlatform" steht um es dann zu binden.

Funktionierte auch nicht perfekt. Bei Sprüngen aus größerer Höhe auf die Plattform kam der Player Charakter immer wieder mal einige Pixel innerhalb der Platform zum stehen statt wie üblich direkt auf dem Collisions Collider.

 

Was ich gerne will ist eine Lösung die in meine modulare Architektur passt.

Die andere Herausforderung ist wie man eine saubere Entbindung hinkriegt. Solange man mit einem Sprung den Trigger Bereich auf der Plattform nicht verlässt wird der Charakter sofort wieder gebunden bevor es noch den Trigger Bereich verlassen kann. Denn OnTriggerStay2D wird ja ständig ausgeführt.

Share this post


Link to post
Share on other sites
vor 11 Stunden schrieb Lightstorm:

Die andere Herausforderung ist wie man eine saubere Entbindung hinkriegt. Solange man mit einem Sprung den Trigger Bereich auf der Plattform nicht verlässt wird der Charakter sofort wieder gebunden bevor es noch den Trigger Bereich verlassen kann. Denn OnTriggerStay2D wird ja ständig ausgeführt.

Zu dem Punkt: Genau deswegen solltest Du lieber OnTriggerEnter2D nutzen, statt Stay. Weil dieses Event nur beim Eintritt ausgelöst wird. OnTriggerExit2D dann, wenn Du den Trigger wieder verlässt.

  • Like 1

Share this post


Link to post
Share on other sites
vor 7 Stunden schrieb devandart:

Zu dem Punkt: Genau deswegen solltest Du lieber OnTriggerEnter2D nutzen, statt Stay. Weil dieses Event nur beim Eintritt ausgelöst wird. OnTriggerExit2D dann, wenn Du den Trigger wieder verlässt.

Dann habe ich ein anderes Problem: Wenn der gebundene Charakter auf der Plattform sich etwas horizontal bewegt, muss ich durch diesen Input den Charakter wieder loslösen. Damit bewegt sich der Charakter aber nur innerhalb des Trigger Colliders, es wird kein erneutes OnTriggerEnter2D zum erneuten binden ausgelöst sobald der Charakter wieder zum stehen kommt.

Nach einer kurzen horizontalen Bewegung würde der Charakter also nicht mehr fest auf der Plattform stehen.

Edit: Langsam bin ich etwas genervt :( So was triviales kostet jetzt so viel Zeit, mir vergeht die Lust.

 

Share this post


Link to post
Share on other sites

Habe nun eine andere einfache Möglichkeit gefunden:

private void OnTriggerStay2D(Collider2D collision)
    {
        if (collision.gameObject.tag == platformTagName)
        {
            autoMove = collision.GetComponentInParent<AutoMovement2D>();
            charakterController2D.relativeVelocity = autoMove.Direction;

        }
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.gameObject.tag == platformTagName)
        {
            charakterController2D.relativeVelocity = Vector3.zero;
        }
    }

relativeVelocity wird auf die Bewegung des Player Charakter dazu addiert. Der Charakter bewegt sich damit mit der selben Geschwindigkeit in die selbe Richtung wie die Plattform solange es keinen Input gibt. Wenn die Plattform verlassen wird, wird relativeVelocity einfach auf Null gesetzt, dadurch gelten wieder nur die Bewegungen durch den Spieler Input.

Mit dieser Vorgehensweise ist es nicht notwendig das Ridigbody2D auf Kinematic zu setzen und das GameObject zum Child des Platform GameObject zu machen.

Einen Haken hat das ganze: Wenn die Platform die Richtung ändert rutscht das Charakter Rigidbody2D ein ganz bisschen in die vorherige Bewegungsrichtung. Wie durch Fliehkraft aufgrund der Richtungsänderung der Platform. Wie wenn die Bahn bremst und man nach vorne gedrückt wird. Das sieht sogar schön aus und macht es ein bisschen realistischer. Wenn man das aber nicht haben möchte weiß ich gerade nicht wie man das verhindern kann.

Share this post


Link to post
Share on other sites

Oh man ich habe gerade nach längerer Zeit erst etwas bemerkt. Man findet im Internet folgenden bzw. ähnlichen Code. Und ich wunderte mich wieso es bei mir nicht funktionierte.

//HoldOnPlatform can be your name of the script
public class HoldOnPlatform : MonoBehaviour {
 
    void OnTriggerEnter(Collider col)
    {
        col.transform.parent = gameObject.transform;
    }
 
    void OnTriggerExit(Collider col)
    {
        col.transform.parent = null;
    }
 
}

Damit funktioniert es perfekt. Kein rutschen auf der Plattform, der Charakter kann perfekt stehen, sich bewegen und problemlos jederzeit weg springen. Allerdings funktioniert es nur wenn die Plattform über ihre transform Eigenschaft bewegt wird. Bewegt man es über rigidibody2D dann funktioniert es nicht.

Und das habe ich gerade zufällig so spät bemerkt :D

Das ist so bitter... aber besser spät als nie.

  • Like 1

Share this post


Link to post
Share on other sites
//HoldOnPlatform can be your name of the script
public class HoldOnPlatform : MonoBehaviour {
 
    void OnTriggerEnter(Collider col)
    {
        col.transform.parent = gameObject.transform;
    }
 
    void OnTriggerExit(Collider col)
    {
        col.transform.parent = null;
    }
 
}

Funktioniert bei mir vorne und hinten nicht. Ehrlich gesagt weiß ich mit diesem Script auch nicht wie ich Spielfigur und Plattform "verbinde". Haben deine Plattformen Rigbodys oder nicht? Meine nicht. Meine bewegen sich auch ohne.

Wäre über einen korrekten Code dankbar, da ich eigentlich bis auf ein paar youtube videos null Ahnung von der Materie habe. 

Share this post


Link to post
Share on other sites

Du wirst nicht drum herum kommen zu lernen. Falls du denkst, dass dir die Leute irgendwelche Codes zur verfügung stellen, die dann auch bei dir funktionieren, hast du dich getäuscht.
Da niemand weiß, wie dein Spiel aufgebaut ist, ist der Code auch nicht für dein Spiel angepasst. Anpassen musst du selber!

Kleiner Tipp, weil du ja nicht weißt, wie das Script die Figur mit der Plattform verbindet:
Parent = Elternteil, verständlich ausgedrückt, Vater!
Sobald deine Figur die Plattform, die natürlich dieses Script haben muss,  triggert, wird sie ein Kindobjekt der Plattform. Beim Verlassen des Triggers wird dieses Vater-Kind Verhältnis wieder aufgehoben.
Ein Kindobjekt wird vom Vaterobjekt mit genommen, wenn sich das Vaterobjekt bewegt. Das funktioniert aber nur solange, bis andere Kräfte oder Bewegungen dagegen arbeiten. Das ist auch gut so, denn du willst ja nicht an der Plattform festkleben, sondern dich darauf bewegen können.

So, jetzt musst du dich schlau machen, wie Collider funktionieren, was ein Triggerevent ist und wie es funktioniert, was die Transformkomponente ist, und was das GameObjekt im Code zu suchen hat.
Ohne dieses Wissen kommst du nicht weiter.

Share this post


Link to post
Share on other sites

@Gadakar86

Wie @malzbie schon richtig schreibt, der Code funktioniert. Wenn du es richtig bei dir verwendest sollte es gehen. Du musst einen Collider für deine bewegliche Plattform erstellen und es als Trigger einstellen. Alles was  im Spiel in diesen Collider rein geht wird durch die Funktion OnTriggerEnter2D zum kindsobjekt der Plattform.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×