You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 7 Next »

Nachdem unser Konzept stand, haben wir als Gruppe beschlossen das wir als erstes einen kleinen spielbaren Prototyp haben wollen,
in welchen wir unsere Spielidee und Konzept testen können.

Grund dafür war das man so relativ schnell fest stellen kann ob unser Konzept überhaupt funktioniert und den Spieler spaß machen kann.

Sozusagen wurde an diesen Punkt entschieden ob wir das Spiel so weiter führen können wie geplant oder wir fundamentale Änderung vornehmen müssen.

Unser derzeitiger stand ist ein Raum mit Spielelementen wie einen Teich, einer Sandbank und diverse Felsen.
Zu diesen Reiht sich eine saftige Wiese die von Bäumen als Raum Trenner umgeben ist.
Unsere Hauptfigur muss sich im Prototyp Raum gegen eine Armee von Explodierenden Teddybären, aggressiven Nahkampf Braunbären
und Pfeil schießende kleine Hamster durchsetzen.
Dafür steht dem Spieler ein Arsenal an Waffen zur Verfügung: Pistole, MG, Shoutgun, Raketenwerfer.

Der Spieler erleidet passend zum Angriff schaden, ebenso kann der Spieler den Tieren schaden.
Der Spieler erhält Feedback wenn er die Tiere schadet oder tötet.

Ein Menü zum Start, bei Pause und beim Tot steht dem Spieler zur Verfügung.

In Anbetracht unseres derzeitigen Standes sind wir überzeugt das wir ein gutes und spaßiges Spiel entwickeln können
und halten am bestehenden Konzept fest.

 

Hier kommt eine Zusammenfassung wie der Prototyp entstanden ist

Als erstes wurde das Unity Projekt erstellt, ein Dummy und unsere Skizze des Main Charakters eingefügt.
Dazu wurden dann die ersten Einstellungen wie Collider vorgenommen und einfache Skripte angepasst.

 

Daraufhin haben wir begonnen die Spielwelt entwickeln.
Grundstein dafür war der Boden und die Wände.

[Bild von Welt ohne Objekte und Gegner]

Um die Welt noch lebendiger aussehen zu lassen haben wir einige Spielobjekte konzeptioniert, erstellt und in die Welt implementiert
[Bilder von Objekten]

Abgerundet wird der Prototypraum von einer Auswahl an Gegner:
[Bilder von Den Gegner]

 Um ein tieferen Blick in die Entwicklung zu gewährleisten gewähren wir ein tieferer Einblick in die Entwicklung unseres Pfeilschiessenden Hamster.

Angefangen haben wir mit einer ersten Skizze.

[Skitze Teemo]

Auf dieser Skizze haben wir den Charakter aufgebaut und seine Walkcyclen passend zum Grundentwurf ausgearbeitet.
Der Charakter hat 6 Walkcyclen die wir alle auf ein „Atlas“ gespeichert haben um „draw-calls“ von Unity zu vermindern und somit eine Höhere Performance zu gewährleisten

[Altas]

Der Atlas in Animations Abläufe übersetzt sieht wie folgt aus.
[Teemo Animationen]

Nun müssen wir Unity mitteilen woher er wissen soll wann er welche Animation abspielen soll.
Dafür nutzen wir den Animator.

[Bild Animator]

Die Variable ,typ integer,  MoveDir erhält je nachdem in welche Richtung der Hamster laufen soll einen bestimmten Wert (oben = 1; rechts = 2, unten = 3, links = 4).
Selbes gilt für die Variable AttackDir, welche dem Animator sagen soll in welche Richtung der Hamster angreifen soll.

Die einzelnen Animationen verbinden wir miteinander und geben dem Spiel die Anweisung von der alten Animation zu der neuen Animation zu ändern, wenn AttackDir oder MovementDir den Wert X erhält.

[Beispiel bild von einen Pfeil]

Nachdem wir die Animation erstellt und Unity mitgeteilt haben wann er welche Animation setzten soll kümmern wir uns um das Verhalten von unserem Hamster, anders gesagt, wir entwickeln seine Künstliche Intelligenz.

 

Im Folgenden werden wir das Script was dafür zuständig ist, Code-Schnipsel weiße erklären:

Hier sehen wir den Header unseres Hamster Script („TeemoControl“), in welchen wir unsere Variablen initialisieren welchen wir im Script benutzen.
Die [Header(„X“)] Anweisung dient zur Übersichtlichkeit im Unity Editor.
Public Variablen lassen sich in Unity Editor verändern, private Variablen hingegen sind nur im Script verwendbar und änderbar. Die Variablen wurden so benannt wie die Funktion die sie im Script erfüllen.

In der vorgenerierten Funktion void Start(), welche beim Starten der Szene einmal ausgeführt wird, binden wir die Position des Spielers an die Variable Player und weißen der Variable animator dem Hamster Animator zu den wir vor dem Skript erstellt und konfiguriert haben.
Ausserdem binden wir die public Variablen health und attackCooldown an private Variablen um feste Werte im Script weiter zu verwenden.

Vielleicht mag man sich fragen warum wir dann überhaupt public Variablen verwenden, wenn die sowieso wieder in private verwandelt werden. Der Grund dafür ist das man so in Unity schnell verschiedene Balancing Veränderung durchführen kann.

Die void Update() Funktion ist auch von Unity generiert und wird nach jedem Frame aufgerufen. Daraufhin lassen wir unsere HP Leiste Prozentual zu den Aktuellen Leben füllen.
Sollte der Welt auf kleiner gleich 0 fallen zerstören wir unser Spielobjekt und lassen ein neues Objekt erstellen, welche unsere Blutlache ist die an der Stelle des Gegners spawnt, wenn eine Gegner getötet wurde. Alle Gameobjekte haben ein eigenes Verhalten, dementsprechend auch ein Skript.
Mit der nächsten If Abfragen prüfen wir ob unser boolean move auf true gesetzte, welche dann die Funktion Movement() aufruft, zu welcher wir noch später einmal zurückkommen.
In Zeile 71 reduzieren wir die attackCooldown um die System Zeit, also wenn im Spiel 200ms vergangen sind, ist geht der attackCooldown Timer auch wirklich 200ms runter.
In der letzten If Abfrage überprüfen wir ob unser Hamster wieder angreifen darf und er sich in einer Angriffs Animation befindet, also das die variable AttackDir nicht den Wert 0 hat.
Wenn dies erfüllt ist rufen wir die Funktion shot() auf und die Funktion resetAttackCooldown(), welche später erläutert werden.

Auf dem Bild sehen wir die Funktion Movement() die wir zur Erinnerung immer aufrufen wenn der boolean move auf True gesetzt ist, also sich der Gegner bewegt.
In den ersten beiden Zeilen (87 und 88) berechnen wir jemals den Unterschied zwischen dem Spieler und unseren Gegner für die X- und für die Y-Achse.
In den nächsten 4 Zeilen errechnen wir die Hypotenuse der zuvor ausgerechneten zwei Strecken um die direkte Entfernung des Gegners zu erhalten.

Es folgt ein Schaubild was die Theorie dahinter nochmal verbildlicht.

 

Mit der errechneten Entfernung können wir gucken ob sich unser Hamster in angriffsreichweite befindet oder er vor den Spieler wegrennen soll oder dem Gegner entgegenrennen soll um in angriffsreichweite zu kommen.


Die erste If überprüft ob sich der Spieler in der Angriffszone befindet, sollte das sein sorgt die Anweisung dafür das er stehen bleibt und auch keine Bewegungsanimation mehr abspielt.
Die darauffolgende else if überprüft ob der Spieler sich zu dicht am Gegner befindet, daraufhin sorgt die Anweisung dafür das der Gegner entgegengesetzt zum Spieler wegläuft und keine Angriffsanimation mehr aktiv sein darf.
Falls keine der beiden vorherigen Szenarien zutrifft rennt der Hamster auf den Spieler zu.

Dazu auch ein Schaubild was die Theorie dahinter nochmal verbildlicht.

Wir befinden unser noch immer in der Movement() Funktion. Auf diesen Bild geht es um das Animator verhalten was wir relativ am Anfang konfiguriert haben. Ziel hier ist es das unser Hamster passend zur Position die Richtige Angriff und Bewegungsanimation abspielt.

Mit der If Abfrage (Zeile 117) überprüfen wir erstmal ob der Abstand zum Spieler auf der X-Achse Größer ist als auf der Y-Achse. Sollte, dass der Fall sein wissen wir das der Spieler sich stärker rechts oder links vom Hamster befindet als über oder unter ihm.

Da wir jetzt wissen das wir entweder die Bewegungs Animation nach links oder nach rechts abspielen müssen, müssen wir noch überprüfen ob der Spieler sich weiter rechts oder weiter links befindet.
Zuerst übernehmen wir den Fall rechts. Dafür prüfen wir in Zeile 119 ob der X-Wert vom Spieler größer als der X-Wert vom Hamster ist.
Trifft dieses Szenario ein setzten wir die Variable AttackDir auf 0, um die Angriffsanimation aufjedenfall zu unterdrücken, und setzten die Variable MovementDir auf 2, was nach unserer anfänglichen Konfiguration die Bewegungsanimation nach rechts entspricht.

Da wir wissen das der Spieler sich rechts von uns befindet nutzen wir den Zustand direkt aus und gucken ob wir uns in Angriffsreichweite befinden mit der if Abfrage in Zeile 124.
Sollten wir uns in besagter Angriffsreichweite befinden rufen wir die Funktion setMoveFalse() auf woaruf wir später nochmal zurückkommen, kurz gesagt setzt sie unser boolean move auf false, setzten die Variable MovementDir auf 0 und die Variable AttackDir auf 2, was nach unsere anfänglichen Konfiguration Angriff nach rechts entspricht. Zusätzlich weißen wir den String shotDirection die zeichenkette „right“ zu und setzten den currentShotPoint auf 1. Letztendlich rufen wir die Funktion attackOffset() auf.

Die Befehle in Zeile 130 bis 132 werden später erläutert.

Falls sich der Spieler Links befindet wird die If in Zeile 135 ausgelöst, welche dasselbe wie die If in Zeile 119 macht, nur sind alle Anweisung angepasst um die Animation nach Links zu steuern.

Der Vollständigkeitshalber der letzte Teil der Movement() Funktion. Sollte die If in der wir testen, ob der Spieler sich mehr links oder rechts befindet als oben oder unten, fehlschlagen wird die else in Zeile 152 ausgelöst. Dementsprechend testen die Nachfolgenden If Abfragen ob der Spieler sich über oder unter unseren Hamster befindet und führt dementsprechend dieselben Anweisungen aus nur auf die richtige Richtung getrimmt.

[Schaubild Animation Handling]

Um das Thema abzuschließen noch ein Schaubild was das ganze verbildlichen soll.

In Zeile 190 definieren wir die Funktion resetAttackCooldown() welche lediglich dafür sorgt das bei jedem Aufruf die derzeitige attackCooldown wieder auf den defenierten Wert von maxCooldown gesetzt wird.
Die nächste Funktion die wir definieren attackOffset() sorgt dafür das auf attackCooldown 0.7f addiert wird. Der Grund dafür das der Hamster den Pfeil erst schießen soll wenn bei der Animation der richtige Frame abgespielt wird, daher müssen wir die künstliche Verzögerung einbauen.
Die Letzte Funktion auf den Bild (Zeile 200) shot() sorgt dafür das unser Hamster wenn die Funktion aufgerufen wird ein GameObject erzeugt was der Pfeil vom Hamster ist und ihn mitteilen wo er erzeugt wird und in welche Richtung der Pfeil fliegen soll. Aus diesen Grund setzten wir in der Movement() Funktion den currentShotPoint und die shotDirection.
Diese Information Teilen wir dem Skript mit der mit den Pfeil vom Hamster verbunden ist und der regelt das Verhalten vom Pfeil.

Auf diesen Bild sehen wir die Funktion OnTriggerEnter2D(Collider2D collision) Funktion.
Diese macht letztendlich nix anderes als die Information von Unity zu bekommen was für eine Berührung bei der Hamster Hitbox, die wir in Unity definiert haben,  stattgefunden hat.

Dafür überprüfen wir den Tag des Objektes welches uns berührt haben und führen dementsprechend eine Anweisung aus.

Als Beispiel gehen wir davon aus das uns ein Maschien Gewehr Kugel, mit den Tag „BulletMG“, getroffen hat. Daraufhin wird von der health Variable der Wert 10 abgezogen, die Kugel die uns getroffen hat wird zerstört und wir initialisieren das Objekt bloodSplattern an der derzeitigen Position des Hamsters. Das bloodSplattern sind die Blut Treffer welche auch wieder von einem eigenen Skript gesteuert wird.

Im letzten Teil des Skripts definieren wir die Funktion setMoveTrue() und die Funktion setMoveFalse() welche jeweils den boolean move auf true oder false setzten.

 

Letztendlich haben wir dann mit unseren vorhandenen Gegnern, Weltobjekten und unseren Spieler den am Anfang besprochenen Prototyp Raum entwickelt.

 

 

Ziel für den nächsten Milestone:
In diesem Milestone planen wir unseren nächsten Raum typ, den Fallenraum, umzusetzen. Zudem soll unser bisheriger Raum mehr Gegner Vielfalt bekommen.

 

 

Schlusswort:

Was wir auch niemanden vorenthalten wollen ist die Wichtigkeit des stetigen Testens von dem was man macht. Als optimal hat sich erwiesen, wenn andere Leute die Sachen testen die man selbst erstellt hat. So konnten immer mehr Fehler gefunden werden als der Ersteller entdecken konnte.

Hier nur ein kleiner Ausschnitt unserer Bug Liste die wir hatten als es nur ein Gegner gab und den Spieler.

 

 

 

  • No labels