Jump to content
Unity Insider Forum

Motorrad Physik/Movement (C#)


J3nsis

Recommended Posts

Hallo Ich bin gerad dabei ein Motorrad Movement zu erstellen und der Script dafür sieht bis jetzt so aus:

 




    void FixedUpdate()
    {
        movement();
    
    }

    void movement()
    {
        if (Input.GetKey("w"))
        {

            if (powerSpeed <= maxSpeed)
            {
                powerSpeed += beschleunigung;
            }

            
        }
        else
        {

            
            if (powerSpeed >= normalSpeed)
            {
                powerSpeed -= auslauf;
            }
            
                

            
        }

        if (Input.GetKey("s"))
        {
            if (powerSpeed >= miniSpeed)
            {
                powerSpeed -= bremse;
            }

        }
        else if (powerSpeed <= normalSpeed)
        {
            powerSpeed += beschleunigungnachminiSpeed;
           
        }

        currentSpeed = Mathf.Round(powerSpeed); 
        slider.value = Mathf.Round(powerSpeed);
        transform.Translate(Vector3.forward * powerSpeed * Time.deltaTime);

       

        if (Input.GetKey("a"))
        {
            transform.Rotate(Vector3.down * turnSpeed * Time.deltaTime);
        }

        if (Input.GetKey("d"))
        {
            transform.Rotate(Vector3.down * -turnSpeed * Time.deltaTime);
        }


        


Ich habe auch schon probiert das sich das Bike wie ein echtes in richtung Boden in der Kurve zu rotieren aber dann lag es die ganze Zeit nur auf der Seite.

Das Problem ist momentan das wenn man über eine Rampe fährt man sehr lange sehr weit nach oben bewegt wird und Ich weis nicht wie man das Fixen soll (liegt denke Ich mal am Auslauf bzw. das man in der Luft immernoch nach vorn gedrückt wird aber nach oben wegen Rampen Rotation). Außerdem wenn man schräg von einer Rampe springt wird man schräg Landen bzw. das Bike liegt dann auf dem Boden und man kann nichts mehr machen. 

Meine Rigidbody Settings:Unbenannte.PNG.198316b6104a622b0fbe46a6be0b4a4a.PNG

 

Gibt es irgendeine Methode eine bessere Bike Physik zu bekommen oder was muss ich ändern damit es so echt wie möglich ist? (Das Bike ist einfach nur ein Motorrad Modell was sich bewegt ohne Räder oder so)

 

MfG J3nsis

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich würde dafür 2 Wheelcollider verwenden. Es gibt dafür bereits etliche Skripte und Tutorials, wie man damit eine Fahrzeugphysik (mit 4 Rädern) implementiert:
https://docs.unity3d.com/Manual/WheelColliderTutorial.html

Ich würde hier "einfach" mal 2 Räder herausnehmen und diese Räder mittig unter dem Fahrzeugcollider zentrieren. Alles andere wäre dann ein Feintuning dieser 3 Komponenten (2 Wheel Collider und einen Box Collider für das Fahrzeuggestell).

Hier ist noch ein Projekt, welches vermutlich bereits ein Bike realisiert hat:
https://github.com/RandomationGames/Randomation-Vehicle-Physics

Link zu diesem Kommentar
Auf anderen Seiten teilen

Zitat

Ich würde dafür 2 Wheelcollider verwenden. Es gibt dafür bereits etliche Skripte und Tutorials, wie man damit eine Fahrzeugphysik (mit 4 Rädern) implementiert:
https://docs.unity3d.com/Manual/WheelColliderTutorial.html

Ich würde hier "einfach" mal 2 Räder herausnehmen und diese Räder mittig unter dem Fahrzeugcollider zentrieren. Alles andere wäre dann ein Feintuning dieser 3 Komponenten (2 Wheel Collider und einen Box Collid

Danke aber leider kann man bei diesem Script nicht nur zwei Räder benutzen. Wenn man versucht die 4 Räder ziemlich dicht an einander zu machen geht es auch nicht weil das Bike dann immer in Kurven umkippt. Und Ich verstehe diesen Code nicht genug um ihn für 2 Räder abzuändern. 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich habe mich mal dran gesetzt und einen einfachen Bikecontroller aus dem Unity Tutorial gebastelt. Wichtig war hierbei einen Masseschwerpunkt hinzuzufügen, sonst kippt das Bike gleich beim 1. Lenkvorgang um. Nach dem Lenken neigt sich das Bike nun in eine Richtung und pendelt nach weiterem Geradeausfahren noch einige Zeit hin und her. Ich denke hier müsste man den Masseschwerpunkt nach einer Lenkung leicht in die entgegengesetzte Richtung verschieben, damit das Bike zu pendeln aufhört und stabiler wird. Das habe ich allerdings erst einmal nicht gemacht, da ich nicht weiß, was für ein Verhalten du möchtest. Vielleicht gibt es auch noch andere Möglichkeiten das Pendeln in den Griff zu bekommen, mit dem Luftwiderstand des Rigidbody habe ich es nicht geschafft. Die andere Variante wäre - diese Idee kommt von Sascha und hat super funktioniert :) - die Rotation des Rigidbodies in Z zu beschränken, dann neigt sich das Fahrzeug durch die Physikengine überhaupt nicht, dies funktioniert mit dem unten stehenden Code ebenfalls:
 

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

/// <summary>
/// Simple Bike Controller by zer0f0rce (skype) for the Unity Insider Forum.
/// "Center of Mass" should be a child gameObject with a centered position below the vehicle on the ground.
/// To completely prevent the swinging of the vehicle add a constraint "freeze rotation Z" to the rigidbody.
/// Missing Feature: Move the center of mass to the opposite direction of the steering process.
/// Relating to:
/// https://docs.unity3d.com/Manual/WheelColliderTutorial.html
/// </summary>
[System.Serializable]
    public class AxleInfoSingle
    {
        public WheelCollider wheel;
        public bool motor;
        public bool steering;
    }

    public class SimpleBikeController : MonoBehaviour
    {
        public List<AxleInfoSingle> axleInfos;
        public float maxMotorTorque;
        public float maxSteeringAngle;
        public Transform centerOfMass;
        public float steerDamping = 5.0f;
        private Rigidbody bikeRigidbody;

    void Start()
        {
          bikeRigidbody = GetComponent<Rigidbody>();
          bikeRigidbody.centerOfMass = centerOfMass.localPosition;
        }
    
        // finds the corresponding visual wheel
        // correctly applies the transform
        public void ApplyLocalPositionToVisuals(WheelCollider collider)
        {
            if (collider.transform.childCount == 0)
            {
                return;
            }

            Transform visualWheel = collider.transform.GetChild(0);

            Vector3 position;
            Quaternion rotation;
            collider.GetWorldPose(out position, out rotation);

            visualWheel.transform.position = position;
            visualWheel.transform.rotation = rotation;
        }

        public void FixedUpdate()
        {
             // dampen the steering of the rigidbody
             float step = steerDamping * Time.deltaTime * bikeRigidbody.velocity.magnitude;
             Quaternion targetRotation = Quaternion.Euler(bikeRigidbody.rotation.eulerAngles.x, bikeRigidbody.rotation.eulerAngles.y, 0);
             Quaternion currentRotation = Quaternion.RotateTowards(bikeRigidbody.rotation, targetRotation, step);
             bikeRigidbody.MoveRotation(currentRotation);

            float motor = maxMotorTorque * Input.GetAxis("Vertical");
            float steering = maxSteeringAngle * Input.GetAxis("Horizontal");

            foreach (AxleInfoSingle axleInfo in axleInfos)
            {
                if (axleInfo.steering)
                {
                    axleInfo.wheel.steerAngle = steering;
                }
                if (axleInfo.motor)
                {
                    axleInfo.wheel.motorTorque = motor;
                }
                ApplyLocalPositionToVisuals(axleInfo.wheel);
            }
        }
    }

Bike.png

Die Werte für das CenterofMass-Transform sind (es liegt zentriert am tiefsten Punkt unter dem Fahrzeug):
x=0 y=-0.663 z=0

Für die visuelle Darstellung der Reifen erzeugst du ein leeres Child-Gameobjekt direkt unter dem jeweiligen Wheelcollider mit folgenden Werten:
x0= y=-0.15 z=0  (Rotation 0/0/0 Scale 1/1/1)
Unter diesem wiederum ein Child-Zylinder-Gameobjekt:
x0= y=0 z=0  Rotation: 0/0/-90 Scale: 1/0.15/1

Wenn du einfach das ganze Projekt haben möchtest, schreib mich an.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 54 Minuten schrieb Zer0Cool:

Ich habe mich mal dran gesetzt und einen einfachen Bikecontroller daraus gebastelt. Wichtig war hierbei einen Massenschwerpunkt hinzuzufügen, sonst kippt das Bike gleich beim 1. Lenkvorgang um. Nach dem Lenken neigt sich das Bike nun in eine Richtung und pendelt nach weiterem Geradeausfahren noch einige Zeit hin und her. Ich denke hier müsste man den Masseschwerpunkt nach einer Lenkung leicht in die entgegengesetzte Richtung verschieben, damit das Bike zu pendeln aufhört. Das habe ich allerdings erst einmal nicht gemacht, da ich nicht weiß, was für eine Verhalten du möchtest. Vielleicht gibt es auch noch andere Möglichkeiten das Pendeln in den Griff zu bekommen, mit dem Luftwiderstand des Rigidbody habe ich es nicht geschafft:
 


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

/// <summary>
/// Simple Bike Controller by zer0f0rce (skype) for the Unity Insider Forum.
/// Missing Feature: Move the center of mass to the opposite direction of the steering process.
/// Relating to:
/// https://docs.unity3d.com/Manual/WheelColliderTutorial.html
/// </summary>
[System.Serializable]
    public class AxleInfoSingle
    {
        public WheelCollider wheel;
        public bool motor;
        public bool steering;
    }

    public class SimpleBikeController : MonoBehaviour
    {
        public List<AxleInfoSingle> axleInfos;
        public float maxMotorTorque;
        public float maxSteeringAngle;
        public Transform centerOfMass;

        void Start()
        {
            Rigidbody rb = GetComponent<Rigidbody>();
            rb.centerOfMass = centerOfMass.localPosition;
        }
    
        // finds the corresponding visual wheel
        // correctly applies the transform
        public void ApplyLocalPositionToVisuals(WheelCollider collider)
        {
            if (collider.transform.childCount == 0)
            {
                return;
            }

            Transform visualWheel = collider.transform.GetChild(0);

            Vector3 position;
            Quaternion rotation;
            collider.GetWorldPose(out position, out rotation);

            visualWheel.transform.position = position;
            visualWheel.transform.rotation = rotation;
        }

        public void FixedUpdate()
        {
            float motor = maxMotorTorque * Input.GetAxis("Vertical");
            float steering = maxSteeringAngle * Input.GetAxis("Horizontal");

            foreach (AxleInfoSingle axleInfo in axleInfos)
            {
                if (axleInfo.steering)
                {
                    axleInfo.wheel.steerAngle = steering;
                }
                if (axleInfo.motor)
                {
                    axleInfo.wheel.motorTorque = motor;
                }
                ApplyLocalPositionToVisuals(axleInfo.wheel);
            }
        }
    }

 

Danke schonmal, allerdings kippt bei mir das Bike direkt beim ersten Lenkvorgang um (Ich habe in die Mitte ein Würfel gesetzt und es dem Centre of Mass zugeordnet, war das richtig??). Außerdem, Ich weiß nicht ob es an mir liegt aber die Visuellen Räder drehen sich bei mir nicht beim lenken obwohl das doch eigentlich hier passieren sollte oder?:

 

Transform visualWheel = collider.transform.GetChild(0);

        Vector3 position;
        Quaternion rotation;
        collider.GetWorldPose(out position, out rotation);

        visualWheel.transform.position = position;
        visualWheel.transform.rotation = rotation;

Aber trotzdem schonmal danke!

 

MfG J3nsis

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das Center of Mass muss ganz unten auf den Boden verschoben werden (geht auch unter den Boden), ist es zu hoch, dann kippt das Bike ganz leicht um.

Ja die Räder schlagen ein und drehen sich, aber ich vermute bei dir einen Fehler im Aufbau der GameObjects. Wie ich oben schrieb, muss das eigentliche Mesh des Rades noch einmal in ein leeres Gameobjekt (der als Contrainer dient) gepackt werden. 
Für das Mesh des Rades einen Cylinder nehmen (wie oben beschrieben einstellen) und hier den Collider entfernen (hatte ich noch vergessen)!
Dieses Mesh ist dann wiederum ein Child den Gameobjektes, also der Aufbau ist wie folgt:
Vorderes Rad:
- front Wheel (WheelCollider): Position: 0 0 1 Rotation: 0 0 0 Scale: 1 1 1
---- GameObject (Container): Position: 0 -0.15 0 Rotation: 0 0 0 Scale: 1 1 1
-------- Cylinder (Mesh): Position: 0 0 0 Rotation: 0 0 -90 Scale: 1 0.15 1

Hinteres Rad:
- rear Wheel (WheelCollider): Position: 0 0 -1 Rotation: 0 0 0 Scale: 1 1 1
---- GameObject (Container): Position: 0 -0.15 0 Rotation: 0 0 0 Scale: 1 1 1
-------- Cylinder (Mesh): Position: 0 0 0 Rotation: 0 0 -90 Scale: 1 0.15 1

Ich bin gerade noch dabei in das Skript eine Dämpfung für die Neigung des Bikes einzubauen...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hier nochmal der aktuelle Code, falls den Thread noch jemand verfolgt:

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

/// <summary>
/// Simple Bike Controller by zer0f0rce (skype) for the Unity Insider Forum.
/// "Center of Mass" should be a child gameObject with a centered position below the vehicle on the ground.
/// To completely prevent the swinging of the vehicle add a constraint "freeze rotation Z" to the rigidbody.
/// Missing Feature: Move the center of mass to the opposite direction of the steering process.
/// Relating to:
/// https://docs.unity3d.com/Manual/WheelColliderTutorial.html
/// </summary>
[System.Serializable]
public class AxleInfoSingle
{
    public WheelCollider wheel;
    public bool motor;
    public bool steering;
}

public class SimpleBikeController : MonoBehaviour
{
    public List<AxleInfoSingle> axleInfos;
    public float maxSpeed = 20.0f;
    public float maxMotorTorque;
    public float maxSteeringAngle;
    public Transform centerOfMass;
    public float steerDamping = 10.0f;
    public float timeToZAlignment = 0.75f;
    private Rigidbody bikeRigidbody;
    private AudioSource bikeAudio;
    private string consoleLog = "";
    private float lastSteer = 0;
    private float lastSteerDelta = 0;


    void Start()
    {
        bikeRigidbody = GetComponent<Rigidbody>();
        bikeRigidbody.centerOfMass = centerOfMass.localPosition;
        bikeAudio = GetComponent<AudioSource>();
    }

    // finds the corresponding visual wheel
    // correctly applies the transform
    public void ApplyLocalPositionToVisuals(WheelCollider collider)
    {
        if (collider.transform.childCount == 0)
        {
            return;
        }

        Transform visualWheel = collider.transform.GetChild(0);

        Vector3 position;
        Quaternion rotation;
        collider.GetWorldPose(out position, out rotation);

        visualWheel.transform.position = position;
        visualWheel.transform.rotation = rotation;
    }

    public void FixedUpdate()
    {
        lastSteerDelta = Time.time - lastSteer;
        if ((Mathf.Abs(Input.GetAxis("Horizontal")) > 0.00001f))
        {
            lastSteer = Time.time;
        }

        Vector3 localAngularVelocity = bikeRigidbody.transform.InverseTransformDirection(bikeRigidbody.angularVelocity);
        Vector3 localRotation = bikeRigidbody.transform.localRotation.eulerAngles;
        if ((lastSteerDelta > timeToZAlignment) ||
            (localRotation.z > 0 && localRotation.z < 60) && (Input.GetAxis("Horizontal") > 0) ||
            (localRotation.z > 300 && localRotation.z < 360) && (Input.GetAxis("Horizontal") < 0))
        {
            consoleLog = "Aufrichten aktiv";
            float step = steerDamping * Time.deltaTime * bikeRigidbody.velocity.magnitude * 0.25f; //geschwindigkeit von aufrichten
            Quaternion targetRotation = Quaternion.Euler(bikeRigidbody.rotation.eulerAngles.x, bikeRigidbody.rotation.eulerAngles.y, 0);
            Quaternion currentRotation = Quaternion.RotateTowards(bikeRigidbody.rotation, targetRotation, step);
            bikeRigidbody.MoveRotation(currentRotation);

        }
        else
        {
            consoleLog = "";
        }

        // Some Infos about values:
        // Rigidbody localAngularVelocity: if z - then the bike is rolling to the right ...  if z + then to the left
        // Input.GetAxis("Horizontal"): if player directs to the left then value is -  ... if to the right then + 
        // Transform localRotation: if z is between 0-60 then the bike is on the left side ... if between 300-360 then on the right

        if (bikeAudio != null)
        {
            bikeAudio.volume = bikeRigidbody.velocity.magnitude * 0.1f;
            bikeAudio.pitch = bikeRigidbody.velocity.magnitude * 0.1f;
        }

        float motor;
        if (bikeRigidbody.velocity.magnitude < maxSpeed)
        {
            motor = maxMotorTorque * Input.GetAxis("Vertical");
        }
        else
        {
            motor = 0;
        }

        float steering = maxSteeringAngle * Input.GetAxis("Horizontal");

        foreach (AxleInfoSingle axleInfo in axleInfos)
        {
            if (axleInfo.steering)
            {
                axleInfo.wheel.steerAngle = steering;
            }
            if (axleInfo.motor)
            {
                axleInfo.wheel.motorTorque = motor;
            }
            ApplyLocalPositionToVisuals(axleInfo.wheel);
        }
    }

    void OnGUI()
    {
        GUI.TextArea(new Rect(10, Screen.height - 70, Screen.width - 10, Screen.height - 10), consoleLog);
    }
}


So sieht das Ganze dann aus:
Bikescene.png

Bikescene2.png

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...