Fast jedes Spiel erfordert 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 sollte sie dagegen ankämpfen, aber alle vom Computer kontrollierten 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 oder ein einfaches Hin- und Herwandern auf der Plattform sein. Wie dem auch sei, es muss sichergestellt werden, dass die KI ihre Arbeit effizient erledigt.
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 des feindlichen Hauptquartiers schleichen muss. Wenn ein Spieler von einer Überwachungskamera bemerkt wird, entstehen in der Nähe Feinde, die den Spieler für kurze Zeit verfolgen. Das setzen wir auf einfachster Ebene im Projekt um. Nach Abschluss des Projekts erhalten Sie ein Objekt eines kontrollierten Spielers, einen Kreis, der als Kamera eines Feindes verwendet wird, und ein Objekt eines Feindes, das den Spieler verfolgt, wenn das Objekt der Kamera über seine Anwesenheit informiert.
Vorbereitung
Zuerst müssen wir ein 3D-Projekt erstellen. Klicken Sie nach dem Starten von Unity oben im Fenster oben auf die Schaltfläche
Neu (siehe Abbildung 1).
Abbildung 1: Erstellen eines neuen ProjektsNennen Sie Ihr
KI- Projekt und stellen Sie sicher, dass es sich um ein 3D-Projekt handelt. Nachdem Sie einen Ort auf dem Computer zum Speichern des Projekts ausgewählt haben, klicken
Sie unten auf die Schaltfläche
Projekt erstellen (siehe Abbildung 2).
Abbildung 2: Projekt-Setup-BildschirmNach dem Erstellen des Projekts müssen wir zunächst die Ordner im Fenster "
Assets" einrichten, um unsere Arbeit zu organisieren. Klicken Sie mit der rechten Maustaste auf das Fenster
Assets und wählen Sie
Erstellen → Ordner , um einen neuen Ordner zu erstellen. Nennen Sie diesen Ordner
Materialien . Erstellen Sie dann einen zweiten Ordner und nennen Sie ihn
Skripte . Abbildung 3 zeigt, wie es aussehen soll.
Abbildung 3: Erstellen eines neuen OrdnersNach all dem sollte das
Assets- Fenster wie in Abbildung 4 dargestellt aussehen.
Abbildung 4: Fenster " Assets" .Erstellen Sie als Nächstes 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 EbenenobjektsBenennen Sie dieses
Bodenobjekt und ändern Sie seinen
X-Skalierungswert auf 7 und den
Z-Skalierungswert auf 3. Danach sollte das
Inspektorfenster mit dem ausgewählten
Bodenobjekt wie in Abbildung 6 dargestellt aussehen.
Abbildung 6: Festlegen der Eigenschaften des Floor- ObjektsJetzt müssen wir ein neues Material für
Floor erstellen, um es von den übrigen Objekten zu unterscheiden, die in der Szene platziert werden. Erstellen Sie im Ordner "
Materialien " des Fensters "
Assets" ein neues Material, indem Sie mit der rechten Maustaste auf das Fenster "
Assets" klicken und "
Erstellen" → "Material" wählen.
Abbildung 7: Neues Material erstellenWenn Sie fertig sind, benennen Sie das Material
Boden .
Abbildung 8: Bodenmaterial .Wählen Sie oben im
Inspektorfenster mit ausgewähltem
Boden einen Farbwähler aus.
Abbildung 9: Auswahl eines Farbwählers
Natürlich können Sie eine beliebige Farbe für den Boden auswählen, aber in diesem Beispiel habe ich Rotbraun gewählt, wie in Abbildung 10 dargestellt.
Abbildung 10: Farbwähler.
Wählen Sie das
Floor- Objekt im
Hierarchiefenster aus und wählen Sie in der
Mesh Renderer- Komponente den kleinen Pfeil neben
Materialien aus .
Abbildung 11: Vorbereitung auf einen MaterialwechselZiehen Sie
Bodenmaterial aus dem Fenster "
Assets" in das Feld "
Element 0" der
Mesh Renderer- Komponente im
Inspektorfenster .
Abbildung 12: Definieren des Bodenmaterials als Material des Bodenobjekts .Nachdem wir mit dem
Bodenobjekt fertig sind, müssen wir um den Wandbereich herum erstellen, damit der Spieler nicht von der Kante fallen kann. Gehen Sie zurück zu
Erstellen → 3D-Objekt → Ebene , um eine neue Ebene zu erstellen. Wir nennen diese Wandebene und stellen sie auf die gleichen Abmessungen wie
Boden ein ,
dh X-Skalierung mit einem Wert von 7 und
Z-Skalierung mit einem Wert von 3. Erstellen Sie dann drei weitere Wände, wählen Sie ein Objekt aus und drücken Sie dreimal Strg + D. Danach platzieren Sie die Wände herum Geschlecht gemäß den Angaben in der Tabelle.
Titel
| Position X.
| Position Y.
| Position z
| Drehung x
| Drehung z
|
Wand
| -35
| 21
| 0
| 0
| -90
|
Wand (1) | -1
| 11
| -15
| 90
| 0
|
Wand (2)
| -1
| 11
| 13.5
| -90
| 0
|
Wand (3)
| 34
| 21
| 0
| 0
| 90 |
Tabelle 1: Positionen und Rotationen aller Wandobjekte.
Nachdem Sie dies alles abgeschlossen haben, 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: Einrichten des KameraobjektsDie Szene ist vorbereitet, es ist also Zeit, den Charakter des Spielers zu erstellen. Klicken
Sie im
Hierarchiefenster auf
Erstellen → 3D-Objekt → Kugel , um ein
Kugelobjekt zu erstellen. Nennen Sie dieses Objekt
Player und klicken Sie dann unten im
Inspektorfenster auf die Schaltfläche
Komponente hinzufügen.
Abbildung 14: Hinzufügen einer neuen KomponenteFinde 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: Hinzufügen einer Rigidbody- KomponenteAls nächstes müssen Sie dem Player 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: Definieren eines neuen TagsWir 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 mit einer
X-Position von 26, einer
Y-Position von 1 und einer
Z-Position von -9 platziert.
Abbildung 17: SpielerplatzierungDamit unser zukünftiger Code ordnungsgemäß funktioniert, müssen wir ihn natürlich an das Objekt anhängen. Gehen Sie zurück zum
Hierarchiefenster und wählen
Sie dieses Mal
Erstellen → 3D-Objekt → Würfel . Rufen Sie diesen
Guard- Cube auf und fügen Sie die
Rigidbody- Komponente und die
NavMesh Agent- Komponente über die
Schaltfläche Komponente hinzufügen im
Inspektorfenster hinzu . Als nächstes platzieren Sie es irgendwo in der oberen linken Ecke der Szene. Danach sieht das
Inspektorfenster des
Guard- Objekts folgendermaßen aus:
Abbildung 18: Schutzobjekt im InspektorfensterUnd dieses Objekt sollte so lokalisiert sein:
Abbildung 19: Platzierung des Guard- Objekts.Schließlich benötigen wir ein Objekt, das als „Auge“ des
Guard- Objekts verwendet wird und das den
Guard benachrichtigt, dass der Spieler es berührt. Gehen Sie zum letzten Mal zum
Hierarchiefenster und wählen Sie
Erstellen → 3D-Objekt → Kugel , um ein weiteres
Kugelobjekt zu erstellen. Nennen Sie dieses Objekt
Looker . Dieses Mal müssen wir keine weiteren Komponenten hinzufügen. Wir werden jedoch die Größe des Objekts ändern. Ändern Sie nach Auswahl von
Looker die folgenden Variablen der
Transformationskomponente im
Inspektorfenster .
- Skaliere X bei 9.
- Skala Y bei 0,5.
- Skala Z bei 9.
Positionieren Sie den
Looker danach so, dass er sich im mittleren oberen Teil des Bodens befindet (siehe Abbildung 20).
Abbildung 20: Position des Lookers.Es ist der richtige Zeitpunkt,
Looker ein einzigartiges Material zu geben, damit Sie sehen können, dass es sich lohnt, es zu vermeiden. Klicken Sie im Ordner "
Materialien " des Fensters "
Assets" mit der rechten Maustaste und erstellen Sie ein neues Material. Nennen Sie es
Looker und geben Sie ihm eine leuchtend rote Farbe. Legen Sie danach dieses Material als Material des
Looker- Objekts fest, um seine Farbe zu ändern. Danach sollte die Szene folgendermaßen aussehen:
Abbildung 21: Looker- Objekt mit neuem Material.Wir müssen nur noch ein Navigationsnetz für die
Wache erstellen, auf dem sie sich bewegen kann. Oben im Unity-Editor befindet sich ein
Fenstermenü . Wählen Sie
Fenster → Navigation , um das in Abbildung 22 gezeigte
Navigationsfenster zu öffnen.
Abbildung 22: NavigationsfensterWählen Sie das
Bodenobjekt in der
Hierarchie aus und
aktivieren Sie dann im
Navigationsfenster das Kontrollkästchen
Navigationsstatik .
Abbildung 23: NavigationsstatikWählen Sie als Nächstes oben im Fenster die Option Backen.
Abbildung 24: Wechseln Sie zum Menü Backen .Das Menü
Backen wird geöffnet, in dem Sie die Eigenschaften des Navigationsnetzes ändern können, das wir erstellen möchten. In unserem Beispiel muss nichts geändert werden. Klicken Sie einfach unten rechts auf die Schaltfläche
Backen .
Abbildung 25: Erstellen eines neuen NavigationsnetzesAn dieser Stelle werden Sie von Unity aufgefordert, die Szene zu speichern. Speichern Sie es, woraufhin ein Navigationsnetz erstellt wird. Jetzt sieht die Szene folgendermaßen aus:
Abbildung 26: Die aktuelle Szene mit dem hinzugefügten Navigationsnetz.Jetzt ist alles in Unity konfiguriert, sodass es Zeit ist, die Skripte zu erstellen, die für das Funktionieren des Projekts 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 SkriptsDanach sieht der Ordner "
Skripte " im Fenster "
Assets " folgendermaßen aus:
Abbildung 28: SkriptordnerZuerst schreiben wir den
Player- Skriptcode. Doppelklicken Sie im Fenster "
Assets" auf das
Player- Skript, um Visual Studio zu öffnen und den Code zu erstellen.
Code
Das
Player- Skript ist recht einfach. Der Benutzer kann lediglich das Ballobjekt bewegen. Unter der Klassendeklaration benötigen wir einen Link zu der
Rigidbody- Komponente, die wir zuvor im Projekt erstellt haben.
private Rigidbody rb;
Unmittelbar danach befehlen wir in der
Startfunktion Unity, die aktuelle
Rigidbody- Komponente des
Player- Objekts auf
rb zu setzen .
rb = GetComponent<Rigidbody>();
Danach sieht das
Player- Skript folgendermaßen aus:
Abbildung 29: Player- Skript im Moment.Nachdem der
rb- Wert zugewiesen wurde, müssen wir das
Player- Objekt bewegen lassen, wenn wir die Pfeiltasten drücken. Um das Objekt zu bewegen, verwenden wir Physik und üben Kraft auf das Objekt aus, wenn der Benutzer die Pfeiltasten drückt. Fügen Sie dazu einfach den folgenden Code zur
Update- Funktion 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);
Damit haben wir das
Player- Skript fertiggestellt. Das fertige Skript sieht folgendermaßen aus:
Abbildung 30: Das fertige Player- Skript.Speichern Sie Ihre Arbeit und kehren Sie zu Unity zurück. Wählen Sie dieses Mal das
Guard- Skript im Fenster "
Assets" aus. Damit der
Guard- Code funktioniert, müssen Sie das using-Konstrukt oben im Skript hinzufügen.
using UnityEngine.AI;
Deklarieren Sie als Nächstes die folgenden Variablen unmittelbar nach der Klassendeklaration.
public GameObject player; private NavMeshAgent navmesh;
Das
Player- Objekt wird als Wert der
Player- Variablen des
Guard- Objekts verwendet. Es wird später nützlich sein, wenn wir dem
Guard- Objekt befehlen, den Spieler zu jagen. Anschließend wird die Variable
navmesh deklariert , um die
NavMeshAgent- Komponente des Objekts zu empfangen. Wir werden es später verwenden, wenn der
Wächter beginnt, den Spieler zu jagen, nachdem er erfahren hat, dass der Spieler das
Looker- Objekt berührt. In der
Startfunktion müssen wir den Wert der Variablen
navmesh auf die Komponente
NavMesh Agent des Objekts setzen:
navmesh = GetComponent<NavMeshAgent>();
Dann fügen wir in der
Update- Funktion eine einzelne Codezeile hinzu:
navmesh.destination = player.transform.position;
Diese Zeile legt das Ziel für das
Guard- Objekt fest. In unserem Fall nimmt es die aktuelle Position des
Player- Objekts ein und bewegt sich zu diesem Punkt. Nach der Operation verfolgt das Objekt den Spieler ständig. Die Frage ist, wie der Antwortprozess 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: Das fertige Guard- Skript.In
Looker müssen wir erneut die folgenden Variablen deklarieren:
public GameObject guard; private float reset = 5; private bool movingDown;
Danach kommentieren wir die
Startfunktion , die wir in diesem Skript nicht benötigen. Fahren wir mit der
Update- Funktion fort und fügen 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 Hauptaktionen des Projekts statt. Analysieren wir also den Code. Erstens wird das Objekt, an das dieses Skript angehängt ist, abhängig vom Wert der booleschen Variablen
moveDown nach oben oder unten verschoben. Sobald er einen bestimmten Punkt erreicht, ändert er die Richtung. Als nächstes
senkt Looker den Rücksetzwert basierend auf der Echtzeit. Sobald der Timer kleiner als Null wird, nimmt er das
Guard- Skript aus dem
Guard- Objekt und deaktiviert es. Danach bewegt sich das
Guard- Objekt bis zu diesem Moment an die letzte bekannte Position des Spielers und stoppt dann.
Looker schaltet auch seinen Collider wieder ein, damit der gesamte Prozess von vorne beginnen kann. Jetzt sieht unser Skript so aus:
Abbildung 32: Looker- SkriptApropos Collider: Es ist Zeit, einen Konfliktcode zu erstellen, der den
Looker- Timer zurücksetzt und das
Guard- Skript enthält. Erstellen Sie in der
Update- Funktion 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 es automatisch als Kollisionscode und führt es daher aus, wenn eine Kollision mit einem anderen Objekt auftritt. In unserem Fall wird zunächst geprüft, ob das kollidierende Objekt ein
Player- Tag hat. Wenn nicht, wird der Rest des Codes ignoriert. Andernfalls wird das
Guard- Skript aktiviert, der
Rücksetz- Timer auf 5 (d. H. Fünf Sekunden) gesetzt und der Collider deaktiviert, sodass sich der Player weiterhin durch das Objekt bewegen kann und nicht versehentlich im
Looker- Objekt stecken bleibt. Die Funktion ist in Abbildung 33 dargestellt.
Abbildung 33: Kollisionscode für Looker
Das ist alles, was der Projektcode fertig ist! Sie können noch ein paar Dinge tun, bevor Sie das Projekt beenden. Speichern Sie die gesamte Arbeit und kehren Sie zu Unity zurück.
Projektabschluss
Um das Projekt abzuschließen, müssen wir nur Skripte an die entsprechenden Objekte anhängen und mehrere Variablen festlegen. Wechseln Sie zunächst vom
Navigationsfenster zum
Inspektorfenster :
Abbildung 34: Übergang zum Inspektorfenster
Beginnen wir danach mit dem
Player- Objekt. Wählen Sie es im
Hierarchiefenster aus, klicken Sie unten im
Inspektorfenster auf die Schaltfläche
Komponente hinzufügen und fügen Sie das
Player- Skript hinzu. Damit ist das
Player- Objekt abgeschlossen.
Abbildung 35: Player-
SkriptkomponenteWählen Sie als Nächstes das
Guard- Objekt aus. Hängen Sie wie zuvor das
Guard- Skript an das Objekt an. Dieses Mal müssen wir der
Wache sagen, 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: Das Player- Objekt zum Wert des Player- Felds machen.Wir müssen auch das
Guard- Skript deaktivieren. In unserem Projekt wird
Guard den Spieler verfolgen, nachdem er sein Skript eingeschaltet hat. Dieses
Guard- Skript sollte erst enthalten sein, nachdem der Player das
Looker- Objekt berührt hat. Alles, was Sie tun müssen, ist das Kontrollkästchen neben dem
Guard- Text
(Skript) in der Komponente zu deaktivieren:
Abbildung 37: Deaktivieren des Guard- SkriptsLassen Sie uns abschließend zum
Looker- Objekt
übergehen und das
Looker- Skript daran anhängen. Dieses Mal benötigt das
Looker- Objekt ein
Guard- Objekt als Wert seiner
Guard- Variablen. So wie wir das
Player- Objekt der
Player- Variablen des
Guard- Skripts zugewiesen haben, werden wir dasselbe mit dem
Guard- Objekt und dem
Looker- Skript tun. Ziehen Sie den
Guard aus der
Hierarchie in das
Guard- Feld des
Looker- Skripts. Und das Projekt ist abgeschlossen! Klicken Sie oben im Unity-Editor auf die Schaltfläche Wiedergabe, um Ihr Projekt zu testen.
Abbildung 38: Testen eines ProjektsVersuchen Sie, das
Player- Objekt in das
Looker- Objekt zu verschieben (denken Sie daran, dass das Verschieben mit Pfeilen erfolgt!). Beachten Sie, dass das
Guard- Objekt danach beginnt, den Spieler zu verfolgen. Er wird die Verfolgung für ungefähr 5 Sekunden fortsetzen, danach wird er aufgeben.
Abbildung 39: Ein vollständig abgeschlossenes Projekt in Aktion.Fazit
Diese KI ist sehr einfach, kann aber leicht erweitert werden. 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 zu geben. Der Spieler kann sich den Kameras nähern, muss jedoch die Augen des Wächters berücksichtigen. Sie können dieses Projekt auch mit dem
Konzept kombinieren
, den 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 solch einfache KI kann auf viele verschiedene Arten entwickelt werden. Möglicherweise möchten Sie nichts von alledem tun und sich dazu entschließen, etwas Eigenes zu tun. Ich rate Ihnen zu experimentieren, vielleicht haben Sie die Idee eines interessanten Projekts, das es wert ist, zum Ende gebracht zu werden.