Jump to content
Unity Insider Forum

Player Bewegung Hackt


Sir_Mathew

Recommended Posts

Hi,

hab mein erstes Player Script und irgendwie Hackt es hier und da.

Erstmal zum Bild.

Hab eine Capsule als Player. Angehängt ist die Kamera für Ego Perspektive und eine Lichtquelle die als Taschenlampe gelten soll.

Laufen mit dem Player Vor/Zurück, Links/Rechts und Springen läuft super.

Nun wollt ich mit der Maus meinen Player Rechts/Links drehen und Hoch/Runter wobei das letztere wende ich nur auf die Kamera und Taschenlampe an, damit der Player nicht auf dem Rücken Liegt. Hier ruckelt es aber im Spiel ganz schön, obwohl nur ein kleiner Raum da ist. Verstehe nicht wieso es Ruckelt...?

Und wenn ich Kamera und Taschenlampe rauf und runter drehe, als ob der Spieler huch guckt, wollte ich das mit Mathf.Clamp begrenzen. Ein Mensch kann nun mal nicht 360°Grad nach oben gucken. Hab das nur mit Taschenlampe erstmal getesten aber wenn ich langsam nach oben gucke, folgt die Taschenlampe 360°grad, bei schneller Bewegung nicht. Also hab ich da auch nen Denkfehler.

Ach und Time.deltaTime ist bei Mausabfragen unötig?

Und FixedUpdate für Player?

Hoffe auf Lösung.

Danke

 

 

using UnityEngine;

public class ScriptPlayer : MonoBehaviour
{
    public float Speed = 0;
    public float SprungPower = 0;
    public float Gravity = 0;
    public Camera camEgo;
    public Light lightEgo;

    CharacterController ccPlayer;
    Vector3 vec3PlayerBewegung = Vector3.zero;
    Vector3 vec3PlayerDrehung = Vector3.zero;
    Vector3 vec3PlayerDrehungCam = Vector3.zero;
    Vector3 vec3PlayerDrehungLight = Vector3.zero;

    void Start()
    {
        ccPlayer = GetComponent<CharacterController>();
    }

    void FixedUpdate()
    {
        if (ccPlayer.isGrounded)
        {
            vec3PlayerBewegung = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
            vec3PlayerBewegung = transform.TransformDirection(vec3PlayerBewegung);
            vec3PlayerDrehung = new Vector3(0, Input.GetAxis("Mouse X") * 20, 0);
            transform.Rotate(vec3PlayerDrehung);
            vec3PlayerDrehungCam = new Vector3(Input.GetAxis("Mouse Y") * (-1) * 10, 0, 0);
            camEgo.transform.Rotate(vec3PlayerDrehungCam);
            vec3PlayerDrehungLight = new Vector3(Input.GetAxis("Mouse Y") * (-1) * 10, 0, 0);
            var newX = Mathf.Clamp(vec3PlayerDrehungLight.x, -2.0f, 2.0f);

            lightEgo.transform.Rotate(new Vector3(newX, 0, 0));

            vec3PlayerBewegung *= Speed;

            if (Input.GetButton("Jump"))
                vec3PlayerBewegung.y = SprungPower;

        }
        vec3PlayerBewegung.y -= Gravity * Time.deltaTime;
        ccPlayer.Move(vec3PlayerBewegung * Time.deltaTime);
    }
}

 

Player.jpg

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor einer Stunde schrieb Sir_Mathew:

Hier ruckelt es aber im Spiel ganz schön, obwohl nur ein kleiner Raum da ist. Verstehe nicht wieso es Ruckelt...?

Vermutlich kein Performance-Problem, sondern eins mit den Timings im Code, wie du schon richtig annimmst. Von daher ist die Komplexität der Szene egal.

Erstmal würde ich den CapsuleCollider löschen. Der CharacterController ist bereits ein CapsuleCollider, der zusätzliche Collider bringt nichts - er könnte sogar stören, indem der CC damit kollidiert.

Als nächstes ist es möglich, dass du in ein übliches Problem mit FixedUpdate reingelaufen bist - ja, es ist genau das richtige, um framerateunabhängig zu arbeiten, aber es ist halt leider auch... framerateunabhängig. Das heißt, dass du zwei, drei Frames oder auch gar keinen Frame zwischen zwei FixedUpdates haben kannst. Stelle dir vor, das Spiel läuft mit 30 oder 120 fps, dann ist das irgendwie leicht verständlich, dass das so ist, so bei 50 FixedUpdates in der Sekunde.

Ich empfehle einmal diesen Artikel: http://blog.13pixels.de/2019/what-exactly-is-fixedupdate/
Da gibt's auch einen Abschnitt über genau dieses Problem. Die Lösung heißt Interpolation, und du kannst dafür das Script auf dein GameObject knallen, das ich im Artikle verlinkt habe.

Dann empfehle ich noch diesen Artikel: http://blog.13pixels.de/2019/creating-a-camera-setup-in-unity/
Da findest du ein paar grundsätzliche Gedanken zu Kamera-Setups, aber eigentlich zu GameObject-Hierarchien im Allgemeinen. Wenn du dir das aneignest, wird das Debuggen sofort viel einfacher.

vor einer Stunde schrieb Sir_Mathew:

und Hoch/Runter wobei das letztere wende ich nur auf die Kamera und Taschenlampe an, damit der Player nicht auf dem Rücken Liegt.

👍

vor einer Stunde schrieb Sir_Mathew:

Ach und Time.deltaTime ist bei Mausabfragen unötig?

Jau. Wenn der Spieler in einem Frame die Maus X cm bewegt, dann erwartet er, dass die Kamera sich um Y° dreht. Wie lange der Frame zum Rendern gebraucht hat, ist dabei egal. Liegt damit in der Natur des Geräts.

vor einer Stunde schrieb Sir_Mathew:

Und FixedUpdate für Player?

Würde ich in den allermeisten Fällen empfehlen. In allen anderen Fällen ist es einfach nur egal. Schadet also nie - sofern man gelernt hat, richtig mit dem Ding umzugehen. Braucht nämlich immer ein paar Anläufe. Lohnt sich aber natürlich auf lange Sicht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

So wie meine Kamera, dreht sich mein Kopf auch im Kreis.

Sehr viele Infos und dann muss mein Rechner(Gehirn) erstmal verarbeiten.

Also für Kamera 2 Scripte für X und für Y Rotation damit es gleichzeitiger läuft?

Deine Interpolations Script ist für mich erstmal ein Buch mit 12 Siegeln. Der zweck leuchtet mir etwas ein. aber eine Rotation "Rot" Wie auch immer.

Will das mal testen. Hab dein Script einfach mal meinen Player zugewiesen und nix.

Denke das ich es falsch nutze.

Muss ich in dein Script mein Player Code einfügen? Also mit in die Funktionen schreiben?

z.b.

    private void FixedUpdate()
    {
        var pos = transform.localPosition;
        if (pos == lastUpdatePos)
        {
            transform.localPosition = pos1;
        }
        else
        {
            AcceptUpdatedPosition(pos);
        }

        var rot = transform.localRotation;
        if (rot == lastUpdateRot)
        {
            transform.localRotation = rot1;
        }
        else
        {
            AcceptUpdatedRotation(rot);
        }

//mein Code......??
    }

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 3 Stunden schrieb Sir_Mathew:

Also für Kamera 2 Scripte für X und für Y Rotation damit es gleichzeitiger läuft?

Naja, hauptsächlich weil es viel einfacher zu lesen ist und Fehler sich viel schlechter verstecken können.

vor 3 Stunden schrieb Sir_Mathew:

Deine Interpolations Script ist für mich erstmal ein Buch mit 12 Siegeln

Das ist oka - da steckt viel Arbeit drin :) 

vor 3 Stunden schrieb Sir_Mathew:

Will das mal testen. Hab dein Script einfach mal meinen Player zugewiesen und nix.

Denke das ich es falsch nutze.

Muss ich in dein Script mein Player Code einfügen? Also mit in die Funktionen schreiben?

Nein, am Code musst du nichts ändern. Du packst das Ding auf das GameObject, das in FixedUpdate bewegt wird. Also in diesem Fall z.B. deinem CahracterController-GameObject. Wenn du den Effekt einmal ganz krass sehen willst, musst du testweise die Project Settings öffnen und im Menü "Time" den "Fixed Timestep" von 0.02 auf etwas hohes setzen, z.B. 1. Dann passiert FixedUpdate nur noch einmal in der Sekunde. Wenn du dich dann in FixedUpdate bewegst, dann ruckelst du im Sekundentakt durch die Gegend. Wenn du aber mein Script draufpackst, dann reagiert der Character immer noch sehr träge (die Bewegungsrichtung ändert sich nach wie vor nur sekündlich), aber der Character springt jetzt nicht mehr von Ort zu Ort.

Das Script ist jedenfalls so konzipiert, dass du ganz normalen Bewegungscode in FixedUpdate schreibst, das Script obendrauf tust ohne etwas daran zu machen, und dann das leichte Ruckeln los bist, das bei FixedUpdate ohne Interpolation entsteht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hab alles nochmal gründlich umgeschrieben.

Mausdrehung hab ich dabei sehr verlangsamt.

In Unity hackt es ein klein wenig auch mit deinen Script zum Interpolieren. Nach Build und run läuft es aber Super. 

Zu deinen Interpolieren Script, warum hast du da alles als private deklariert obwohl auch ohne private alles private sein sollte?

Zu mein Bewegungsscript hab ich aber noch ein Problem mit Player Bewegung mit Springen und isGrounded abfrage.

Und zwar wenn ich Player.isGrounded nur für Jump verwende, kann ich nur wenige cm Springen.

Nehme ich die Player Bewegung mit rein, kann ich zwar normal Springen aber im Sprung mich nicht bewegen.

Hat sicher etwas mit vec3PlayerBewegung zu tun, aber verstehe ehrlich gesagt nicht warum.

Ist mir etwas unlogisch, bzw. stehe da auf dem schlauch. Hilfe

using UnityEngine;

public class ScriptPlayer : MonoBehaviour
{
    public GameObject player;
    public Camera playerCam;
    public Light playerTaschenlampe;

    CharacterController ccPlayer;

    float flPlayerCamDrehungY = 0.0f;
    float flPlayerCamMaxHochSchwenken = -50.0f;
    float flPlayerCamMaxRunterSchwenken = 30.0f;
    float flPlayerCamBewegungSpeed = 4.0f;
    float flPlayerMausXInput = 0.0f;
    float flPlayerMausYInput = 0.0f;

    float flPlayerDrehungSpeed = 2.0f;

    float flPlayerTastaturHorizontalInput = 0.0f;
    float flPlayerTastaturVerticalInput = 0.0f;
    float flPlayerBewegungHorizontal = 0.0f;
    float flPlayerBewegungSpeed = 200.0f;
    bool blPlayerTastaturSpringenInput = false;
    int intSprungPower = 400;
    int intGravity = 1000;
    Vector3 vec3PlayerBewegung;

    void Start()
    {
        ccPlayer = player.GetComponent<CharacterController>();
    }

    void FixedUpdate()
    {
        //////////Maus Input//////////
        flPlayerMausXInput = Input.GetAxis("Mouse X");
        flPlayerMausYInput = Input.GetAxis("Mouse Y");

        //////////Tastatur Input//////////
        flPlayerTastaturHorizontalInput = Input.GetAxis("Horizontal");
        flPlayerTastaturVerticalInput = Input.GetAxis("Vertical");
        blPlayerTastaturSpringenInput = Input.GetButton("Jump");

        //////////Player Cam//////////
        flPlayerCamDrehungY -= flPlayerMausYInput * flPlayerCamBewegungSpeed;
        flPlayerCamDrehungY = Mathf.Clamp(flPlayerCamDrehungY, flPlayerCamMaxHochSchwenken, flPlayerCamMaxRunterSchwenken);
        playerCam.transform.localEulerAngles = Vector3.right * flPlayerCamDrehungY;

        //////////Player Taschenlampe//////////
        playerTaschenlampe.transform.localEulerAngles = Vector3.right * flPlayerCamDrehungY;

        //////////Player//////////
        flPlayerBewegungHorizontal -= flPlayerMausXInput * flPlayerDrehungSpeed;
        player.transform.localEulerAngles = Vector3.down * flPlayerBewegungHorizontal;
        //////////////////////hier ccPlayer.isGrounded als if abfrage funktioniert Springen aber laufen im Sprung nicht mehr möglich
        vec3PlayerBewegung = new Vector3(flPlayerTastaturHorizontalInput, 0, flPlayerTastaturVerticalInput);
        vec3PlayerBewegung = transform.TransformDirection(vec3PlayerBewegung);
        ccPlayer.Move(vec3PlayerBewegung * Time.deltaTime * flPlayerBewegungSpeed);

        if ((blPlayerTastaturSpringenInput == true) && (ccPlayer.isGrounded == true))
        {
            vec3PlayerBewegung.y = intSprungPower;
        }

        vec3PlayerBewegung.y -= intGravity * Time.deltaTime;
        ccPlayer.Move(vec3PlayerBewegung * Time.deltaTime);
        Debug.Log(vec3PlayerBewegung.y); //test
    }
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 9 Stunden schrieb Sir_Mathew:

In Unity hackt es ein klein wenig auch mit deinen Script zum Interpolieren. Nach Build und run läuft es aber Super. 

Also... im Build ist die Performance besser, weil im Editor ja noch Leistung für den Editor selbst draufgeht. Gerade Logs in der Konsole fressen spürbar Leistung, wenn man da ein paar von hat. Aber komisch klingt das trotzdem. Da würde ich nachhaken wollen, weil es sein kann, dass das nicht mit Editor/Nicht-Editor zu tun hat, sondern an etwas anderem, und dann hakt es bei anderen Leuten auf dem Rechner vielleicht auch, wenn die Bedingungen gleich sind.

vor 11 Stunden schrieb Sir_Mathew:

Zu deinen Interpolieren Script, warum hast du da alles als private deklariert obwohl auch ohne private alles private sein sollte?

https://stackoverflow.com/questions/4113651/why-explicitly-write-private

Explizit ist besser als implizit. In anderen Sprachen heißt "kein Modifikator" andere Sachen. In Java z.B. package-private. Mit einem expliziten Modifikator stellt man sicher, dass man auch wirklich private meinte und nicht einfach nur etwas vergessen hat.

vor 11 Stunden schrieb Sir_Mathew:

Zu mein Bewegungsscript hab ich aber noch ein Problem mit Player Bewegung mit Springen und isGrounded abfrage.

Naja, du überschreibst halt .y direkt im nächsten Frame wieder mit

vec3PlayerBewegung = new Vector3(flPlayerTastaturHorizontalInput, 0, flPlayerTastaturVerticalInput);

Die Lösung ist da so etwas:

if (ccPlayer.isGrounded)
{
  DoGroundMovement();
  
  if (blPlayerTastaturSpringenInput)
  {
    Jump();
  }
}
else
{
  DoAirMovement();
}

GroundMovement und Jump sind dann das, was du schon hast. AirMovement ist dann so ähnlich wie GroundMovement, aber halt ohne Überschreiben der Y-Komponente.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ah erstmal zum Thema warum es bei mir im Editor Mode Hackt und im Vollbild nicht.

Beim Fenster Modus wird alles was im Hintergrund läuft, wie Programme und Desktop mitberechnet.

Meine CPU hat eine Auslastung von 54% mit einigen Spitzen in den einzelnen Kernen.

Im Vollbild hab ich meine CPU Auslastung bei 14%. Zudem wird im Vollbild  Direct 3D zugeschaltet. 

Es liegt einfach an mein alten Rechner. Ist überlastet:(

So nun zurück zum isGrounded Problem.

Das mit der 0 hab ich irgendwie nicht auf dem Schirm gehabt. Mein Monitor ist halt älter wie deiner :o

Hab erstmal überlegt was du mit deinen 

  DoGroundMovement();

etc. meinst. Dann klar, einfach 3 Funktionen die dann aufgerufen werden.

Hab es aber nun ganz anders gemacht.

Hab einfach im Vector die zuweisung von y weggelassen, also jeden x und z einzeln zugewiesen B)

So sieht nun der gesamte Player Code aus, vielleicht will ja jemand abschreiben.:D

using UnityEngine;

public class ScriptPlayer : MonoBehaviour
{
    public GameObject player;
    public Camera playerCam;
    public Light playerTaschenlampe;

    CharacterController ccPlayer;

    float flPlayerCamDrehungY = 0.0f;
    float flPlayerCamMaxHochSchwenken = -60.0f;
    float flPlayerCamMaxRunterSchwenken = 50.0f;
    float flPlayerCamBewegungSpeed = 4.0f;
    float flPlayerMausXInput = 0.0f;
    float flPlayerMausYInput = 0.0f;

    float flPlayerDrehungSpeed = 2.0f;

    float flPlayerTastaturHorizontalInput = 0.0f;
    float flPlayerTastaturVerticalInput = 0.0f;
    float flPlayerBewegungHorizontal = 0.0f;
    float flPlayerBewegungSpeed = 200.0f;
    bool blPlayerTastaturSpringenInput = false;
    int intSprungPower = 7;
    int intGravity = 20;
    Vector3 vec3PlayerBewegung;

    void Start()
    {
        ccPlayer = player.GetComponent<CharacterController>();
    }

    void FixedUpdate()
    {
        //////////Maus Input//////////
        flPlayerMausXInput = Input.GetAxis("Mouse X");
        flPlayerMausYInput = Input.GetAxis("Mouse Y");

        //////////Tastatur Input//////////
        flPlayerTastaturHorizontalInput = Input.GetAxis("Horizontal");
        flPlayerTastaturVerticalInput = Input.GetAxis("Vertical");
        blPlayerTastaturSpringenInput = Input.GetButton("Jump");

        //////////Player Cam//////////
        flPlayerCamDrehungY -= flPlayerMausYInput * flPlayerCamBewegungSpeed;
        flPlayerCamDrehungY = Mathf.Clamp(flPlayerCamDrehungY, flPlayerCamMaxHochSchwenken, flPlayerCamMaxRunterSchwenken);
        playerCam.transform.localEulerAngles = Vector3.right * flPlayerCamDrehungY;

        //////////Player Taschenlampe//////////
        playerTaschenlampe.transform.localEulerAngles = Vector3.right * flPlayerCamDrehungY;

        //////////Player//////////
        flPlayerBewegungHorizontal -= flPlayerMausXInput * flPlayerDrehungSpeed;
        player.transform.localEulerAngles = Vector3.down * flPlayerBewegungHorizontal;
        vec3PlayerBewegung.x = flPlayerTastaturHorizontalInput;
        vec3PlayerBewegung.z = flPlayerTastaturVerticalInput;
        vec3PlayerBewegung = transform.TransformDirection(vec3PlayerBewegung);
        ccPlayer.Move(vec3PlayerBewegung * Time.deltaTime * flPlayerBewegungSpeed);

        if ((blPlayerTastaturSpringenInput == true) && (ccPlayer.isGrounded == true))
        {
            vec3PlayerBewegung.y = intSprungPower;
        }

        if (ccPlayer.isGrounded == false)
        {
            vec3PlayerBewegung.y -= intGravity * Time.deltaTime;
        }
        else
        {
            if (blPlayerTastaturSpringenInput == false)
            {
                vec3PlayerBewegung.y = 0;
            }
        }
    }
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...