Erstellen einfacher KI-Interaktionen mit Umgebungsobjekten


Bei der Erstellung künstlicher Intelligenz für Videospiele ist der Standort einer der wichtigsten Aspekte. Die Position des KI-Charakters kann seine Verhaltensweisen und zukünftigen Entscheidungen vollständig verändern. In diesem Tutorial werden wir verstehen, wie sich die Spielumgebung auf die KI auswirken kann und wie man sie richtig verwendet.

Dieser Artikel stammt aus dem Buch Practical Game AI Programming , das von Michael Dagrack geschrieben und von Packt Publishing veröffentlicht wurde. In diesem Buch erfahren Sie, wie Sie eine Spiel-KI erstellen und die fortschrittlichsten KI-Algorithmen von Grund auf neu implementieren.

Visuelle Interaktionen sind grundlegend, sie wirken sich nicht direkt auf das Gameplay aus, aber Sie können das Videospiel und seine Charaktere verbessern, indem Sie sie zu einem Teil der von uns erstellten Umgebung machen, was das Eintauchen des Spielers in das Spiel stark beeinflusst. Dies zeigt uns, wie wichtig es ist, dass die Umgebung Teil des Spiels ist und nicht nur dazu beiträgt, den Platz auf dem Bildschirm auszufüllen. Ähnliche Interaktionen finden sich zunehmend in Spielen, und die Spieler erwarten, sie zu sehen. Wenn es ein Objekt im Spiel gibt, muss es eine Funktion erfüllen, wenn auch nicht die wichtigste.

Eines der ersten Beispiele für die Interaktion mit Umgebungen ist das erste Castlevania, das 1986 für das Nintendo Entertainment System veröffentlicht wurde. Von Anfang an kann der Spieler mit der Peitsche Kerzen und Feuer zerstören, die ursprünglich Teil des Hintergrunds waren.


Dieses und einige Spiele dieser Zeit eröffneten viele Türen und Möglichkeiten in Bezug auf die moderne Wahrnehmung der Hintergründe und Umgebungen der Charaktere im Spiel. Aufgrund der Hardwarebeschränkungen dieser Konsolengeneration war es offensichtlich viel schwieriger, einfache Dinge zu erstellen, die von den aktuellen Standards allgemein akzeptiert werden. Aber jede Generation von Konsolen brachte neue Funktionen mit und Entwickler verwendeten sie, um erstaunliche Spiele zu erstellen.

Unser erstes Beispiel für visuelle Interaktion ist also ein Objekt im Hintergrund, das zerstört werden kann, ohne das Gameplay direkt zu beeinflussen. Diese Art der Interaktion findet man in vielen Spielen. Die Implementierung ist einfach. Animieren Sie das Objekt nur, wenn es angegriffen wird. Danach können wir entscheiden, ob Punkte oder Objekte von dem Objekt entfernt werden sollen, die den Spieler für die Erkundung des Spiels belohnen.

Jetzt können wir mit dem nächsten Beispiel fortfahren - Objekten im Spiel, die animiert sind oder sich bewegen, wenn Charaktere sie passieren. Das Prinzip ist hier dasselbe wie bei zerstörbaren Objekten, aber diesmal ist die Interaktion subtiler - der Charakter muss sich zu dem Punkt bewegen, an dem sich das Objekt befindet. Dies kann auf verschiedene Elemente des Spiels angewendet werden, von der Bewegung von Gras, Staub oder Wasser bis hin zu fliegenden Vögeln oder Menschen, die lustige Gesten machen. Die Möglichkeiten sind endlos.

Bei der Analyse dieser Interaktionen können wir leicht feststellen, dass sie nicht unbedingt KI verwenden. In den meisten Fällen handelt es sich nur um eine Boolesche Funktion, die gemäß einer bestimmten Aktion aktiviert wird. Sie sind jedoch Teil der Umgebung und sollten daher bei der Implementierung einer qualitativ hochwertigen Interaktion zwischen Umgebung und KI berücksichtigt werden.

Erstellen Sie einfache Interaktionen mit der Umgebung


Wie wir bereits gesehen haben, wurde die Umgebung einst Teil des Gameplays, und dies führte zu vielen neuen Konzepten und Ideen für zukünftige Spiele. Der nächste Schritt war die Integration dieser kleinen Änderungen in das Gameplay und ihre Verwendung, um das Verhalten des Spielers im Spiel zu ändern. Dies wirkte sich definitiv positiv auf die Geschichte der Videospiele aus, da alle Elemente der Szene allmählich zum Leben erweckt wurden und der Spieler erkannte, wie reich die Umgebung war. Die Verwendung von Umgebungen zum Erreichen von Zielen im Spiel ist Teil des Gameplays geworden.


Um ein Beispiel für eine Umgebung zu demonstrieren, die sich direkt auf das Gameplay auswirkt, nehmen wir ein hervorragendes Beispiel - das Tomb Raider-Franchise. In diesem Beispiel muss unsere Figur Lara Croft den Würfel schieben, bis er auf dem markierten Bereich landet. Dies wird die Umgebung verändern und einen neuen Pfad eröffnen, so dass sich der Spieler weiter im Level bewegen kann.

Solche Rätsel gibt es in vielen Spielen: Sie müssen eine Aktion an einem bestimmten Punkt auf der Karte ausführen, damit in einem anderen Teil etwas passiert, und dies kann verwendet werden, um ein bestimmtes Ziel im Spiel zu erreichen. Normalerweise müssen wir die Umgebung selbst ändern, um das Niveau weiter zu verbessern. Wenn Entwickler eine Karte oder Ebene planen, berücksichtigen sie dies und erstellen alle Regeln für jede Interaktion. Zum Beispiel:

if(cube.transform.position == mark.transform.position)
{
  openDoor = true;
}

Stellen Sie sich jetzt für einen Moment vor, dass Lara Croft einen Verbündeten hat, dessen Hauptaufgabe es ist, ihr zu helfen, diese Kiste an ihre Stelle zu setzen. Und in diesem Kapitel werden wir genau diese Art der Interaktion betrachten: Der KI-Charakter versteht, wie die Umgebung funktioniert und wie man sie verwendet.

Bewegliche Umgebung in Tomb Raider


Gehen wir direkt zu diesem Szenario und versuchen, eine Situation nachzubilden, in der es einen KI-Charakter gibt, der dem Spieler helfen kann, sein Ziel zu erreichen. In diesem Beispiel stellen wir uns vor, dass ein Spieler gefangen ist, von dem er keinen Zugriff auf ein interaktives Objekt erhält, das ihn befreien kann. Der Charakter, den wir erstellen, muss in der Lage sein, den Würfel zu finden und in die richtige Richtung zu schieben.


Jetzt haben wir also alle Charaktere und Objekte. Lassen Sie uns planen, wie sich der KI-Charakter in dieser Situation verhalten soll. Zuerst sollte er sehen, dass der Spieler in der Nähe ist, damit er beginnen kann, den Würfel zu suchen und an die gewünschte Position zu bewegen. Angenommen, wenn sich der Würfel an der Markierung befindet, erscheint ein neuer Block aus dem Sand, der es dem Spieler ermöglicht, weiter im Level voranzukommen. Ein KI-Charakter kann einen Würfel in vier Richtungen schieben: links, rechts, vorwärts und rückwärts, so dass er perfekt zur Positionsmarkierung passt.


Der KI-Charakter muss jede in diesem Verhaltensbaum angezeigte Aktion überprüfen und validieren. Das erste und wichtigste für die Fortsetzung der Aufgabe ist, dass der Charakter sicher sein muss, dass sich der Spieler auf seiner Marke befindet.

Wenn der Spieler dort noch nicht angekommen ist, muss unser Charakter warten und an Ort und Stelle bleiben. Wenn der Spieler bereits an der Marke angekommen ist, setzt der KI-Charakter die Ausführung fort und fragt sich, wie weit er vom Würfelobjekt entfernt ist. Wenn nicht, sollte sich der Charakter in Richtung des Würfels bewegen und sobald diese Aktion bestätigt ist, sollte er dieselbe Frage stellen. Wenn die Antwort positiv wird und sich der Charakter neben dem Würfel befindet, muss er herausfinden, in welche Richtung Sie den Würfel zuerst schieben müssen.

Dann beginnt er, den Würfel entlang der Y- oder X-Achse zu schieben, bis er mit der Markierungsposition übereinstimmt und die Aufgabe abgeschlossen ist.

public GameObject playerMesh;
public Transform playerMark;
public Transform cubeMark;
public Transform currentPlayerPosition;
public Transform currentCubePosition;

public float proximityValueX;
public float proximityValueY;
public float nearValue;

private bool playerOnMark;


void Start () {

}

void Update () {

  // Calculates the current position of the player
  currentPlayerPosition.transform.position = playerMesh.transform.position;

  // Calculates the distance between the player and the player mark of the X axis
  proximityValueX = playerMark.transform.position.x - currentPlayerPosition.transform.position.x;

  // Calculates the distance between the player and the player mark of the Y axis
  proximityValueYplayerMark.transform.position.y - currentPlayerPosition.transform.position.y;

  // Calculates if the player is near of his MARK POSITION
  if((proximityValueX + proximityValueY) < nearValue)
  {
     playerOnMark = true;
  }
}

Wir beginnen, dem Code Informationen hinzuzufügen, mit denen der Charakter überprüfen kann, ob sich der Spieler neben seiner markierten Position befindet. Dazu erstellen wir alle Variablen, die zur Berechnung der Abstände zwischen dem Spieler und der Position, in der er sich befinden sollte, erforderlich sind. playerMeshbezieht sich auf das 3D-Modell des Spielers, aus dem wir seine Position extrahieren und als verwenden currentPlayerPosition.

Um zu wissen, ob es nahe an der Marke liegt, benötigen wir eine Variable, die die Position der Marke darstellt. In unserem Beispiel haben wir eine Variable erstellt, playerMarkin die wir die Position schreiben können, an der sich der Spieler befinden soll. Dann haben wir drei Variablen hinzugefügt, die uns mitteilen, ob der Spieler in der Nähe ist. proximityValueXberechnet den Abstand zwischen dem Spieler und der X-Achsen-Markierung. proximityValueYBerechnet den Abstand zwischen dem Spieler und der Y-Achsen-Markierung.

Als nächstes haben wir nearValue, in dem wir bestimmen können, wie weit der Spieler von der Position der Marke entfernt sein kann, wenn der KI-Charakter beginnen kann, an der Erreichung des Ziels zu arbeiten. Sobald sich der Spieler der Marke nähert, playerOnMarkändert die Boolesche Variable den Wert in true.

Um den Abstand zwischen dem Spieler und der Marke zu berechnen, haben wir Folgendes verwendet: den Abstand zwischen dem Spieler und seiner Marke, ähnlich (mark.position - player.position).

Um festzustellen, ob sich das AI-Zeichen in der Nähe des Würfels befindet, berechnen wir dieselbe Gleichung, indem wir den Abstand zwischen der AI und dem Würfel berechnen. Zusätzlich haben wir den Code mit Positionen auf beiden Markierungen (Spieler und Würfel) ergänzt:

public GameObject playerMesh;
public Transform playerMark;
public Transform cubeMark;
public Transform currentPlayerPosition;
public Transform currentCubePosition;

public float proximityValueX;
public float proximityValueY;
public float nearValue;

public float cubeProximityX;
public float cubeProximityY;
public float nearCube;

private bool playerOnMark;
private bool cubeIsNear;


void Start () {

   Vector3 playerMark = new Vector3(81.2f, 32.6f, -31.3f);
   Vector3 cubeMark = new Vector3(81.9f, -8.3f, -2.94f);
   nearValue = 0.5f;
   nearCube = 0.5f;
}

void Update () {

  // Calculates the current position of the player
  currentPlayerPosition.transform.position = playerMesh.transform.position;

  // Calculates the distance between the player and the player mark of the X axis
  proximityValueX = playerMark.transform.position.x - currentPlayerPosition.transform.position.x;

  // Calculates the distance between the player and the player mark of the Y axis
  proximityValueY = playerMark.transform.position.y - currentPlayerPosition.transform.position.y;

  // Calculates if the player is near of his MARK POSITION
  if((proximityValueX + proximityValueY) < nearValue)
  {
     playerOnMark = true;
  }

  cubeProximityX = currentCubePosition.transform.position.x - this.transform.position.x;
  cubeProximityY = currentCubePosition.transform.position.y - this.transform.position.y;

  if((cubeProximityX + cubeProximityY) < nearCube)
  {
     cubeIsNear = true;
  }

  else
  {
     cubeIsNear = false;
  }
}

Jetzt, da unser KI-Charakter weiß, ob er sich neben dem Würfel befindet, können wir die Frage beantworten und feststellen, ob er zum nächsten von uns geplanten Zweig übergehen kann. Aber was passiert, wenn sich der Charakter nicht neben dem Würfel befindet? Er muss sich dem Würfel nähern. Deshalb werden wir dies dem Code hinzufügen:

public GameObject playerMesh;
public Transform playerMark;
public Transform cubeMark;
public Transform cubeMesh;
public Transform currentPlayerPosition;
public Transform currentCubePosition;

public float proximityValueX;
public float proximityValueY;
public float nearValue;

public float cubeProximityX;
public float cubeProximityY;
public float nearCube;

private bool playerOnMark;
private bool cubeIsNear;

public float speed;
public bool Finding;


void Start () {

   Vector3 playerMark = new Vector3(81.2f, 32.6f, -31.3f);
   Vector3 cubeMark = new Vector3(81.9f, -8.3f, -2.94f);
   nearValue = 0.5f;
   nearCube = 0.5f;
   speed = 1.3f;
}

void Update () {

  // Calculates the current position of the player
  currentPlayerPosition.transform.position = playerMesh.transform.position;

  // Calculates the distance between the player and the player mark of the X axis
  proximityValueX = playerMark.transform.position.x - currentPlayerPosition.transform.position.x;

  // Calculates the distance between the player and the player mark of the Y axis
  proximityValueY = playerMark.transform.position.y - currentPlayerPosition.transform.position.y;

  // Calculates if the player is near of his MARK POSITION
  if((proximityValueX + proximityValueY) < nearValue)
  { 
      playerOnMark = true;
  }

  cubeProximityX = currentCubePosition.transform.position.x - this.transform.position.x;
  cubeProximityY = currentCubePosition.transform.position.y - this.transform.position.y;

  if((cubeProximityX + cubeProximityY) < nearCube)
  {
      cubeIsNear = true;
  }

  else
  {
      cubeIsNear = false;
  }

  if(playerOnMark == true && cubeIsNear == false && Finding == false)
  {
     PositionChanging();
  }

  if(playerOnMark == true && cubeIsNear == true)
  {
     Finding = false;
  }

}

void PositionChanging () {

  Finding = true;
  Vector3 positionA = this.transform.position;
  Vector3 positionB = cubeMesh.transform.position;
  this.transform.position = Vector3.Lerp(positionA, positionB, Time.deltaTime * speed);
}

Bisher kann unser KI-Charakter die Entfernung zwischen sich und dem Würfel berechnen. Wenn sie zu weit voneinander entfernt sind, geht er zum Würfel. Nach Abschluss dieser Aufgabe kann er mit der nächsten Phase fortfahren und den Würfel schieben. Als letztes muss er berechnen, wie weit der Würfel von der Position der Marke entfernt ist. Danach entscheidet er, in welche Richtung er schieben soll, wobei er berücksichtigt, auf welcher Seite des Würfels sich die Marke befindet.


Der Würfel kann nur entlang der X- und Z-Achse geschoben werden, und seine Drehung ist für uns noch nicht wichtig, da die Schaltfläche aktiviert wird, wenn der Würfel darauf installiert ist. In Anbetracht dessen muss der KI-Charakter berechnen, wie weit der Würfel von der Position der Markierung auf X und der Position der Markierung auf Z entfernt ist.

Dann vergleicht er die beiden Werte auf den beiden Achsen und wählt aus, welche weiter von der gewünschten Position entfernt ist, und beginnt dann, diese zu verschieben Achse. Der Charakter drückt weiter in diese Richtung, bis der Würfel an der Position der Marke ausgerichtet ist, wechselt dann zur anderen Seite und drückt ihn, bis er vollständig über der Position der Marke liegt:

public GameObject playerMesh;
public Transform playerMark;
public Transform cubeMark;
public Transform cubeMesh;
public Transform currentPlayerPosition;
public Transform currentCubePosition;

public float proximityValueX;
public float proximityValueY;
public float nearValue;

public float cubeProximityX;
public float cubeProximityY;
public float nearCube;

public float cubeMarkProximityX;
public float cubeMarkProximityZ;

private bool playerOnMark;
private bool cubeIsNear;

public float speed;
public bool Finding;


void Start () {

        Vector3 playerMark = new Vector3(81.2f, 32.6f, -31.3f);
        Vector3 cubeMark = new Vector3(81.9f, -8.3f, -2.94f);
        nearValue = 0.5f;
        nearCube = 0.5f;
        speed = 1.3f;
}

void Update () {

  // Calculates the current position of the player
  currentPlayerPosition.transform.position = playerMesh.transform.position;

  // Calculates the distance between the player and the player mark of the X axis
  proximityValueX = playerMark.transform.position.x - currentPlayerPosition.transform.position.x;

  // Calculates the distance between the player and the player mark of the Y axis
  proximityValueY = playerMark.transform.position.y - currentPlayerPosition.transform.position.y;

  // Calculates if the player is near of his MARK POSITION
  if((proximityValueX + proximityValueY) < nearValue)
  {
     playerOnMark = true;
  }

  cubeProximityX = currentCubePosition.transform.position.x - this.transform.position.x;
  cubeProximityY = currentCubePosition.transform.position.y - this.transform.position.y;

  if((cubeProximityX + cubeProximityY) < nearCube)
  {
     cubeIsNear = true;
  }

  else
  {
     cubeIsNear = false;
  }

  if(playerOnMark == true && cubeIsNear == false && Finding == false)
  {
      PositionChanging();
  }

  if(playerOnMark == true && cubeIsNear == true)
  {
      Finding = false;
    }

   cubeMarkProximityX = cubeMark.transform.position.x - currentCubePosition.transform.position.x;
   cubeMarkProximityZ = cubeMark.transform.position.z - currentCubePosition.transform.position.z;

   if(cubeMarkProximityX > cubeMarkProximityZ)
   {
     PushX();
   }

   if(cubeMarkProximityX < cubeMarkProximityZ)
   {
     PushZ();
   }

}

void PositionChanging () {

  Finding = true;
  Vector3 positionA = this.transform.position;
  Vector3 positionB = cubeMesh.transform.position;
  this.transform.position = Vector3.Lerp(positionA, positionB, Time.deltaTime * speed);
}

Nach dem Hinzufügen der neuesten Aktionen zum Code muss der Charakter lernen, sein Ziel zu bestimmen, den Würfel zu finden und an die gewünschte Position zu schieben, damit der Spieler das Level durchlaufen und beenden kann. In diesem Beispiel haben wir uns darauf konzentriert, wie Entfernungen zwischen Szenenobjekten und Charakteren berechnet werden. Dies wird uns helfen, ähnliche Arten von Interaktionen zu erstellen, bei denen wir das Spielobjekt an einer bestimmten Position platzieren müssen.

Das Beispiel zeigt einen freundlichen KI-Charakter, der dem Spieler hilft, aber die gleichen Prinzipien können angewendet werden, wenn wir den gegenteiligen Effekt benötigen (wenn der Charakter ein Feind ist), bei dem der Charakter den Würfel so schnell wie möglich finden muss, um den Spieler zu stoppen.

Hindernisobjekte in Umgebungen am Beispiel von Age of Empires


Wie wir bereits gesehen haben, können Sie Objekte im Spiel verwenden oder verschieben, um Ziele zu erreichen. Was passiert jedoch, wenn ein Objekt den Weg des Charakters blockiert? Das Objekt kann vom Spieler platziert oder einfach vom Designer an dieser Position der Karte platziert werden. In jedem Fall sollte der KI-Charakter bestimmen können, was in dieser Situation zu tun ist.

Wir können dieses Verhalten beispielsweise in einer Strategie namens Age of Empires II beobachten, die von Ensemble Studios entwickelt wurde. Jedes Mal, wenn ein Spielcharakter das feindliche Gebiet nicht erreichen kann, weil er von befestigten Mauern umgeben ist, wechselt die KI dazu, einen Teil der Mauer zu zerstören, um weiterzumachen.

Diese Art der Interaktion ist auch sehr klug und wichtig, da die Charaktere sonst nur auf der Suche nach einem Eingang an der Wand entlang wandern würden und dies nicht nach vernünftigem Verhalten aussehen würde. Da die verstärkte Wand vom Spieler erstellt wird, kann sie überall platziert werden und jede Form haben. Daher müssen Sie bei der Entwicklung einer feindlichen KI darüber nachdenken.


Dieses Beispiel bezieht sich auch auf das Thema unseres Artikels, da wir in der Planungsphase beim Erstellen von Verhaltensbäumen darüber nachdenken müssen, was passieren wird, wenn etwas dem Charakter im Weg steht und er seine Ziele nicht erreichen kann. Wir werden diesen Aspekt in den folgenden Kapiteln des Buches ausführlich betrachten, aber jetzt vereinfachen wir die Situation und analysieren, wie sich der KI-Charakter verhalten soll, wenn das Umgebungsobjekt ihn daran hindert, sein Ziel zu erreichen.


In unserem Beispiel muss der KI-Charakter das Haus betreten, aber als er sich nähert, stellt er fest, dass er von einem Holzzaun umgeben ist, durch den Sie nicht gehen können. Wir möchten, dass der Charakter zu diesem Zeitpunkt ein Ziel auswählt und angreift, bis dieser Teil des Zauns zerstört ist und er das Haus betreten kann.

In diesem Beispiel müssen wir berechnen, welchen Zaun der Charakter angesichts der Entfernung und des aktuellen Gesundheitszustands des Zauns angreifen soll. Ein Zaun mit niedrigen HP sollte eine höhere Priorität für Angriffe haben als ein Zaun mit vollen HP, daher werden wir dies in unseren Berechnungen berücksichtigen.


Wir wollen die Nachbarschaft um den Charakter herum festlegen, in der die nächsten Zäune ihre Informationen an künstliche Intelligenz übertragen, damit sie entscheiden können, welche leichter zu zerstören ist. Dies kann auf verschiedene Arten implementiert werden, entweder durch Erkennen von Kollisionen von Zäunen mit dem Spieler oder durch Erzwingen der Berechnung des Abstands zwischen Zäunen / Objekten und dem Spieler. Wir legen den Wert der Entfernung fest, ab der der Spieler den Zustand des Zauns wahrnimmt. In unserem Beispiel berechnen wir die Entfernung und verwenden sie, um den Charakter über HP Zäune zu informieren.

Beginnen wir mit der Erstellung des Codes, der auf das Zaunobjekt angewendet wird. Alle haben das gleiche Skript:

public float HP;
public float distanceValue;
private Transform characterPosition;
private GameObject characterMesh;

private float proximityValueX;
private float proximityValueY;
private float nearValue;

// Use this for initialization
void Start () {

  HP = 100f;
  distanceValue = 1.5f;

  // Find the Character Mesh
  characterMesh = GameObject.Find("AICharacter");
}

// Update is called once per frame
void Update () {

  // Obtain the Character Mesh Position
  characterPosition = characterMesh.transform;

  //Calculate the distance between this object and the AI Character
  proximityValueX = characterPosition.transform.position.x - this.transform.position.x;
  proximityValueY = characterPosition.transform.position.y - this.transform.position.y;

  nearValue = proximityValueX + proximityValueY;
}

In diesem Skript haben wir grundlegende Informationen zu HP und Entfernungen hinzugefügt, die zur Verbindung mit dem KI-Charakter verwendet werden. Dieses Mal fügen wir das Skript zur Entfernungsberechnung nicht dem Zeichen, sondern den Umgebungsobjekten hinzu. Dies gibt dem Objekt mehr Dynamik und ermöglicht es uns, mehr Möglichkeiten zu schaffen.

Wenn die Charaktere des Spiels beispielsweise auch Zäune bauen, haben sie unterschiedliche Zustände, z. B. "im Bau", "abgeschlossen" oder "beschädigt". dann kann der Charakter diese Informationen empfangen und für seine eigenen Zwecke verwenden.

Lassen Sie uns den Charakter so einstellen, dass er mit dem Umgebungsobjekt interagiert. Sein Hauptziel wird es sein, Zugang zum Haus zu erhalten, aber als er sich ihm nähert, stellt er fest, dass er nicht hineinkommen kann, weil er von Holzzäunen umgeben ist. Wir wollen, dass unser Charakter, nachdem er die Situation analysiert hat, den Zaun zerstört, um sein Ziel zu erreichen und ins Haus zu gelangen.

Im Charakterskript fügen wir eine statische Funktion hinzu, zu deren Eingabe Zäune Informationen über ihre aktuelle "Gesundheit" übertragen können. Dies wird dem Charakter helfen, den am besten geeigneten Zaun für die Zerstörung auszuwählen.

public static float fenceHP;
public static float lowerFenceHP;
public static float fencesAnalyzed;
public static GameObject bestFence;

private Transform House;

private float timeWasted;
public float speed;



void Start () {

        fenceHP = 100f;
        lowerFenceHP = fenceHP;
        fencesAnalyzed = 0;
        speed = 0.8;

        Vector3 House = new Vector3(300.2f, 83.3f, -13.3f);

}

void Update () {

        timeWasted += Time.deltaTime;

        if(fenceHP > lowerFenceHP)
        {
            lowerFenceHP = fenceHP;
        }

        if(timeWasted > 30f)
        {
            GoToFence();  
        }
}

void GoToFence() {

        Vector3 positionA = this.transform.position;
        Vector3 positionB = bestFence.transform.position;
        this.transform.position = Vector3.Lerp(positionA, positionB, Time.deltaTime * speed);
}


Wir haben dem Charakter bereits die grundlegendsten Informationen hinzugefügt. fenceHPwird eine statische Variable sein, bei der jeder Zaun, der in den Radius der Nachbarschaft des Charakters fällt, Informationen über die aktuellen HP aufzeichnet. Dann analysiert der KI-Charakter die empfangenen Informationen und vergleicht sie mit dem Zaun mit den geringsten präsentierten HP lowerFenceHP.

Der Charakter hat eine Variable, timeWasteddie die Anzahl der Sekunden darstellt, die er bereits auf der Suche nach einem geeigneten Zaun zur Zerstörung verbracht hat. fencesAnalyzedwird verwendet, um herauszufinden, ob der Code bereits einen Zaun enthält, und wenn nicht, wird der erste vom Charakter gefundene Zaun hinzugefügt. Falls Zäune den gleichen HP-Wert haben, greift der Charakter sie zuerst an. Fügen wir nun den Code der Zäune hinzu, damit sie auf das Skript des Charakters zugreifen und nützliche Informationen eingeben können.

public float HP;
public float distanceValue;
private Transform characterPosition;
private GameObject characterMesh;

private float proximityValueX;
private float proximityValueY;
private float nearValue;
void Start () {

        HP = 100f;
        distanceValue = 1.5f;

        // Find the Character Mesh
        characterMesh = GameObject.Find("AICharacter");
}

void Update () {

        // Obtain the Character Mesh Position
        characterPosition = characterMesh.transform;

        //Calculate the distance between this object and the AI Character
        proximityValueX = characterPosition.transform.position.x - this.transform.position.x;
        proximityValueY = characterPosition.transform.position.y - this.transform.position.y;

        nearValue = proximityValueX + proximityValueY;

        if(nearValue <= distanceValue){
            if(AICharacter.fencesAnalyzed == 0){
                AICharacter.fencesAnalyzed = 1;
                AICharacter.bestFence = this.gameObject;
            }

            AICharacter.fenceHP = HP;

            if(HP < AICharacter.lowerFenceHP){
                AICharacter.bestFence = this.gameObject;
            }
        }
}

Wir haben dieses Beispiel endlich fertiggestellt. Jetzt vergleicht der Zaun seine aktuellen HP mit den Daten des Charakters ( lowerFenceHP). Wenn seine HP niedriger als der niedrigste Wert des Charakters sind, wird dieser Zaun berücksichtigt bestFence.

Dieses Beispiel zeigt, wie ein KI-Charakter an verschiedene dynamische Objekte im Spiel angepasst wird. Das gleiche Prinzip kann erweitert und verwendet werden, um mit fast jedem Objekt zu interagieren. Es ist auch anwendbar und nützlich, wenn Objekte verwendet werden, um mit einem Charakter zu interagieren und Informationen zwischen ihnen zu verknüpfen.

In diesem Beitrag haben wir verschiedene Arten der Interaktion mit der Umgebung untersucht. Die in diesem Kapitel vorgestellten Techniken können auf viele verschiedene Spielgenres erweitert und zur Durchführung einfacher und komplexer Interaktionen zwischen KI-Charakteren und der Umgebung verwendet werden.

All Articles