[Neuling] Roll a Ball Extended Version - Lektion 6 - Münzen für den Spieler

  • Willkommen bei "[Neuling] Roll a Ball Extended Version - Lektion 6 - Münzen für den Spieler" 8)

    Diese Lektion setzt Lektion 5 dieser Reihe voraus und baut entsprechend darauf auf.


    Als nächstes wollen wir uns um die Münzen in unserem Spiel kümmern, welcher der Spieler einsammeln muss um das Spiel erfolgreich zu beenden.


    Navigiert in den FBX Ordner und zieht das Objekt "Coin" auf das Spielfeld und ändert die Position der Münze folgendermaßen: "x = 0, y = 0.7, z = 0" die Rotation sollte jeweils auf 0 sein - die Scale (Größen-Werte) sollten bei ca -70, -70 und -13 (mit jeweiligen Nachkommastellen liegen.)

    Gebt dem Coin Objekt eine "Mesh Collider" Komponente.


    Wechselt in den Material Ordner, erstellt ein neues Material mit den farblichen Hex-Wert"987930" und zieht es auf das Coin Objekt in der Szene.

    Wechselt nun zum Prefabs Ordner und zieht dieses Objekt (Coin) vom Hierarchy Fenster in den Prefabs Ordner.


    Erstellt Anschließend in der Hierarchy ein leeres Empty (Rechtsklick => Create Empty) und benennt es "Coins".

    Stellt sicher, dass der Ursprung auf 0 ist und wenn nicht, resettet es. Zieht nun die Münze (Coin) der Szene in das "Coins" Objekt um ein Kind-Element / Kind-Objekt zu erhalten.



    Dupliziert nun das "Coin" Objekt (die Münze) in der Hierarchy, sodass ihr insgesamt 20 Stk als Kind-Objekte habt. Ich übergebe im Folgenden die Positionen der 20 Münzen.

    Die Größe sowie die Rotation bleiben wie im Bild gezeigt die gleichen Werte.

    Es ändert sich nur jeweils im Transform Komponent die "Position".

    Jede Zeile steht für eine Münze - Die Spalten geben die Koordinaten an:


    Position "x" - Wert Position "y" - Wert Position "z" - Wert
    14.87 0.7 4.16
    15.12 3.12 -1.89
    14.32 1.92 9.54
    15.75 1.78 13.19
    14.49 0.7 -14.4
    2.35 0.7 -16.51
    -7.27 0.7 -15.81
    -6.74 0.7 5.57
    5.83 0.7 -5.91
    5.06 0.7 15.9
    -5.49 0.7 12.05
    -12.21 0.7 18.4
    -18.04 0.7 9.24
    -12.53 0.7 0
    -17.7 0.7 -9.84
    -12.02 0.7 -17.83
    -18.95 1.75 -17.31
    -7.91 3.87 13.8
    -14.11 3.87 7.67
    -13.07 3.87 12.79


    Euer Spielfeld sollte nun in etwa so aussehen:

    (Die Benennung dieser Münzen spielen hier keine Rolle)


    Ihr könnt nun das Spiel speichern und im Play-Mode testen.

    Doch... die Münzen sind bisher nur statische Objekte. Beendet den Play-Mode - wir wollen dies nun ändern.


    Die Münzen sollen sammelbar sein und sich zudem drehen.

    Wechselt wieder in den Prefabs Ordner und wählt dort das Objekt "Coin" aus.

    Fügt ihm ein Skript mit dem Namen "Rotator" hinzu.

    Schiebt das Skript wieder in den Scripts Ordner.


    Zum Check könnt ihr nun auch eure Münzen auf dem Spielfeld anklicken (ohne diese zu bewegen).

    Jedes der Münzen hat nun ein Skript, da das Original im Prefabs Ordner ein Skript erhalten hat.


    Wechselt nun zum Ordner mit dem Skript und öffnet dieses.

    Löscht die komplette "void Start()" Methode und fügt diese Zeile in die "void Update()" Methode ein:

    "transform.Rotate(new Vector3(5, 45, 0) * Time.deltaTime);"


    Euer Rotator Skript sollte nun so aussehen:

    Csharp
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class Rotator : MonoBehaviour {
    5. // Update is called once per frame
    6. void Update () {
    7. transform.Rotate(new Vector3(5, 45, 0) * Time.deltaTime);
    8. }
    9. }


    mit "transform.Rotate()" greifen wir auf die Rotation des Objektes zu, welches dieses Skript bekommt. Also in diesem Fall die Münze.

    wir geben dem ganzen einen Vector3, da es sich um ein 3D Objekt handelt, welches sich entsprechend im 3D Raum drehen (rotieren) soll. Die Werte sind x=5, y=45 und z=0 entsprechend.

    Da Update einmal pro Frame aufgerufen wird, wir jedoch die Objekte "Frame-unabhängig" rotieren sehen wollen, multiplizieren wir das ganze noch mit "Time.deltaTime".

    Mehr zu Time.deltaTime hier.


    Speichert das Skript ab und kehrt zum Editor zurück.

    Testet ruhig das Spiel erneut - alle platzierten Münzen sollten sich nun drehen.

    Wenn nicht, haben sie nicht das Skript und sind ebenso nicht synchron zu eurem Prefab.


    Nun kümmern wir uns darum, dass die Münzen einsammelbar werden.

    Hierzu ist ein bisschen Theorie und Hintergrundwissen notwendig.

    Wir wissen bereits, dass die sogenannten "Collider" dafür verantwortlich sind, dass unser 'Player' an diesen abprallt bzw. die Objekte 'bemerkt' und nicht durch diese hindurch rollt.

    Genau diese Collider können (ähnlich wie beim Maker) auf als "Trigger" bei Kontakt mit diesen funktionieren.

    Heißt: Unser Player berührt einen Münzen Collider und da dieser ein "Trigger" ist bzw. diese Eigenschaft von uns bekommt, prüft unser "Player" via Skript, ob es sich um eine Münze handelt und wenn ja, soll diese verschwinden (deaktiviert werden). Wir sammeln sie ja so gesehen ein.


    Hierzu navigieren wir in Unity zu unserem Prefabs Ordner und wählen das Coin Objekt an.

    Schaut euch die "Mesh Collider" Komponente genauer an. Unter der Checkbox "Convex" gibt es auch eine Chekbox "Is Trigger".

    Diese Checkbox benötigen wir - um diese zu aktivieren, wählt "Convex [x]" an und danach "Is Trigger [x]".

    Nun sollte jede Münze auf dem Spielfeld diese Eigenschaften übernommen haben.


    Doch woher weiß nun der Player, dass es sich um eine Münze handelt?

    => Das Geheimnis lautet "Tag's". Wir fügen unserem Prefab "Coin" einen 'Tag' also eine Kennung ähnlich wie #RpgMaker hinzu, damit wir dieses als Münze verifizieren können. (Später im Skript.)


    Um ein 'Tag' zu erstellen, wählt das "Coin" Prefab aus und schaut unter dem Namen oben beim Inspector nach.

    Hier ist eine Bezeichnung "Tag" mit dem Wert "Untagged" (Standardmäßig).

    Wählt nun "Untagged", wodurch sich ein Drop-Down öffnet. Wählt nun "Add Tag ...".

    Klickt auf das kleine Plus um einen neuen Tag hinzuzufügen. Nennt diesen "Coin" und klickt auf "Save".

    Wählt nun erneut euer Prefab Objekt "Coin" aus und klickt erneut auf das Tag Feld mit dem Wert "Untagged".

    Ihr solltet nun euren Tag "Coin" in der Liste vorfinden. => Merke: So werden Tags erstellt, die in Skripts verwendet werden können.

    Wählt nun den Coin Tag aus, so das es so aussieht, wie auf dem Bild:


    Nun sollten ebenso alle Münzen einen "Coin" Tag haben.

    Wählt nun im Scripts Ordner das ControllerPlayer.cs Skript aus und öffnet dieses.


    Wir wissen ja, dass es mit dem Collider und dem Trigger zusammenhängt.

    Suchen wir in der Unity Scripting API finden wir folgendes dazu.

    Wir wollen das Beispiel (ganz unten) übernehmen und schreiben in unser Skript unterhalb der "void FixedUpdate() { ... } " Methode:

    Csharp
    1. void OnTriggerEnter(Collider other)
    2. {
    3. Destroy(other.gameObject);
    4. }


    Nun wüssten wir, wie man das Objekt zerstören könnte. Aber das wollten wir eigentlich nicht. Sinnvoller wäre es dieses zu deaktivieren.

    Daher löschen wir wieder die Zeile:

    Csharp
    1. Destroy(other.gameObject);


    Wir brauchen also eine "If-Abfrage" um den Fall zu überprüfen, "wenn" das Objekt den "Tag = 'Coin' " besitzt, soll es deaktiviert werden.

    Dies kann nun in Unity gesucht werden oder man schaut sich im Editor den Aufbau eines "GameObjects" an. Also eines jeden Objektes in Unity.

    Jedes Objekt kann Komponente haben. Wir greifen nun in unserem Skript über die Funktion "void OnTriggerEnter(Collider other)" mit einer Variable "other" vom Typ "Collider" auf alles weitere zu.

    Wir benötigen aber das gameObject. (Und wir müssen den Tag vergleichen (compare - im Englischen).


    Die Zeilen, die uns noch in unserem Code fehlen sind demnach folgende:

    Csharp
    1. if (other.gameObject.CompareTag("Coin"))
    2. {
    3. other.gameObject.SetActive(false);
    4. }

    Wir vergleichen hier, ob der Tag des berührten Objektes dem Tag "Coin" entspricht und wenn ja, soll er den Status auf "false" also "deaktiviert" setzen.

    Sprich: unsere Münzen sollen deaktiviert werden.


    Dies kann man durch kennen der Methoden die Unity einen bietet herausfinden, durch googeln oder durch die Sctipting API von Unity bzw. Erfahrung mit C#.

    Daher: Auch wenn ggf. meine C# Tutorials noch nicht so weit sind, würden diese hierbei beim Verständnis sicherlich sehr helfen. (Zumindest was Funktionen, if-Abfragen und allgemein die Programmlogik betrifft.)


    Das gesamte Skript sollte nun wie folgt aussehen:


    Speichert es ab und kehrt zu Unity zurück.

    Nun könnt ihr das Spiel testen und die Münzen sollten bei Berührung verschwinden. Zumindest jene, an die man heran kommt.

    Wir haben 3 Münzen, die oberhalb unserer Reichweite liegen.

    Um diese wollen wir uns nun auch noch kümmern.


    Wechselt in den Prefabs Ordner und wählt das Objekt "Elevator" an.

    Markiert die Checkbox "Is Trigger" im "Box Collider" Komponent.

    Da es sich hierbei um ein "Primitiv" Objekt handelt, muss es nicht Convex sein, da ohnehin.

    Erstellt nun wieder einen neuen Tag Namens "Elevator" und übergebt diesen Tag den "Elevator" Objekt. (Analog zu dem Coin Objekt)


    Wechselt nun zu unserem Skript "ControllerPlayer" und öffnet dieses.

    Wir wollen nun den "Elevator" wirklich zum "Aufzug" machen, bzw. einen ähnlichen Effekt beim Berühren geben.

    Wir haben wieder einen Tag vergeben und einen Collider, der als Trigger funktioniert. Demnach brauchen wir eigentlich nur eine weitere Abfrage, die prüft, ob der Tag / das Objekt beim Berühren ein "Elevator" / Aufzug ist.

    Wenn ja, soll er uns nach oben befördern / drücken. Wenn nein, soll nichts passieren, bzw. bei einer Münze (Coin) soll diese deaktiviert werden.


    Wir gehen daher in die Zeile von "void OnTriggerEvent(Collider other)" unterhalb der "if-Abfrage" der 'Coin'.

    Wir fügen folgenden Code ein:

    Csharp
    1. else if (other.gameObject.CompareTag("Elevator"))
    2. {
    3. rb.velocity = new Vector3(0, 0, 0);
    4. rb.AddForce(0.0f, 8, 0.0f, ForceMode.Impulse);
    5. }


    Wir sagen hiermit also: "Wenn es keine Münze ist - 'Ist es ein Objekt mit dem Tag "Elevator" ' ? " Wenn ja:

    Unser Player (der Rigidbody) soll seine Bewegung komplett einstellen (rb.velocity = new Vector3(0, 0, 0);

    Und im Anschluss soll er (wie schon mal realisiert) eine Kraft erhalten. Aber diesmal nach Oben. Diese Kraft /Bewegung soll außerdem "Impulsiv" also plötzlich sein, wie eine Rakete.

    Das war es auch schon.


    Vergesst generell nicht für euch selber Kommentare mit " // .... " in eurem Code zu hinterlegen, sodass ihr entsprechend diesen später wieder versteht.

    (Eine Beschreibung könnt ihr ja anhand meiner Erklärung übernehmen.)


    Euer Skript sollte nun vollständig so aussehen:


    Speichert euer Skript ab und testet nun erneut das Spiel.

    Ihr solltet nun alle Münzen, die bisher erstellt wurden einsammeln können.

    (Die 3 Münzen auf der Plattform, bzw jene, die von der Plattform zu erreichen sind, können über den "Elevator" am Boden erreicht werden, wenn ihr mit dem Player auf diesen rollt).

    Sollte dies nicht funktionieren, prüft, ob dieser wie das Prefab den "Elevator" Tag besitzt und im Collider der "Trigger auf 'Is Trigger [x]' " gesetzt ist.




    Weiter geht es in "[Neuling] Roll a Ball Extended Version - Lektion 7 - Anzeigen der Score sowie Texte"

    :s_info: Ehemalig in dieser Community als Toothless bekannt, habe ich nun meinen Künstlernamen angenommen: Cryptogene

    So manch einer kennt ja ohnehin schon meine 3D Szenen.


    ninja_pointright Ihr wollt euch für das Forum bedanken und dieses zu 100% unterstützen? Ihr könnt uns finanziell durch eine Schenkung unterstützen. Danke für euren Support!