Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

1

11.07.2016, 22:21

"Eigene" Steuerung oder immer CharacterController in Unity nutzen

Hi,

ich bastel mir grade eine Steuerung zusammen und habe gelesen, dass der CharacterController in Unity immer genutzt werden sollte, besonders um Fehler zu vermeiden. Diese Komponente soll wohl anscheinend schon von Haus aus gut was liefern.

Nun habe ich aber schon ein Script mit einer Bewegungsmethode, die Spyro, oder Spiele in der Richtung, in etwa ähnelt. In einem Testscript sieht das Ganze so aus

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
private Vector3 bewegungsInputs = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));

    public float sprungGeschwindigkeit = 10F;
    public float schwerkraft = 20.0F;
    public float bewegungsGeschwindigkeit = 10.0F;
    public float rotationsGeschwindigkeit = 8.0F;

    public GameObject richtungsObjekt;

    private CharacterController charController;

    private bool kannDoppeltSpringen = false;

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

    private void Update()
    {
        if (Input.GetKey(KeyCode.A))
        {
            Bewegen(Vector3.left);
        }
        if (Input.GetKey(KeyCode.D))
        {
            Bewegen(Vector3.right);
        }
        if (Input.GetKey(KeyCode.W))
        {
            Bewegen(Vector3.forward);
        }
        if (Input.GetKey(KeyCode.S))
        {
            Bewegen(Vector3.back);
        }


        if (charController.isGrounded)
        {
            if (Input.GetButton("Jump"))
            {
                bewegungsInputs.y = sprungGeschwindigkeit;
                kannDoppeltSpringen = true;
            }

            bewegungsInputs.y -= schwerkraft * Time.deltaTime;
        }
        else if (!charController.isGrounded)
        {
            if (Input.GetButtonDown("Jump") && kannDoppeltSpringen)
            {
                bewegungsInputs.y = sprungGeschwindigkeit;
                kannDoppeltSpringen = false;
            }
            bewegungsInputs.y -= schwerkraft * Time.deltaTime;
        }

        charController.Move(bewegungsInputs * bewegungsGeschwindigkeit * Time.deltaTime);
    }

    private void Bewegen(Vector3 richtung)
    {
        Laufen(richtung);
        Rotieren(richtung);
    }

    private void Laufen(Vector3 richtung)
    {
        Vector3 neueRichtung = Quaternion.LookRotation(Camera.main.transform.position - transform.position).eulerAngles;
        neueRichtung.x = 0;
        neueRichtung.z = 0;
        richtungsObjekt.transform.rotation = Quaternion.Euler(neueRichtung);
        transform.Translate(-richtung * Time.deltaTime * bewegungsGeschwindigkeit, richtungsObjekt.transform);
    }

    private void Rotieren(Vector3 richtung)
    {
        Quaternion neueRotation = Quaternion.LookRotation(-richtung);
        transform.rotation = Quaternion.Slerp(transform.rotation, neueRotation * richtungsObjekt.transform.rotation, Time.deltaTime * rotationsGeschwindigkeit);
    }


Das alles ist natürlich doppelt gemoppelt, meine Frage ist nun, ob ich den CharacterController so einbauen kann, dass meine Bewegungsmethode erhalten bleibt, da diese eigentlich das gewünschte Verhalten aufruft. Dadurch fallen dann natürlich auch die doppelten Inputs weg, die Variablen sind derzeit in dem Testscript halt doppelt, einmal für den CharController und für die "eigene" Bewegung.

Lässt sich meine Bewegungsmethode irgendwie in den CharacterController einbinden/reinbasteln?

KeksX

Community-Fossil

Beiträge: 2 107

Beruf: Game Designer

  • Private Nachricht senden

2

11.07.2016, 22:25

Zu deiner Frage: Ja, das geht.

Aber wenn du ohnehin custom behaviour brauchst, und du den Unity-eigenen Controller komplett umwerfen würdest, warum solltest du ihn verwenden?
WIP Website: kevinheese.de

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

3

12.07.2016, 09:31

Darauf zielte ja meine Frage ab :P SOLLTE/MUSS man ihn verwenden? Ich habe damals auch mal eine Customsteuerung gehabt, beim Springen gegen Wände gabs dann den tollen Nebeneffekt das ich wie Spiderman dran hängen blieb :D Dann habe ich gesehen, dass es einen CharacterController gibt, diesen benutzt und schon habe ich meine Superkräfte verloren.

Deshalb meine Frage, ob dieser eine sichere Wahl ist oder ob man auch ohne gute Ergebnisse erzielen kann.

KeksX

Community-Fossil

Beiträge: 2 107

Beruf: Game Designer

  • Private Nachricht senden

4

12.07.2016, 18:31

Wenn der Controller nicht das macht, was du gerne hättest, gibt es keinen Grund ihn zu verwenden.


Wenn du jedoch genau das gleiche, oder etwas minimal anderes möchtest, macht es schon Sinn, den zu benutzen.
WIP Website: kevinheese.de

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

5

12.07.2016, 22:21

Genau kenne ich mich da halt leider nicht aus. Ich kann nicht sagen ob ich ihn weglassen kann :D Mit meiner eigenen Bewegungsmethode habe ich zumindest was brauchbares gebastelt glaube ich.

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

6

13.07.2016, 09:05

Das Problem mit den Wänden liegt an den Physic-Materials. Standardmäßig ist eine bestimmte Reibung eingestellt, wodurch sich bewegende Objekte auch wieder zum Stillstand kommen, statt sich wie auf einer Eisfläche zu bewegen.
Dazu kommt, dass in eigenen Bewegungsskripten meist nicht auf Kollisionen mit Wänden eingegangen wird, weshalb auch im Sprung eine Kraft gegen die Wand aufgebaut wird.
Durch die Kombination dieser beiden Dinge bleibt man an Wänden hängen, solange man sich auf diese zubewegt.

KeksX hat die ursprüngliche Frage aber bereits beantwortet: Wenn der CharacterController für deine Bedürfnisse genug mitliefert, wäre eine Verwendung und Erweiterung dessen sinnvoller, als eine Eigenimplementierung. Wenn du nicht weißt, was er alles mitliefert, du aber keinen Grund hättest, ihn wegzulassen, dann verwende ihn vorerst und sorge über deine Scripte, dass sich alles richtig verhält.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

7

13.07.2016, 21:01

Also ich habe jetzt den CharacterController weggelassen, da meine Bewegungsmethode das richtige Verhalten aufweist. Da ich übers Gamepad spielen will, brauche ich die Achsen, anstatt Buttons.

Grundsätzliches zur Steuerung: Der Spieler folgt bis jetzt einer Kugel (dem Richtungsobjekt), da er sich so wie Spyro etc. direkt auf die andere Seite drehen kann, sollte sich der Input ändern.

Die Rotationen beim Rigidbody sind auf x,y,z eingefroren.

Durch meine Abfrage wird die Steuerung aber mehr als komisch, schwer zu beschreiben, deswegen hab ichs hier mal optisch festgehalten:

http://sendvid.com/wozpwtik

Die Figur bewegt sich horizontal bogenförmig, bewege ich mich runter, geht er so seltsam in die Luft. Springen geht grade auch nicht.

Ohne CharacterController sieht das Script jetzt so aus:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public float sprungKraft = 10.0f;
    public float bewegungsGeschwindigkeit = 10.0f;
    public float rotationsGeschwindigkeit = 8.0f;
    private bool aufDemBoden;
    private float bodenLaenge = 1.5f;
    private RaycastHit bodenTreffer;
    public GameObject richtungsObjekt;

    private void Update()
    {
        if (Input.GetAxis("Horizontal") < 0)
        {
            Bewegen(Vector3.left);
        }
        if (Input.GetAxis("Horizontal") > 0)
        {
            Bewegen(Vector3.right);
        }
        if (Input.GetAxis("Vertical") < 0)
        {
            Bewegen(Vector3.down);
        }
        if (Input.GetAxis("Vertical") > 0)
        {
            Bewegen(Vector3.forward);
        }

        Vector3 physikZentrum = transform.position + GetComponent<CapsuleCollider>().center;

        if (Physics.Raycast(physikZentrum, Vector3.down, out bodenTreffer, bodenLaenge))
        {
            if (bodenTreffer.transform.gameObject.tag != "Player")
            {
                aufDemBoden = true;
            }
        }
        else
        {
            aufDemBoden = false;
        }

        if (Input.GetKeyDown("space") && aufDemBoden)
        {
            GetComponent<Rigidbody>().AddForce(Vector3.up * sprungKraft);
        }
    }

    private void Bewegen(Vector3 richtung)
    {
        Laufen(richtung);
        Rotieren(richtung);
    }

    private void Laufen(Vector3 richtung)
    {
        Vector3 neueRichtung = Quaternion.LookRotation(Camera.main.transform.position - transform.position).eulerAngles;
        neueRichtung.x = 0;
        neueRichtung.z = 0;
        richtungsObjekt.transform.rotation = Quaternion.Euler(neueRichtung);
        transform.Translate(-richtung * Time.deltaTime * bewegungsGeschwindigkeit, richtungsObjekt.transform);
    }

    private void Rotieren(Vector3 richtung)
    {
        Quaternion neueRotation = Quaternion.LookRotation(-richtung);
        transform.rotation = Quaternion.Slerp(transform.rotation, neueRotation * richtungsObjekt.transform.rotation, Time.deltaTime * rotationsGeschwindigkeit);
    }


Ich denke der Fehler liegt bei der Abfrage der Achsen, aber Springen kann ich ja moementan auch nicht. Weiß da jemand worans liegt =?

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

8

14.07.2016, 09:23

Was heißt "da er sich so wie Spyro etc. direkt auf die andere Seite drehen kann, sollte sich der Input ändern."?

Abgesehen davon denke ich mal, dass dein Ansatz, dass der Spieler einem anderen Objekt folgt, welches durch den Player-Input bewegt, nicht der richtige ist.
Was spricht dagegen, dass der Character direkt gesteuert wird? Wenn diese Kugel dem Spieler unbedingt angezeigt werden soll, dann sollte sich diese nach der Bewegung des Charakters richten.

Abgesehen davon ist die "Bewegen"-Methode etwas komisch, da bspw. die darin enthaltene "Rotieren"-Methode nur dann aufgerufen wird, wenn der Spieler Input liefert.

Sehe ich es richtig, dass du dich nicht weiter mit dem CharacterController beschäftigst?

Und du solltest die angewöhnen, englische Bezeichner zu verwenden.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

9

14.07.2016, 22:02

Hi,
als Beispiel für deine Frage mit der Spyro Bewegung (Supuer Mario 64 ist genauso) kann ichs dir nur so erklären, dass er sich nach vorne bewegt, zieht man den Joystick nach unten, dreht er sich aber sofort um. Der CharacterController läuft ja einfach nur nach hinten, guckt aber weiterhin grade aus. Nur dieses Verhalten möchte ich gerne herbeiführen. Ich habe ein funktionierendes Script mit einem CharacterController. Nur dieser dreht sich leider nicht um, daher habe ich an diesem "Testscript" gebastelt, um zu gucken, obs mit einer selbstgebauten Bewegung funktioniert.

Hier nochmal die Steuerung als Beispiel:
https://www.youtube.com/watch?v=We3NOzyTJwo

Ich finde den CharacterController gut, da dort alles einwandfrei funktioniert. Leider muss ich bei meinem Originalscript den Spieler mit dem rechten Joystick rotieren, da sich die Figur ja wie gesagt nur nach hinten bewegt, aber leider noch nach vorne guckt.

Ich möchte aber das Verhalten, bei der Bewegung auch gleichzeitig eine Rotation herbeizuführen. Wenn dies beim CharacterController möglich ist, dann benutze ich den sehr gerne weiter :D

Und zu den englischen Bezeichnern, ja da hast du Recht, ich als Unityanfänger benutze aber gerne erstmal alles auf Deutsch, einfach um selber schnell über das Script zu gucken und zu wissen was es tut. Zudem versuche ich mir ja Codeschnipsel im Notizprogramm zu merken.

Also bevor ich jetzt wieder ein langes Script poste, lass mich vorher wissen, ob du mal das OriginalScript (mit Charcontroller) sehen willst. Steuerung funktioniert über den linken Joystick, Rotation über den rechten.

Garzec

Alter Hase

  • »Garzec« ist der Autor dieses Themas

Beiträge: 693

Wohnort: Gießen

  • Private Nachricht senden

10

16.07.2016, 18:17

@Sacaldur,

ich hatte dieses Script schon mal in einem anderen Thread gepostet, ich versuche die Rotation des rechten Joysticks auf den linken zu vereinen, da ich mich komplett mit dem linken Joystick bewegen möchte, so wie in den alten Spielen.

Hier der Link zum Post:

Unity "Helfer" gesucht

Mein originales Script geht aus dem 1. Post hervor, das 2. Script ist nur das Testscript, das ich jetzt erstmal sein lasse und das originale versuche zu ändern.

Werbeanzeige