Erstellen einer einfachen KI in C # in Unity

Published on August 27, 2018

Erstellen einer einfachen KI in C # in Unity

Ursprünglicher Autor: Lance Talbert
  • Übersetzung
Bild

Fast jedes Spiel erfordert eine künstliche Intelligenz (KI), die mit dem Benutzer interagiert, meist in Form einer dem Spieler feindlichen Kraft. In einigen Fällen sollte die KI dem Spieler helfen, in anderen dagegen anzukämpfen, aber alle computergesteuerten Charaktere haben einige Ähnlichkeiten. Abhängig von den Anforderungen des Projekts kann die KI einfache oder komplexe Verhaltensweisen verwenden. Solche Anforderungen können Diplomatie mit einem anderen Spieler sein oder einfach auf der Plattform hin und her wandern. Wie auch immer, es muss sichergestellt werden, dass die KI ihre Arbeit mit hoher Qualität ausführt.

In diesem Projekt werde ich eine sehr einfache künstliche Intelligenz demonstrieren. Angenommen, wir erstellen ein Spiel, in dem sich ein Spieler in die Nähe eines feindlichen Hauptquartiers schleichen muss. Wenn ein Spieler von einer Verfolgungskamera bemerkt wird, werden in der Nähe Feinde erzeugt, die einen Spieler für kurze Zeit verfolgen. Das setzen wir im Projekt auf einfachster Ebene um. Nach Abschluss des Projekts erhalten Sie das verwaltete Objekt eines Spielers, einen Kreis, der als Kamera eines Feindes verwendet wird, und ein feindliches Objekt, das den Spieler verfolgt, wenn ein Kameraobjekt seine Anwesenheit meldet.

Vorbereitung


Zuerst müssen wir ein 3D-Projekt erstellen. Klicken Sie nach dem Starten von Unity oben im Fenster auf die Schaltfläche Neu (siehe Abbildung 1).


Abbildung 1: Erstellen eines neuen Projekts

Benennen Sie Ihre Projekt- KI und stellen Sie sicher, dass es sich um ein 3D-Projekt handelt. Nachdem Sie einen Ort auf dem Computer ausgewählt haben, an dem das Projekt gespeichert werden soll, klicken Sie unten auf die Schaltfläche Projekt erstellen (siehe Abbildung 2).


Abbildung 2: Bildschirm „

Projekteinstellungen“ Nach dem Erstellen eines Projekts müssen wir zunächst Ordner im Fenster „ Assets“ einrichten , um unsere Arbeit zu organisieren. Klicken Sie mit der rechten Maustaste auf das Assets- Fenster und wählen Sie Erstellen → Ordner , um einen neuen Ordner zu erstellen. Nennen Sie diesen Ordner Materials . Erstellen Sie dann einen zweiten Ordner und nennen Sie ihn Skripte . Abbildung 3 zeigt, wie es aussehen sollte.


Abbildung 3: Erstellen eines neuen Ordners

Nach alledem sollte das Fenster " Assets" wie in Abbildung 4 aussehen.


Abbildung 4: Fenster " Assets" .

Als nächstes erstellen Sie einen Boden, auf dem alle Objekte stehen. Wählen Sie im Hierarchiefenster Erstellen → 3D-Objekt → Ebene , um ein Ebenenobjekt zu erstellen, das als Boden verwendet wird.


Abbildung 5: Erstellen eines Ebenenobjekts

Benennen Sie dieses Floor- Objekt und ändern Sie seinen X-Scale- Wert auf 7 und den Z-Scale- Wert auf 3. Danach sollte das Inspector- Fenster mit dem ausgewählten Floor- Objekt wie in Abbildung 6 dargestellt aussehen.


Abbildung 6: Referenzobjekteigenschaften Etage .

Jetzt müssen wir ein neues Material für Floor erstellen , um es von anderen Objekten zu unterscheiden, die in der Szene platziert werden. Erstellen Sie im Ordner Materialien des Assets- Fensters ein neues Material, indem Sie mit der rechten Maustaste auf das Assets- Fenster klicken und Erstellen → Material auswählen .


Abbildung 7: Erstellen eines neuen Materials

Benennen Sie nach Abschluss das Material Etage .


Abbildung 8: Bodenmaterial .

Wählen Sie oben im Inspektorfenster mit dem ausgewählten Bodenmaterial einen Farbwähler aus.


Abbildung 9: Auswählen eines Farbwählers

Natürlich können Sie eine beliebige Farbe für den Boden wählen, aber in diesem Beispiel habe ich eine rotbraune Farbe gewählt, wie in Abbildung 10 gezeigt.


Abbildung 10: Farbwähler

Wählen Sie das Floor- Objekt im Hierarchiefenster aus und klicken Sie in der Mesh Renderer- Komponente auf den kleinen Pfeil neben Materials .


Abbildung 11: Vorbereitung zum Materialwechsel.

Ziehen Material Boden der Fenster Assets in dem Element 0 Komponente Mesh - Renderer Fenster der Inspektor .


Abbildung 12: Referenzmaterial Boden als Objektmaterial Boden .

Nachdem Sie das Floor- Objekt fertiggestellt haben , müssen Sie einen Bereich um die Wand herum erstellen, damit der Spieler nicht vom Rand fallen kann. Gehen Sie erneut zu Erstellen → 3D-Objekt → Ebene , um eine neue Ebene zu erstellen. Benennen Sie diese Ebene Wand und stellen Sie sie auf die gleichen Abmessungen wie Boden ein , d. H. X-Skalierung mit einem Wert von 7 und Z-Skalierung mit einem Wert von 3. Erstellen Sie dann drei weitere Wände, indem Sie das Objekt auswählen und dreimal Strg + D drücken Boden in Übereinstimmung mit den Daten aus der Tabelle.

Name
Position X.
Position y
Position z
Drehung x
Drehung z
Mauer
-35
21
0
0
-90
Mauer (1) -1
11
-15
90
0
Mauer (2)
-1
11
13.5
-90
0
Mauer (3)
34
21
0
0
90

Tabelle 1: Die Position und die Rotation von Objekten der Wand .

Nach Abschluss dieses Vorgangs müssen Sie die Position der Kamera so ändern, dass sie von oben auf den Boden schaut. Wählen Sie das Hauptkameraobjekt aus und setzen Sie die Y-Position auf 30, die Z-Position auf 0 und die X-Drehung auf 80.


Abbildung 13: Konfigurieren Sie das Kameraobjekt.

Die Szene ist vorbereitet, also ist es Zeit, einen Spielercharakter zu erstellen. Klicken Sie im Hierarchiefenster auf Erstellen → 3D-Objekt → Kugel , um ein Kugelobjekt zu erstellen. Benennen Sie dieses Objekt Spieler holen , und klicken Sie dann auf Komponente hinzufügen am unteren Rand des Inspector .


Abbildung 14: Hinzufügen einer neuen Komponente

Finden Sie jetzt den starren Körper . Wählen Sie anschließend die Rigidbody- Komponente aus der Liste aus und fügen Sie den Rigidbody zum Player- Objekt hinzu .


Abbildung 15: Zusatz der Komponente Starrkörper .

Als nächstes müssen Sie dem Spieler ein Tag zuweisen, das uns später im Code nützlich sein wird. Klicken Sie auf das Dropdown-Menü Tag in der oberen linken Ecke des Inspektorfensters und wählen Sie das Player- Tag aus .


Abbildung 16: Setzen eines neuen Tags

Wir müssen die Position des Spielers so einstellen, dass er sich nicht unter dem Bodenobjekt befindet . Im Beispiel habe ich den Spieler in der oberen linken Ecke platziert, wobei die X-Position gleich 26, die Y-Position gleich 1 und die Z-Position gleich -9 ist.


Abbildung 17: Spielerplatzierung

Damit unser zukünftiger Code ordnungsgemäß funktioniert, müssen wir ihn natürlich an das Objekt anhängen. Kehren Sie zum Hierarchie- Fenster zurück und wählen Sie dieses Mal Erstellen → 3D-Objekt → Würfel . Nennen wir diesen Cube Guard , und fügen Sie ihm die Rigidbody- Komponente und die NavMesh Agent- Komponente hinzu , indem Sie im Inspektorfenster auf die Schaltfläche Komponente hinzufügen klicken . Als nächstes platziere es irgendwo in der oberen linken Ecke der Szene. Danach sieht das Inspektorfenster des Guard- Objekts folgendermaßen aus:


Abbildung 18: Das Guard- Objekt im Inspector- Fenster .

Und dieses Objekt sollte so liegen:


Abbildung 19: Platzierung des Guard- Objekts .

Schließlich benötigen wir ein Objekt, das als "Auge" des Wachobjekts verwendet wird und das die Wache darüber informiert, dass der Spieler es berührt. Gehen Sie ein letztes Mal zum Fenster Hierarchie und wählen Sie Erstellen → 3D-Objekt → Kugel , um ein weiteres Kugelobjekt zu erstellen. Nennen Sie dieses Objekt einen Betrachter . Dieses Mal müssen wir keine weiteren Komponenten hinzufügen. Wir werden jedoch die Größe des Objekts ändern. Ändern Sie bei ausgewähltem Looker die folgenden Variablen der Transformationskomponente im Inspektorfenster .

  • Skaliere X auf 9.
  • Skaliere Y auf 0,5.
  • Skala Z bei 9.

Danach platzieren Sie das Looker- Objekt so, dass es sich im mittleren oberen Teil des Bodens befindet (siehe Abbildung 20).


Abbildung 20: Platzierung von Ebenenobjekten

Jetzt ist der richtige Zeitpunkt, um dem Looker ein einzigartiges Material zu geben , damit es sich bemerkbar macht, dass es vermieden werden sollte. Klicken Sie im Ordner " Materialien " des Fensters " Assets" mit der rechten Maustaste und erstellen Sie ein neues Material. Nennen Sie es einen Hingucker und geben Sie ihm eine leuchtend rote Farbe. Weisen Sie dieses Material anschließend als Material zu, damit das Looker- Objekt seine Farbe ändert. Danach sollte die Szene so aussehen:


Abbildung 21: Looker- Objekt mit neuem Material.

Das einzige, was uns noch bleibt, ist die Erstellung eines Navigationsnetzes für die Wache, durch das sie sich bewegen kann. Oben im Unity-Editor befindet sich das Menü Fenster . Wählen Sie das Fenster → die Navigation zu öffnen , die Navigation , in 22 gezeigt.


Abbildung 22: Navigationsfenster .

Wählen Sie das Floor- Objekt in der Hierarchie aus und aktivieren Sie im Navigationsfenster das Kontrollkästchen " Navigationsstatik " .


Abbildung 23: die Navigation der Static .

Wählen Sie dann die Option Backen oben im Fenster.


Abbildung 24: Wechseln Sie in das Menü Backen .

Das Menü Backen wird geöffnet, in dem Sie die Eigenschaften des zu erstellenden Navigationsnetzes ändern können. In unserem Beispiel muss nichts geändert werden. Klicken Sie einfach auf die Schaltfläche Backen unten rechts.


Abbildung 25: Erstellen eines neuen Navigationsnetzes

An dieser Stelle fordert Unity Sie auf, die Szene zu speichern. Speichern Sie es, woraufhin das Navigationsnetz erstellt wird. Nun sieht die Szene so aus:


Abbildung 26: Die aktuelle Szene mit dem hinzugefügten Navigationsnetz.

Jetzt ist alles in Unity konfiguriert, und es ist an der Zeit, die Skripte zu erstellen, die für das Projekt erforderlich sind. Klicken Sie im Fenster Assets mit der rechten Maustaste und wählen Sie Erstellen → C # -Skript . Nennen Sie dieses Skript Player . Wiederholen Sie diesen Vorgang noch zweimal und erstellen Sie Skripte mit den Namen Guard und Looker .


Abbildung 27: Erstellen eines neuen Skripts

Danach sieht der Ordner " Scripts " im Fenster " Assets " folgendermaßen aus:


Abbildung 28: Skriptordner .

Zuerst werden wir das Skript für den Player schreiben . Doppelklicken Sie im Assets- Fenster auf das Player- Skript , um Visual Studio zu öffnen und Code zu erstellen.

Code


Das Player- Skript ist recht einfach, es erlaubt dem Benutzer lediglich, das Ballobjekt zu bewegen. Unter der Klassendeklaration benötigen wir einen Verweis auf die Rigidbody- Komponente , die wir zuvor im Projekt erstellt haben.

private Rigidbody rb;

Unmittelbar danach wird in der Funktion starten wir bestellen die aktuelle Komponente machen Unity Starrkörper Objekt Spielerwert rb .

rb = GetComponent<Rigidbody>();

Danach sieht das Player- Skript folgendermaßen aus:


Abbildung 29: Derzeitiges Player- Skript Nachdem

der rb- Wert zugewiesen wurde, müssen wir dem Player- Objekt erlauben, sich zu bewegen, wenn wir die Pfeiltasten drücken. Um das Objekt zu bewegen, wenden wir Physik an und üben eine Kraft auf das Objekt aus, wenn der Benutzer die Pfeiltasten drückt. Fügen Sie dazu der Update- Funktion den folgenden Code hinzu:

if (Input.GetKey(KeyCode.UpArrow))
            rb.AddForce(Vector3.forward * 20);
if (Input.GetKey(KeyCode.DownArrow))
            rb.AddForce(Vector3.back * 20);
if (Input.GetKey(KeyCode.LeftArrow))
            rb.AddForce(Vector3.left * 20);
if (Input.GetKey(KeyCode.RightArrow))
            rb.AddForce(Vector3.right * 20);

Zu diesem Zeitpunkt haben wir das Player- Skript fertiggestellt . Das fertige Skript sieht folgendermaßen aus:


Abbildung 30: Ready Player Script .

Speichern Sie Ihre Arbeit und kehren Sie zu Unity zurück. Wählen Sie dieses Mal das Guard- Skript im Assets- Fenster aus . Damit der Code für Guard funktioniert, müssen Sie oben im Skript ein using-Konstrukt hinzufügen.

using UnityEngine.AI;

Als Nächstes deklarieren wir die folgenden Variablen unmittelbar nach der Klassendeklaration.

public GameObject player;
private NavMeshAgent navmesh;

Der Wert der Variablen Spieler Objekt Wache Objekt wird verwendet , einen Spieler . Es wird uns später nützlich sein, wenn wir dem Guard- Objekt befehlen, den Spieler zu verfolgen. Anschließend wird die Variable navmesh so deklariert , dass sie die NavMeshAgent- Komponente des Objekts empfängt . Wir verwenden es später, wenn der Wächter den Spieler zu verfolgen beginnt, nachdem er herausgefunden hat, dass der Spieler das Looker- Objekt berührt . Die Funktion starten , müssen wir den Wert der Variablen setzen NavMesh Komponente NavMesh Agent - Objekt:

navmesh = GetComponent<NavMeshAgent>();

Dann fügen wir in der Update- Funktion eine einzelne Codezeile hinzu:

navmesh.destination = player.transform.position;

Diese Zeile gibt das Ziel für das Guard- Objekt an . In unserem Fall wird die aktuelle Position des Player- Objekts übernommen und an diesen Punkt verschoben. Nach dem Auslösen des Objekts wird der Spieler ständig verfolgt. Die Frage ist, wie der Auslösevorgang durchgeführt wird? Es wird nicht im Guard- Skript , sondern im Looker- Skript codiert . Bevor Sie mit dem Looker-Skript fortfahren, sehen Sie sich Abbildung 31 an, um Ihren Guard- Skriptcode zu überprüfen .


Abbildung 31: Der fertige Skript - Schutz .

In Looker müssen die folgenden Variablen erneut deklariert werden:

public GameObject guard;
private float reset = 5;
private bool movingDown;

Danach werden wir die Start- Funktion auskommentieren , die wir in diesem Skript nicht benötigen. Gehen Sie zur Update- Funktion und fügen Sie den folgenden Code hinzu:

if (movingDown == false)
            transform.position -= new Vector3(0, 0, 0.1f);
        else
            transform.position += new Vector3(0, 0, 0.1f);
if (transform.position.z > 10)
            movingDown = false;
else if (transform.position.z < -10)
            movingDown = true;
reset -= Time.deltaTime;
if (reset < 0)
{
            guard.GetComponent<Guard>().enabled = false;
            GetComponent<SphereCollider>().enabled = true;
}

Hier finden die Hauptaktivitäten des Projekts statt. Analysieren wir also den Code. Je nach dem Wert der booleschen Variablen movingDown wird das Objekt, an das dieses Skript angehängt ist, nach oben oder unten verschoben. Sobald es einen bestimmten Punkt erreicht, ändert es die Richtung. Weitere Looker den Wert des Reset auf der Grundlage von Echtzeit reduzieren. Sobald der Zeitgeber kleiner als Null ist, wird er das Skript nehmen Schutz des Objekts Wache und ziehen Sie es, und dann das Objekt Wache beginnt mit dem letzten vor momenrta Position Spieler bekannt zu bewegen und dann stoppen. HinguckerAußerdem wird der Collider wieder eingeschaltet, sodass der gesamte Vorgang von vorne beginnen kann. Jetzt sieht unser Skript so aus:


Abbildung 32: Script Looker .

Apropos Collider: Es ist an der Zeit, einen Kollisionscode zu erstellen, den Looker- Timer zurückzusetzen und das Guard- Skript einzuschließen . Erstellen Sie in der Aktualisierungsfunktion den folgenden Code:

private void OnCollisionEnter(Collision collision)
{
        if (collision.gameObject.tag == "Player")
        {
            guard.GetComponent<Guard>().enabled = true;
            reset = 5;
            GetComponent<SphereCollider>().enabled = false;
        }
}

OnCollisionEnter Unity erkennt automatisch als Kollisionscode und führt diesen aus, wenn eine Kollision mit einem anderen Objekt auftritt. In unserem Fall wird zuerst geprüft, ob das gefundene Objekt ein Player- Tag hat . Wenn nicht, wird der Rest des Codes ignoriert. Andernfalls wird das Guard- Skript aktiviert, der Reset- Timer auf 5 ( dh fünf Sekunden) gesetzt und der Collider deaktiviert, sodass der Spieler sich weiterhin durch das Objekt bewegen und nicht versehentlich im Looker- Objekt stecken bleiben kann . Die Funktion ist in Abbildung 33 dargestellt.


Abbildung 33: Kollisionscode für Looker.

Daraufhin ist der gesamte Projektcode fertig! Sie können einige Dinge tun, bevor Sie das Projekt abschließen. Speichern Sie die gesamte Arbeit und kehren Sie zu Unity zurück.

Abschluss des Projekts


Um das Projekt abzuschließen, müssen wir nur Skripte an die entsprechenden Objekte anhängen und mehrere Variablen setzen. Wechseln Sie zunächst vom Navigationsfenster zum Inspektorfenster :


Abbildung 34: Öffnen Sie das Inspector- Fenster .

Beginnen wir danach mit dem Player- Objekt . Wählen Sie es im Hierarchiefenster aus , und klicken Sie unten im Inspektorfenster auf die Schaltfläche Komponente hinzufügen, und fügen Sie das Player- Skript hinzu . Dies vervollständigt das Player- Objekt .


Abbildung 35: Player- Skriptkomponente .

Wählen Sie als nächstes das Objekt Guard aus . Hängen Sie wie zuvor das Guard- Skript an das Objekt an. Dieses Mal müssen wir der Wache mitteilen, wer der Spieler ist. Ziehen Sie dazu das Player- Objekt aus der Hierarchie in das Player- Feld der Guard- Skriptkomponente (siehe Abbildung 36).


Abbildung 36: Machen Sie das Player- Objekt zum Wert des Player- Felds .

Wir müssen auch das Guard- Skript deaktivieren . In unserem Projekt wird der Wächter den Spieler nach der Aufnahme seines Drehbuchs verfolgen. Dieses Guard- Skript sollte erst aktiviert werden, nachdem der Player das Looker- Objekt berührt hat . Sie müssen lediglich das Kontrollkästchen neben dem Text Guard (Script) in der Komponente deaktivieren :


Abbildung 37: Script deaktivieren Schutz .

Wechseln Sie schließlich zum Looker- Objekt und hängen Sie das Looker- Skript daran an . Diesmal benötigt das Looker- Objekt das Guard- Objekt als Wert seiner Guard- Variablen . So wie wir das Objekt zugewiesen Spieler variable Spieler Skript - Schutz , werden wir das gleiche mit dem Objekt tun Wache und Skript Looker . Ziehen Sie Guard aus der Hierarchie in das Guard- Feld des Looker- Skripts. Und dieses Projekt ist abgeschlossen! Klicken Sie oben im Unity-Editor auf die Schaltfläche Wiedergabe, um Ihr Projekt zu testen.


Abbildung 38: Testen des Projekts

Versuchen Sie, das Player- Objekt auf das Looker- Objekt zu verschieben (vergessen Sie nicht, dass die Bewegung durch Pfeile erfolgt!). Beachten Sie, dass das Guard- Objekt danach den Spieler verfolgt. Er wird die Verfolgung für ungefähr 5 Sekunden fortsetzen, wonach er sich ergeben wird.


Abbildung 39: Ein vollständiges Projekt in Aktion.

Fazit


Diese KI ist sehr einfach, aber Sie können sie leicht erweitern. Angenommen, wenn wir uns vorstellen, dass das Looker- Objekt eine Kamera ist und der Wächter durch sie schaut, um Sie zu finden, ist es logisch, dem Guard- Objekt ein eigenes Augenpaar zuzuweisen. Der Spieler darf sich den Kameras nähern, muss aber die Augen des Wächters berücksichtigen. Sie können dieses Projekt auch mit dem Konzept kombinieren , einen Pfad zu finden : Geben Sie dem Wächter den Pfad, dem er folgen wird, und schaffen Sie so eine interessantere Umgebung für den Spieler.

Eine so einfache KI kann auf viele verschiedene Arten entwickelt werden. Möglicherweise möchten Sie das oben Genannte nicht tun und sich dazu entschließen, etwas Eigenes zu tun. Ich rate Ihnen zu experimentieren, vielleicht haben Sie die Idee eines interessanten Projekts, das abgeschlossen werden sollte.