Jump to content
Unity Insider Forum
Sign in to follow this  
DerStefan

[2D] Charaktermodell schwebt

Recommended Posts

Hallo,

bin neu hier im Forum und befasse mich erst seit Kurzem mit Unity.
Meine Version ist die 2018.3.0f2 Personal (Windows 7 Pro 64 Bit).

Habe mir ein Youtube-Tutorial angeschaut und in dem 2D-Spiel bereits folgendes umgesetzt:
- Charaktermodell mittels einzelner Texturen zusammensetzen
- RigidBody2D und Collider setzen
- rutschiges Material erstellen, damit der Charakter nicht an vertikalen Wänden hängen bleibt (dieses den beiden Collidern zuweisen)
- Animationen hinzugefügt (laufen, springen, idle)
- Schusswaffe abfeuern und Schaden hinzufügen
- Laser anhand von unsichtbaren Trigger-Wänden automatisch vernichten lassen

Mein derzeitiges Problem ist, dass mein Charaktermodell aus mir unbekannten Gründen schwebt.
Anfangs hatte ich das Problem, dass das Laufen sehr schwergängig war (fast schon wie Zeitlupe).
Beim Springen gab es nie Probleme (und der Luft konnte er sich schneller horizontal bewegen als auf dem Boden).

Mitlerweile ist es aber schlimmer geworden, heißt, das Charaktermodell schwebt nur noch
und auch noch immer weiter nach oben (langsam, aber sichtbar).
Änderungen der Gravity haben keinen Unterschied bewirkt.

Hab mir die Videos mehrmals angeschaut, aber ich finde einfach den Fehler nicht.
(Im Video wird eine ziemlich alte Unity-Version verwendet - Version 4 und 5).

Das sind meine Skripte, die ich bisher erstellt bzw. nachgestellt habe:
CollisionDetection, EnemyHealth, HealthController, LaserDamage und PlayerController
EnemyHealth, HealthController und LaserDamage schließe ich mal aus...

Das ist das CollisionDetectionSkript:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
	public class CollisionDamage : MonoBehaviour
{
    public float damage = 1;
	    void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.CompareTag("Player")) // If object is the player:
        {
            collision.SendMessage("ApplyDamage", damage); // Apply damage to player
        }
    }
	    void OnTriggerStay2D(Collider2D collision)
    {
        if (collision.CompareTag("Player")) // If object is the player:
        {
            collision.SendMessage("ApplyDamage", damage); // Apply damage to player
        }
    }
}
	

Der PlayerController:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
	public class PlayerController : MonoBehaviour
{
    public float maxSpeed    = 4; // Movement speed of character (Orig = 4)
    public float jumpForce   = 500; // Jump force of character
    public Transform groundCheck; // Check if character is on ground or not
    public LayerMask whatIsGround; // Define what is grounded
	    [HideInInspector] // Don't show the following variables inside of the Inspector in Unity
    public bool lookingRight = true; // Character looks right by default
    public GameObject laserPrefab;
    public Transform spawnPoint;
    public float laserSpeed = 500;
    private Rigidbody2D rigidbody2D; // Access Rigidbody2D class
    private Animator animator; // Access animator class
    private bool isGrounded  = false;
    private bool jump        = false; // Is character jumping?
    private bool isAttacking = false;
	    // Start is called before the first frame update
    void Start()
    {
        rigidbody2D = GetComponent<Rigidbody2D>(); // Access Rigidbody2D class
        animator    = GetComponent<Animator>(); // Access animator class
    }
	    void Update() // Update is called once per frame
    {
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            jump = true;
        }
        if (Input.GetButtonDown("Fire1") && !isAttacking)
        {
            isAttacking = true;
        }
    }
	    void FixedUpdate() // Update is called fixed (e.g 0.02 seconds for 50 FPS) - main code goes here
    {
        float horizontal = Input.GetAxis("Horizontal"); // Left right arrows
        animator.SetFloat("Speed", Mathf.Abs(horizontal)); // Convert negative values
        rigidbody2D.velocity = new Vector2(horizontal * maxSpeed, rigidbody2D.velocity.y); // Character movement
        isGrounded = Physics2D.OverlapCircle(groundCheck.position, 0.15F, whatIsGround);
        //isGrounded = Physics2D.OverlapCircle(groundCheck.position, 0.15F, whatIsGround); // ORIG
        animator.SetBool("IsGrounded", isGrounded); // Parameter IsGrounded (in Unity) = Value of isGrounded
	        if ((horizontal > 0 && !lookingRight) || (horizontal < 0 && lookingRight)) // If character moves right but doesn't look right OR if character moves left and looks right:
        {
            Flip(); // Flip character
        }
        if (jump)
        {
            rigidbody2D.AddForce(new Vector2(0, jumpForce)); // Move character 0 in X, and "500" in Y
            jump = false; // Enable jumping again
        }
        if (isAttacking)
        {
            animator.SetTrigger("Attack"); // Enable attack animation
            GameObject laser = (GameObject)Instantiate(laserPrefab, spawnPoint.position, Quaternion.identity);
	            if (lookingRight)
            {
                laser.GetComponent<Rigidbody2D>().AddForce(Vector3.right * laserSpeed);
            }
            else
            {
                laser.GetComponent<Rigidbody2D>().AddForce(Vector3.left * laserSpeed);
            }
            isAttacking = false;
        }
    }
    public void Flip() // Flip character
    {
        lookingRight = !lookingRight; // Invert looking direction
        Vector3 vector3Temp = transform.localScale; // Temporar saving
        vector3Temp.x *= -1; // Invert looking direction
        transform.localScale = vector3Temp; // Execute flipping
    }
}

Und hier noch zwei Screenshots, die CircleCollider zeigen - Anhang.
(Der Sprecher im Video empfiehlt, statt nur 1 Collider zu nutzen, 3 verschiedene zu verwenden.)
Habe im 1. Screenshot die GroundDetection absichtlich deaktiviert, damit man die Collider besser sieht.

Sicherlich irgendein Anfängerfehler...

Danke für jede Hilfe!

unity1.png

unity2.png

Share this post


Link to post
Share on other sites

Verstehe nicht ganz, wie es mit "Schweben" aussieht. Reagiert dein Player gar nicht auf die Gravitation? Rigidbody hast du ja drauf, theoretisch muss dein Player runterfallen, bis er auf Kollider trifft.

Ein Teil der Steuerung scheint bei dir in der FixedUpdate zu sein. War es in dem Youtube Tutorial genau so? Halte ich für keine gute Idee. Wenigstens die Inputs sollte man eigentlich in der Update einlesen. Vielleicht wollte der Autor des Tutorials somit die Geschwindigkeit des Players FPS unabhängig haben, aber dafür gibts Time.deltaTime.

Vielleicht hängt das auch damit zusammen, dass dein Charakter sich wie in der Zeitluppe bewegt.

Du kannst es testen und FixedUpdate Intervall verkürzen.

Geh Edit -> Project Settings -> Time -> Fixed Timestep. Standartmäßig steht da 0.03 oder 0.02. Versuch mal auf 0.01 zu stellen und guck ob dein Charakter sich nun schneller bewegt. bzw. reagiert.

 

Share this post


Link to post
Share on other sites

Hi und danke für deine Antwort.

Das mit dem FixedUpdate war im Tutorial genau so.
Habe mir das hier als Notiz geschrieben:


- die Spiele-Logik wird nun entweder in die void Update() oder in die void FixedUpdate() geschrieben
  - die void FixedUpdate() sorgt dafür, dass alles im gleichen Takt (z.B. 0,02 Sekunden) abläuft während die void Update() variieren kann
- void Update() wird in diesem Beispiel nur für Springen und Schießen verwendet
- die einfachen Steuerungstasten können in der void FixedUpdate() implementiert werden, da es dort nicht auf die Millisekunde genau drauf ankommt

Ich habe jetzt mal weiter rumprobiert und sobald ich den Animator ausschalte, fällt der Charakter auf den Boden.
Ist der Animator an, bleibt der Charakter einfach in der Luft schweben.
(Er befindet sich standardmäßig 1 Meter über der Plattform.)

Das komische ist aber, dass ich mit den Steuerungstasten nicht den Charakter bewege, sondern nur seine Neigung ändere.

Liegt er schließlich auf dem Boden, kann ich ihn bewegen, was aber sehr seltsam aussieht.
Hier mal 2 GIF-Dateien, damit du sehen kannst, wie es abläuft:
Ohne Animator:
wik8pb4d.gif

Mit Animator:
izil34dg.gif

P.S. Das mit dem FixedUpdate werde ich prüfen, aber vorher sollte der Charakter sich schon normal bewegen können :)

Viele Grüße

 

Share this post


Link to post
Share on other sites

Also liegts an Animationen? Vielleicht hast du ausversehen die Welt Koordinaten des Spielers mitaufgezeichnet beim animieren, deswegen kehrt er immer zu der Ursprungsquelle zurück, die aufgezeichnet wurde?

Share this post


Link to post
Share on other sites

Hi,

das könnte sein.
Ich kam mit dem Animator ehrlich gesagt überhaupt nicht klar.
Er hat die Animationen immer automatisch mehrmals erstellt,
obwohl ich sie nur auf einem Zeitpunkt setzen wollte.
Selbst beim Setzen auf "flat", änderte sich nichts.
Ich musste dann immer alles händisch löschen.

Allerdings müsste sich der Charaker nach Deaktivieren des Animators doch dennoch normal bewegen?
Es fehlen dann die Animationen (wie z.B. Fußbewegungen).

In meinem Fall wird der Charakter rotiert und erst bewegt, wenn er auf dem Boden liegt.

P.S. Die GIF-Animationen sind sehr kurz, in Echt würde der beim Schweben immer weiter hoch gehen.

Grüße

Share this post


Link to post
Share on other sites

Hallo,

ich habe ein paar kleine Fortschritte gemacht.

Zuerstmal hat es nichts gebracht, die Animationen zu löschen.
Ich musste im Inspector den Animation Controller (der meinem Charakter hinzugefügt war) resetten.
Erst dann hörte die Sache mit dem Schweben auf.

Das nächste Problem war, dass der Charakter statt zu laufen immer nur komisch umkippte (wie oben in der GIF).
Das lag an zwei Boundaries (unsichtbare Wände), die sich jeweils links und rechts neben dem Charakter befinden.
(In einem Abstand von rund 20 Metern).
Diese dienen dazu, abgeschossene Laser zu zerstören, damit diese nicht endlos weit fliegen.

Seltsamerweise wird der Charakter von diesen Boundaries magisch angezogen.
Deaktiviere ich nur den einen, zieht's den Charakter automatisch zu dem anderen.
Ich muss im Inspector bei den Boundaries "IsTrigger" deaktivieren.
Der Autor des Tutorials weist aber explizit darauf hin, dass diese auf isTrigger gesetzt sein müssen,
da sonst der Charakter dagegen laufen könnte.
Ich dachte aber, dass der Abstand zwischen Boundaries und Charakter eh immer gleich wäre.
(Sprich, er könnte doch eh niemals dagegen laufen?!)

Das letzte Problem war, dass der Charakter immer am Umkippen war, als er einfach nur still stand.
Dafür habe ich den Collider, der für die Füße war, durch einen eckigen ersetzt.
Beim Stehen kippt er nicht mehr um, aber leider beim Laufen (nicht viel, aber etwas).

Daher die Abschlussfragen:
1. Wie kann es sein, dass der Charakter von unsichtbaren Wänden angezogen wird?
2. Was muss ich einstellen, damit der Charakter nicht anfängt umzukippen, sobald ich mich bewege? (Anhang)

Zu 2. hab ich gerade gesehen, dass es nicht mehr passiert, wenn ich bei RigidBody2D (im Inspector)
"Freeze Rotation Z" ankreuze.
Ob das aber wirklich korrekt ist, weiß ich auch nicht...
Der soll ja nur beim Laufen nicht umkippen.

P.S: Dass es keine Lauf-Animation gibt, ist normal, da ich ja alles gelöscht hab.

Danke für jede Hilfe!

Viele Grüße

 

unityLaufen.gif

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×