Jump to content
Unity Insider Forum

Jump - schnelleres hochspringen


MoinPeter

Recommended Posts

Hallo, ich möchte für einen 2D-Platformer-Jump mit variabler Jumphöhe das Aufsteigen/Hochspringen des Players schneller machen als das Runterfallen. Allerdings bekomme ich es nicht hin, da man mit der velocity.y den player nur weiter aufsteigen lassen kann, nicht schneller. Kann mir jemand weiterhelfen? Hier der Code:

void Start(){
        gravity = -(2*maxJumpHeight)/Mathf.Pow(timeToJumpApex,2);
        maxJumpVelocity = Mathf.Abs(gravity) * timeToJumpApex;
        minJumpVelocity = Mathf.Sqrt (2 * Mathf.Abs (gravity) * minJumpHeight);
    }
 
void Update(){
        // JUMP
        if(Input.GetKeyDown(KeyCode.Space) && controller.collisions.below){
            velocity.y = maxJumpVelocity;
        }
 
        if(Input.GetKeyUp(KeyCode.Space)){
            if(velocity.y > minJumpVelocity){
                velocity.y = minJumpVelocity;
            }
}

Viele Grüße

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich verstehe das Problem nicht so ganz, aber vielleicht machst du es dir auch zu schwer. Der Rigidbody2D von Unity besitzt bereits eine Schwerkraft die permanent wirkt (siehe Gravity Scale bspw. auf 3 setzen). Daher würde ich keinen Controller verwenden der eine Schwerkraft einführt/simuliert, es sei denn man möchte gänzlich ohne Rigidbody2D auskommen. 

Ein Sprung des 2D-Charakters kann nun einfach ausgelöst werden über eine Kraft auf den Rigidbody2D in Y-Richtung:

[SerializeField] private float m_JumpForce = 400f; // Amount of force added when the player jumps.

...
...
...

m_Rigidbody2D.AddForce(new Vector2(0f, m_JumpForce));

Ansonsten poste mal deinen gesamten Controller, weil der Teilausschnitt hilft nicht das Problem zu verstehen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hier mal ein ganz einfacher 2D Controller. Du brauchst nur ein Spielersprite mit 2D Collider und ein Bodensprite mit 2D Collider.
Der Spieler braucht noch ein Child-Transform mit dem Namen "GroundCheck". Dieses gibt an wo die Füße des Spielers sind.

Ich habe alles überflüssige entfernt, so daß man nur noch eine Klasse braucht. Auch keinen "CharacterController2D" mehr.

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

public class ControllerTest2D : MonoBehaviour
{
    private float gravity;
    private float maxJumpVelocity;
    private float minJumpVelocity;
    public float maxJumpHeight = 4;
    public float minJumpHeight = 1;
    public float timeToJumpApex = .4f;
    float accelerationTimeAirborne = .2f;
    float accelerationTimeGrounded = .1f;

    private Transform m_GroundCheck;    // A position marking where to check if the player is grounded.
    const float k_GroundedRadius = .1f; // Radius of the overlap circle to determine if grounded
    private bool m_Grounded;            // Whether or not the player is grounded.
    [SerializeField]
    private LayerMask m_WhatIsGround = 1; // A mask determining what is ground to the character
    private bool m_FacingRight = true;  // For determining which way the player is currently facing.

    private Vector3 velocity;
    private  Vector3 movement;
    private Vector3 input;

    private void Awake()
    {
        // Setting up references.
        m_GroundCheck = transform.Find("GroundCheck");
    }

    void Start()
    {
        gravity = -(2 * maxJumpHeight) / Mathf.Pow(timeToJumpApex, 2);
        maxJumpVelocity = Mathf.Abs(gravity) * timeToJumpApex;
        minJumpVelocity = Mathf.Sqrt(2 * Mathf.Abs(gravity) * minJumpHeight);
    }

    private void FixedUpdate()
    {
        movement = new Vector3(0, 0, 0);
        m_Grounded = false;

        movement.x = input.x;

        // The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
        // This can be done using layers instead but Sample Assets will not overwrite your project settings.
        Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
        for (int i = 0; i < colliders.Length; i++)
        {
            if (colliders[i].gameObject != gameObject)
                m_Grounded = true;
        }

        if (!m_Grounded)
        {
            movement.y = gravity * Time.deltaTime;
            if (velocity.y > 0) velocity.y = velocity.y + gravity * Time.deltaTime;
            else velocity.y = 0;
        }

        movement.y = movement.y + velocity.y;

        //controller.Move(velocity * Time.deltaTime, input);
        this.transform.Translate(movement * Time.deltaTime);
    }

    void Update()
    {
        input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")); 

        // JUMP
        if (Input.GetKeyDown(KeyCode.Space) && m_Grounded)
        {
            velocity.y = maxJumpVelocity;
        }

        if (Input.GetKeyUp(KeyCode.Space))
        {
            if (velocity.y > minJumpVelocity)
            {
                velocity.y = minJumpVelocity;
            }
        }

        // If the input is moving the player right and the player is facing left...
        if (input.x > 0 && !m_FacingRight)
        {
            // ... flip the player.
            Flip();
        }
        // Otherwise if the input is moving the player left and the player is facing right...
        else if (input.x < 0 && m_FacingRight)
        {
            // ... flip the player.
            Flip();
        }
    }

    private void Flip()
    {
        // Switch the way the player is labelled as facing.
        m_FacingRight = !m_FacingRight;

        // Multiply the player's x local scale by -1.
        Vector3 theScale = transform.localScale;
        theScale.x *= -1;
        transform.localScale = theScale;
    }
}


 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Nachdem ich den selbst zusammengeflickten Controller betrachtet habe, musst du bei deinem alten Controller vermutlich einfach nur "timeToJumpApex" erhöhen oder senken.
Es bestimmt die Zeit, wie schnell der Charakter seine Sprunghöhe erreichen soll (musst du im Inspektor einstellen). Da ich nicht genau weiß, wie der CharacterController2D Gravitaton auswertet funktioniert bei meinem Controller timeToJumpApex zwar "irgendwie", aber ich bin mir nicht sicher, ob dies bei deinem Controller auch so ist.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ok. Ich habe meinen Controller noch einmal erweitert, nun funktioniert auch "timeToJumpApex" wie angedacht.
"timeToJumpApex" bestimmt dabei, wie lange er bis zum Scheitelpunkt des Sprunges braucht, mit "staticGravity" stellst du die Gravitation ein, die wirken soll, wenn der Spieler zurück auf den Boden fällt. Damit kannst du nun sowohl einstellen, wie schnell der Spieler hochspringt und auch wie schnell er wieder auf den Boden fällt.

Ich habe noch einen fließenden Übergang zwischen dynamischer Gravitation und statischer Gravitation eingebaut. Damit beschleunigt der Spieler nach dem Scheitelpunkt des Sprunges langsam auf die maximale statische Gravitation (physikalisch nicht korrekt, da die Gravitation ja eigentlich eine Beschleunigung ist). Damit wird quasi ein Luftwiderstand simuliert, wobei wieder ein physikalisch korrekter Eindruck entsteht. Als Übergang habe ich 1/3 der Zeit von "timeToJumpApex" genommen. Man kann es aber über "timeToFullStaticGravity" noch einmal nachregeln.

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

public class ControllerTest2D : MonoBehaviour
{

    public float staticGravity = 300f;
    public float timeToFullStaticGravity = 0.3f; // This time is dependent from timeToJumpApex
    public float maxJumpHeight = 8;
    public float minJumpHeight = 1;
    public float timeToJumpApex = 1.0f;

    private float dynamicGravity;
    private float maxJumpVelocity;
    private float minJumpVelocity;

    private Transform m_GroundCheck;    // A position marking where to check if the player is grounded.
    const float k_GroundedRadius = .1f; // Radius of the overlap circle to determine if grounded
    private bool m_Grounded;            // Whether or not the player is grounded.
    [SerializeField]
    private LayerMask m_WhatIsGround = 1; // A mask determining what is ground to the character
    private bool m_FacingRight = true;  // For determining which way the player is currently facing.

    private Vector3 velocity;
    private  Vector3 movement;
    private Vector3 input;
    private float turningPointDampingTime;
    private float turningPointTime;

    private void Awake()
    {
        // Setting up references.
        m_GroundCheck = transform.Find("GroundCheck");
    }

    void Start()
    {
        dynamicGravity = -(2 * maxJumpHeight) / Mathf.Pow(timeToJumpApex, 2);
        maxJumpVelocity = Mathf.Abs(dynamicGravity) * timeToJumpApex;
        minJumpVelocity = Mathf.Sqrt(2 * Mathf.Abs(dynamicGravity) * minJumpHeight);
        turningPointDampingTime = 1.0f / (timeToJumpApex * timeToFullStaticGravity);
        //print(dynamicGravity);
        //print(maxJumpVelocity);
    }

    
    private void FixedUpdate()
    {
        m_Grounded = false;

        // The player is grounded if a circlecast to the groundcheck position hits anything designated as ground
        // This can be done using layers instead but Sample Assets will not overwrite your project settings.
        Collider2D[] colliders = Physics2D.OverlapCircleAll(m_GroundCheck.position, k_GroundedRadius, m_WhatIsGround);
        for (int i = 0; i < colliders.Length; i++)
        {
            if (colliders[i].gameObject != gameObject)
                m_Grounded = true;
        }

        MovementCycle();
    }

    void MovementCycle()
    {
        movement = new Vector3(0, 0, 0);
        movement.x = input.x*2.0f;

        if (!m_Grounded)
        {
            if (velocity.y > 0)
            {
                movement.y = dynamicGravity * Time.deltaTime;
                velocity.y = velocity.y + dynamicGravity * Time.deltaTime;
                turningPointTime = Time.time;
            }
            else
            {
                movement.y = Mathf.Lerp(dynamicGravity, -staticGravity, (Time.time - turningPointTime) * turningPointDampingTime) * Time.deltaTime;
                velocity.y = 0;
            }
        }

        movement.y = movement.y + velocity.y;
    }

    void Update()
    {
        input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")); 

        // JUMP
        if (Input.GetKeyDown(KeyCode.Space) && m_Grounded)
        {
            velocity.y = maxJumpVelocity;
        }

        if (Input.GetKeyUp(KeyCode.Space))
        {
            if (velocity.y > minJumpVelocity)
            {
                velocity.y = minJumpVelocity;
            }
        }

        // If the input is moving the player right and the player is facing left...
        if (input.x > 0 && !m_FacingRight)
        {
            // ... flip the player.
            Flip();
        }
        // Otherwise if the input is moving the player left and the player is facing right...
        else if (input.x < 0 && m_FacingRight)
        {
            // ... flip the player.
            Flip();
        }

        // Move Player
        this.transform.Translate(movement * Time.deltaTime);
    }

    private void Flip()
    {
        // Switch the way the player is labelled as facing.
        m_FacingRight = !m_FacingRight;

        // Multiply the player's x local scale by -1.
        Vector3 theScale = transform.localScale;
        theScale.x *= -1;
        transform.localScale = theScale;
    }

}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...