Jump to content
Unity Insider Forum

Layer Einfluss auf die Geschwindigkeit


STU

Recommended Posts

Hi zusammen,

ich versuche mir ein 2D Spiel zu programmieren. Nun habe ich das Problem, wenn ich den Layer von meinen Spieler ändere, dann verändert sich auch meine run Geschwindigkeit. Es wirk so als ob man deutlich gebremst wird. Auch wenn ein Collider auf Tigger steht und ich durchrenne verändert sich meine Spielergewindigkeit deutlich.

Woran kann das liegen?

Danke

Viele Grüße

STU

Link zu diesem Kommentar
Auf anderen Seiten teilen

Habe ich auch so gedacht, wenn ich haber den Layer ändere, ist auf einmal meine Geschindigkeit doppelt so hoch, ohne das ich etwas anpassen. Wenn aber wie beschrieben ein anderer Collider kommt, geht diese wieder deutlich runter, solange ich in dem Collider stecke.

grafik.png.ca38fb90b1394b57f3889f556b4b49e9.png

grafik.png.4c8d51335e7dfaa8a9ef274953cd487b.png

grafik.png.5a9890a0daf0e6ba0d6f1873c2a909c9.png

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Der CharacterController2D ist... der von Brackeys? Denn das Ding ist das offenbar, das diese Probleme verursacht. Kann es sein, dass die Layer bei dem Ding nicht richtig eingestellt sind? Dass die Figur z.B. denkt, durchgehend "grounded" oder eben nicht "grounded" zu sein, weil sie z.B. mit sich selbst oder eben dem Trigger kollidiert.

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 2 weeks later...

Von wem der CharacterController2D ist weiß ich leider nicht. Als ich angefangen habe, wurde dieser empfohlen und ich habe ihn nie geändert 😅 

Ich muss mich anscheinend jetzt mehr mit dem Ding befassen. Du denkst es liegt am grounded? Ich werde mich morgen mal daran setzen und das Skript genauer unter die Lupe nehmen

Hatte nur bis jetzt andere Baustellen 😉

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 3 weeks later...

ich möchte eine Leiter rauf klettern können. Dieses Phänomen tritt bei mir aber leider an verschiedenen Stellen im Spiel auf, wenn ich eine ...Stay2D im Skript habe.

 

private void OnTriggerStay2D(Collider2D other)
    {

        if (other.gameObject.tag == "Player" && Input.GetKey(KeyCode.UpArrow))
        {
            other.GetComponent<Rigidbody2D>().velocity = new Vector2(0, speedUpDown);
        }

        else if (other.gameObject.tag == "Player" && Input.GetKey(KeyCode.DownArrow))
        {
            other.GetComponent<Rigidbody2D>().velocity = new Vector2(0, -speedUpDown);
        }

        else
        {
            other.GetComponent<Rigidbody2D>().velocity = new Vector2(0, 0.5f);
        }
    } 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

der Fehler liegt in der letzten Zeile. Dadurch soll die Schwerkraft ausgesetzt werden, damit ich nicht von der Leiter falle wenn ich die Pfeiltaste nicht mehr drücke. Wie kann ich dass aber so gestalten, dass die Schwerkraft nicht mehr wirkt und ich trotzdem keinen Einfluss habe wenn ich nur durch laufe?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ein ganz allgemeiner Tipp: Achte genau auf das, was du denkst/sagst. Du schreibst nämlich

vor 11 Stunden schrieb STU:

Dadurch soll die Schwerkraft ausgesetzt werden

aber dein Script tut das nicht. Dein Script arbeitet gegen die Schwerkraft an. Interessanterweise machen das viele Leute, dass sie das, was sie haben wollen, präzise und schlau formulieren, dann aber etwas anderes implementieren. "Schwerkraft aussetzen" ist eine sehr gute Idee, der aktuelle Code dagegen sehr anfällig für Probleme.

So würde "Schwerkraft aussetzen" aussehen:

private void OnTriggerEnter2D(Collider2D other)
{
  if (other.gameObject.CompareTag("Player"))
  {
    other.GetComponent<Rigidbody2D>().gravityScale = 0f;
  }
}

private void OnTriggerExit2D(Collider2D other)
{
  if (other.gameObject.CompareTag("Player"))
  {
    other.GetComponent<Rigidbody2D>().gravityScale = 1f;
  }
}

Das ist nur die Basisimplementation. Hier gibt es Probleme, wenn

  • dein Rigidbody normalerweise eine andere gravityScale als 1 hat. Dann muss sich das Volumen das merken, oder besser: Du packst das Leiter-/Kletterscript auf den Spieler.
  • der Spieler zwei Leitervolumen gleichzeitig berührt. Beim Verlassen des ersten würde dann die Gravitation zurückgesetzt werden, obwohl die zweite Leiter noch berührt wird. Auch hier wäre es sinnvoll, das Script auf den Player zu packen.

Wenn du mich fragst, ist es sowieso irgendwie intuitiver, wenn das Kletterverhalten auch auf dem Kletterer definiert ist, und nicht auf der Leiter. Eine Faustregel ist: Objekte sollten sich so viel wie möglich um ihren eigenen Kram kümmern und so wenig wie möglich um den Kram anderer Objekte.

Schreiben wir das also direkt mal um.

[RequireComponent(typeof(Rigidbody2D))]
public class LadderClimber : MonoBehaviour
{
  private Rigidbody2D rigidbody2d;
  private float defaultGravityScale;
  private int touchedLadderCount = 0;
  public float speedUpDown = 5f;
  
  
  private void Awake()
  {
    rigidbody2d = GetComponent<Rigidbody2D>();
    defaultGravityScale = rigidbody2d.graivityScale;
  }
  
  private void OnTriggerEnter2D(Collider2D other)
  {
    if (other.GetComponent<Ladder>())
    {
      touchedLadderCount++;
      rigidbody2d.gravityScale = 0f;
    }
  }

  private void OnTriggerExit2D(Collider2D other)
  {
    if (other.GetComponent<Ladder>())
    {
      touchedLadderCount--;
      if (touchedLadderCount == 0)
      {
        rigidbody2d.gravityScale = defaultGravityScale;
      }
    }
  }
  
  private void FixedUpdate()
  {
    if (touchedLadderCount > 0)
    {
      if (Input.GetKey(KeyCode.UpArrow))
      {
      	rigidbody2d.velocity = new Vector2(0, speedUpDown);
      }
      else if (Input.GetKey(KeyCode.DownArrow))
      {
        rigidbody2d.velocity = new Vector2(0, -speedUpDown);
      }
      else
      {
        rigidbody2d.velocity = Vector2.zero;
      }
    }
  }
}

Sieht auf den ersten Blick evtl. nach viel aus, ist aber recht simpel:

  1. Mit OnTriggerEnter und OnTriggerExit wird gezählt, in wie vielen Leitern gleichzeitig wir uns befinden. Zwar ist nur "0 oder nicht 0" interessant, aber das Problem mit dem Deaktivieren, wenn man von zwei Leitern nur noch eine berührt, ist damit weg. Jetzt musst du beim Leveldesign nicht mehr furchtbar aufpassen, dass die Positionen deiner Leitern irgendein Script zerschießen.
  2. FixedUpdate macht hier (in Kombination mit der if-Abfrage) quasi dasselbe wie OnTriggerStay, aber eben nur einmal pro Physik-Update. Selbst, wenn wir uns gerade in mehreren Leitern gleichzeitig befinden.
  3. Dadurch, dass dieses Script auf demselben GameObject sitzt, auf dem auch der Rigidbody ist, den wir beeinflussen wollen, brauchen wir nur ein GetComponent in Awake. Das spart eine Menge hässlicher GetComponents.
  4. Der gravityScale, den dein Rigidbody im Editor eingestellt gekriegt hat, wird hier in Awake gemerkt und dann wiederverwendet, sobald keine Leitern mehr berührt werden.
  5. Statt Tags benutze ich GetComponent, weil Tags kacke sind. Du machst also ein leeres Script namens "Ladder" und packst das auf deine Leitern. Naja, du hast ja schon eins. Einfach leer machen :)
Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...