Jump to content
Unity Insider Forum

Mehrmal springen beim halten des Buttons


Thanny08
 Share

Recommended Posts

Hii,

 

 

Ich suxche nach einer Möglichkeit, das wenn der Spieler den Button hält das der Player dann solange springt bis er den Button wieder los lässt. habe dafür weder auf Youtube noch im Internet eine Lösung gefunden... 

 

Mein Jump Script sieht bisher so aus:

 

 

<>public class PlayerJump : MonoBehaviour
{
    public float jumpForce = 5f;
    private Rigidbody2D myRB;
    private bool canJump;
    // Start is called before the first frame update
    private Animator anim;
    
    void Start()
    {
        anim = GetComponent<Animator>();
        myRB = GetComponent<Rigidbody2D>();
    }
    //Jump Funktiom

    public void Jump ()
     {
        //Darf Spieler springen?
        if (canJump)
        {
            canJump = false;
            myRB.velocity = new Vector2(0f, jumpForce);

        }

    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        canJump = true;
    }

}
 

(Ich habe es nicht hinbekommen Code Blöcke hinzuzufügen...)

Link to comment
Share on other sites

vor 5 Stunden schrieb Thanny08:

 

Also ich habe das Problem gelöst und habe nun noch eine andere kleinere Frage:

Und zwar springt der ASpieler jetzt oft hintereinander wie er soll, aber da das ziemlich unrealistisch aussieht weil keine Zeit dazwischen ist, wollte ich das der Player noch 0,1 Sekunden wartet bis er wieder springt. Das habe ich nicht hinbekommen...

Hier mein Script:

<>

void Update()
    {
        if (buttonHeldDown)
        {
           
                while (canJump)
                {
                    if (canJump)
                    {
                        canJump = false;
                        myRB.velocity = new Vector2(0f, jumpForce);
                        //Hier soll noch 0,1 Sekunden gewrtet werden<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                }
            }
                


            
        } 
    }

(Ich bekomme die Codeblöcke immer noch nicht hin...)

weiß jmd was ich dort für eine Methode brauche?

Link to comment
Share on other sites

Also für deine Codeblöcke musst du nur auf das "SYMBOL" klicken, welches neben dem Smylie ist. Das sieth so aus: "<>".
Dann offnet sich ein extra Fenster, wo du dann unten rechts highliting einstellen kannst. Wähle da C aus. Jetzt einfach deinen Code ins Fenster rein bringen und wenn du fertig bist Fenster schließen.

Wegen deinem Warten:

Bau dir eine Coroutine, in die du mit StartCoroutine(Warte());  reinspringst. Warte ist der Name der Coroutine.

In der CoRoutine kannst du dann eine gewünschte Zeit warten und dein CanJimp wieder auf true setzen.

IEnumerator Warte(){
  yield return new WaitForSeconds(0.1f);
  canJump=true;

Solltest du aber vor ablauf der 0.1 Sekunden mit etwas kollidieren, würde vorher schon canJump auf true gesetzt werden. Das ist der Coroutine aber egal, die arbeitet das trotzdem ab.
Was ich damit sagen will: Wenn du etwas berührst bevor die CR fertig gewartet hat, wird canJump true. Hältst du den Button immer noch, wird canJump sofoert wieder false und die CR nochmals gestartet. Das heisst also, die läuft jetzt 2Mal und die wird jedes Mal, wenn sie fertig ist das canJump wieder auf true setzen !!!

Es gibt aber die Möglichkeit alle Coroutinen zu stoppen  StopAllCoroutines();
Und das solltest du tun, bevor du die Coroutine neu startest, denn wie gesagt, die Dinger lassen sich so oft starten wie du willst und mit jedem Start gibt es auch einen Ablauf.

Link to comment
Share on other sites

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class PlayerJump : MonoBehaviour
{
    public float jumpForce = 5f;
    private Rigidbody2D myRB;
    private bool canJump;
    // Start is called before the first frame update
    bool buttonHeldDown;

    //Jump Funktiom
    public void HoldButton()
    {
        buttonHeldDown = true;
    }
    public void ReleaseButton()
    {
        buttonHeldDown = false;

    }
    private void OnCollisionEnter2D(Collision2D collision)
    {
        canJump = true;
    }
    void Update()
    {
        if (buttonHeldDown)
        {

            while (canJump)
            {
                if (canJump)
                {
                    canJump = false;
                    myRB.velocity = new Vector2(0f, jumpForce);
                    StartCoroutine(Warte());
                    IEnumerator Warte()
                    {
                        yield return new WaitForSeconds(0.1f);
                        canJump = true;
                    }
                    StopAllCoroutines(); ;



                }
            }









        }
    }
}
Am 5.9.2022 um 11:12 schrieb Thanny08:

 

Ich habe jz alles so gemacht aber es funktioniert gar nichts mehr. Das heißt der Spieler springt gra nicht... Ich glaube in Unity habe ich alles richtig gemacht. Kann es am Script liegen? Es sind keinerlei Fehlermeldungen vorhanden...

 

Hier mein Script:

 

Link to comment
Share on other sites

Also wenn du zuerst einen neu Coroutine startest, aber gleich danach alle stoppst, wird nichts passieren.
Reihenfolge ist schon wichtig.

Eine Coroutine hat außerdem außerhalb einer Methode oder Funktion zu sein. Das ist ein separates Dingen. OnCollisionEnter hast du ja auch nicht in die Update rein gemacht.

Schreib sie mal unter die Update .

 

Link to comment
Share on other sites

Also jetzt klappt es auf jedenfall mit dem springen. HAbe bemerkt das ich einfach nur den RB vergessen habe.... ;) Oh man das ich wegen sowas solange festgehangen bin!! na ja. 

Der Spieler springt aber immer noch ohne Pause zwischen den Sprüngen. Ich habe Die StopAllCoroutines(); Am Anfang der Update Methode hingemacht und auch alles andere ausprobiert... da klappt iwi nicht... Weißt du woran das liegen könnte?

 

Hier jetzt nochmal das überarbeitete Script:

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class PlayerJump : MonoBehaviour
{
    public float jumpForce = 10f;
    private Rigidbody2D playerRigidbody;
    private bool canJump;
    // Start is called before the first frame update
    bool buttonHeldDown;

    private void Start()
    {
        playerRigidbody = GetComponent<Rigidbody2D>();
    }
    //Jump Funktiom
    public void HoldButton()
    {
        buttonHeldDown = true;

    }
    public void ReleaseButton()
    {
        buttonHeldDown = false;

    }
     void OnCollisionEnter2D(Collision2D collision)
    {
        canJump = true;
    }
    void Update()
    {
        StopAllCoroutines();


        if (buttonHeldDown)
        {

            while (canJump)
            {
                if (canJump)
                {
                    canJump = false;
                    playerRigidbody.velocity = new Vector2(0f, jumpForce);
                    StartCoroutine(Warte());
                    IEnumerator Warte()
                    {
                        yield return new WaitForSecondsRealtime(0.1f);
                        canJump = true;
                    }





                }
            }
        }
   }
   




}

Vielen Dank für deine Hilfe!!!!!

Link to comment
Share on other sites

Ne... ich glaube du bist noch nicht so weit für eine CoRoutine.
Die ist ja immer noch in der Update drinne!

Mach das mal anders und frage einfach die Zeit ab.
Schau dir dieses Script mal an. Unten erkläre ich dir alles dazu.

private float timer; // diese Variable musst du genau so einfügen
public float wartezeit=0.1f; // diese auch, denn das ist die Wartezeit, die du im Inspector einstellen kannst

private void Start()
{
  playerRigidbody = GetComponent<Rigidbody2D>();
  timer = wartezeit; // hier übergibst du dem Timer die gewünschte Wartezeit
}
public void ReleaseButton()
{
  buttonHeldDown=false;
  timer = wartezeit; // immer wenn du den Button losgelassen hast, wird der Timer wieder zurück gesetzt
}
void OnCollisionEnter2D(Collision2D collision)
{
  canJump = true;
  timer = wartezeit; // immer wenn du etwas berührt hast, wird der Timer wieder zurück gesetzt
}
    
private void Update()
{
  if (buttonHeldDown)
  {
    if (canJump)  // ist true sobald du irgendwas berührst oder die zeit abgelaufen ist
    {
      canJump = false; // jetzt erstmal auf false setzen
      playerRigidbody.velocity = new Vector2(0f, jumpForce); // sprung!
    }
    timer-=Time.deltaTime; // die deltaTime vom Timer abziehen
    if(timer<=0) // ist die Zeit abgelaufen?
    {
      timer += wartezeit; //wenn sie es ist, dann dem Timer die eingestellte Wartezeit drauf tun
      canJump=true; //  und jetzt darf auch wieder gesprungen werden
    }
  }
} 

Zur Erklärung:

Du brauchst eine neue Variable die sich timer nennt und auch eine Variable, die du zum Testen verändern kannst, die wartezeit.

Startest du das Spiel, bekommt der timer die wartezeit übergeben.
Diese timer Variable wird dann als Zeit zwischen den Sprüngen genutzt.

In der Void ReleaseButton() wird der timer dann wieder sauber auf die wartezeit gesetzt. Also immer nur dann wenn du den Button losgelassen hast, damit bei nächsten Mal drücken wieder mit der sauberen Wartezeit gestartet werden kann.

Bei einer Collision wird der timer auch zurück gestellt. Denn, die Collision stellt ja sofort canJump auf true, was auch zum sofortigen Sprung führt, wenn du die Taste noch hältst. Damit nicht sofort wieder gehüpft wird, weil vielleicht auch gleich der timer abgelaufen ist, machen wir da wenigstens eine saubere Wartezeit rein. Das ist etwas unglücklich, da bei dir jede Collision, egal was es ist, zum setzen von canJump führt.

Da die Update so oft ausgeführt wird, wie deine Framerate gerade ist (mit VSync ist das in der Regel 60 mal pro Sekunde), wird es nie genau 0.1 Sekunden dauern, bis canJump wieder true wird. Es wird minimal länger sein. Deswegen setze ich den Timer innerhalb der Update nicht auf 0.1 sondern addiere 0.1 dazu.
Das führt dazu, dass die neu gesetzte Zeit minimal kürzer sein kann ( weil der Timer evtl. auf -0.014 war, und nach der Addition dann auf 0.086 steht).
Im Durchschnitt ist es aber dann alle 0.1 Sekunden, die du springen kannst.
Würdest du den Timer immer fest auf die Wartezeit setzen, dann würde auch immer etwas mehr Zeit vergehen und das würde sich summieren. Dann kannst du nicht mehr 10 Mal pro Sekunde, sondern evtl. nur noch 8 Mal pro Sekunde springen. Verstehst du das?

Ich nutze die Time.deltaTime für das Reduzieren des Timers deswegen, weil das die Zeit ist, die zwischen 2 Frames vergangen ist. Das macht die Zeitmessung unabhängig von der Framerate. Bei Rechnern die vielleich nur 30 Fps schaffen, ist die deltaTime doppelt so groß als bei Rechnern mit 60 Fps. (1 / Framerate).

Ich habe deine Update auch etwas geändert, wie du ja siehst. Denn deine while Schleife ist komplett unnötig gewesen, da die Bedingung für das while gleich beim allerersten Durchgang aufgehoben wurde.

Mir ist klar, dass du noch ganz frisch bist und somit verschiedene Dinge einbaust, die du noch nicht verstehst. Deswegen habe ich dir dieses Script hier angefügt und versucht alles zu erklären.
Du kannst jetzt dein Script so anpassen und es sollte gehen. Da ich das aber einfach aus dem Kopf dahin geschrieben habe, könnten da kleine Fehler drin sein.
Deswegen solltest du nicht einfach kopieren und einfügen, sondern selber neuen Dinge einfügen und die alten löschen.

Ich hoffe du verstehst, was da passiert und kannst es in dein Projekt einbauen.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...