Programming lesson
Fuzzy-Logik-Agent für Rennspiele: Umsetzung der CS7632 Aufgabe 7
Lerne, wie du einen Fuzzy-Logik-Agenten für ein Rennspiel in Unity implementierst. Schritt-für-Schritt-Anleitung mit praktischen Tipps zu Fuzzy-Regeln, Metriken und Vermeidung typischer Fehler.
Einführung in Fuzzy-Logik für Rennspiele
In dieser Anleitung lernst du, wie du einen Fuzzy-Logik-Agenten für ein Rennspiel in Unity implementierst. Die Aufgabe stammt aus dem CS7632 Assignment 7 – Race Track. Ziel ist es, einen Truck so schnell wie möglich um eine prozedural generierte Rennstrecke zu steuern, ohne zu crashen oder stecken zu bleiben. Fuzzy Logic eignet sich hervorragend, um unscharfe Sensorwerte wie „Geschwindigkeit ist hoch“ oder „Abstand zur Streckenmitte ist groß“ in präzise Steuerbefehle umzuwandeln.
Grundlagen des Fuzzy-Systems
Das bereitgestellte Fuzzy-Logik-System basiert auf dem Buch „Programming Game AI by Example“ von Mat Buckland. Du definierst linguistische Variablen (z. B. Geschwindigkeit, Abstand zur Streckenmitte) mit Zugehörigkeitsfunktionen (z. B. niedrig, mittel, hoch) und formulierst Fuzzy-Regeln wie „Wenn Geschwindigkeit hoch und Abstand zur Streckenmitte groß, dann Lenkung stark“. Die Regeln werden ausgewertet und zu einem scharfen Wert defuzzifiziert – hier für Gas (Throttle) und Lenkung (Steering).
Metriken für den Fuzzy-Agenten
Dein Agent benötigt sinnvolle Eingabewerte. Nützliche Metriken aus dem PathTracker sind:
- Abstand zur Streckenmitte: Berechne den senkrechten Abstand von der Fahrzeugposition zur nächsten Streckenmitte (closestPointOnPath).
- Geschwindigkeit: Nutze die Eigenschaft
Speedin km/h. - Richtungsabweichung: Der Winkel zwischen Fahrzeugrichtung und der Tangentenrichtung der Strecke (closestPointDirectionOnPath).
- Kurvenkrümmung voraus: Schätze die Krümmung der Strecke in einigen Metern Entfernung, um vorausschauend lenken zu können.
Fuzzy-Variablen definieren
Erstelle für jede Metrik eine Fuzzy-Variable mit passenden Zugehörigkeitsfunktionen. Beispiel für die Geschwindigkeit (in km/h):
public FuzzyVariable GetSpeedVariable() {
FuzzyVariable speed = new FuzzyVariable();
speed.AddTerm("niedrig", new LeftShoulder(0, 30, 50));
speed.AddTerm("mittel", new Triangle(30, 60, 90));
speed.AddTerm("hoch", new RightShoulder(70, 100, 150));
return speed;
}Analog für Abstand zur Streckenmitte (in Metern):
public FuzzyVariable GetDistanceVariable() {
FuzzyVariable dist = new FuzzyVariable();
dist.AddTerm("nah", new LeftShoulder(0, 1, 2));
dist.AddTerm("mittel", new Triangle(1, 3, 5));
dist.AddTerm("weit", new RightShoulder(4, 6, 10));
return dist;
}Die Streckenbreite beträgt 10 Meter (halfRoadWidth = 5), daher sind Abstände bis 5 Meter relevant.
Fuzzy-Regeln für Gas und Lenkung
Definiere Regeln für den Throttle (Gas). Beispiel: Wenn die Geschwindigkeit niedrig ist, soll viel Gas gegeben werden. Wenn die Geschwindigkeit hoch ist, wenig Gas. Hier ein Ausschnitt:
FuzzyRuleSet throttleRules = new FuzzyRuleSet();
throttleRules.AddRule(new FuzzyRule(
new FuzzyRuleCondition(speed, "niedrig"),
new FuzzyRuleConsequent(throttle, "hoch")
));
throttleRules.AddRule(new FuzzyRule(
new FuzzyRuleCondition(speed, "mittel"),
new FuzzyRuleConsequent(throttle, "mittel")
));
throttleRules.AddRule(new FuzzyRule(
new FuzzyRuleCondition(speed, "hoch"),
new FuzzyRuleConsequent(throttle, "niedrig")
));Für die Lenkung (Steering) sind die Regeln entscheidend: Kombiniere Abstand und Richtungsabweichung. Beispiel:
FuzzyRuleSet steeringRules = new FuzzyRuleSet();
steeringRules.AddRule(new FuzzyRule(
new FuzzyRuleCondition(distance, "weit"),
new FuzzyRuleCondition(direction, "rechts"),
new FuzzyRuleConsequent(steering, "links")
));
steeringRules.AddRule(new FuzzyRule(
new FuzzyRuleCondition(distance, "nah"),
new FuzzyRuleCondition(direction, "gerade"),
new FuzzyRuleConsequent(steering, "gerade")
));Beachte, dass die Ausgabevariablen für Throttle und Steering jeweils eigene Fuzzy-Variablen mit Termen wie „niedrig“, „mittel“, „hoch“ bzw. „links“, „gerade“, „rechts“ benötigen.
Integration in den FuzzyVehicle
In der Update-Methode deines FuzzyVehicle-Skripts sammelst du die scharfen Eingabewerte, erstellst ein FuzzyValueSet und rufst ApplyFuzzyRules auf. Wichtig: Du darfst HardCodeSteering oder HardCodeThrottle nicht verwenden, da der Autograder sonst fehlschlägt. Ein minimales Beispiel:
void Update() {
// 1. Metriken sammeln
float speed = Speed;
float distance = Vector3.Distance(transform.position, pathTracker.closestPointOnPath);
// 2. Fuzzy-Werte setzen
FuzzyValueSet inputs = new FuzzyValueSet();
speedVariable.Evaluate(speed, inputs);
distanceVariable.Evaluate(distance, inputs);
// 3. Regeln auswerten
ApplyFuzzyRules(
throttleEnum, steeringEnum,
throttleRules, steeringRules,
inputs,
out throttleOutput, out steeringOutput,
ref mergedThrottle, ref mergedSteering
);
}Feintuning und häufige Fehler
Die größte Herausforderung ist das Tuning der Zugehörigkeitsfunktionen und der Regeln. Beginne mit einfachen Regeln und beobachte das Verhalten im Unity Editor. Häufige Fehler sind:
- Zu aggressive Lenkung, die zum Schleudern führt.
- Zu spätes Bremsen in Kurven – integriere eine Vorausschau auf die Streckenkrümmung.
- Vergessen, die
distanceTravelled-Metrik zu nutzen, um Streckenabschnitte zu erkennen.
Ein Tipp aus der Praxis: Vergleiche deinen Agenten mit einem neuronalen Netz (optionaler Teil der Aufgabe). Fuzzy Logic ist oft leichter zu debuggen und liefert bei gutem Tuning ähnliche Ergebnisse wie ein simpler ML-Agent.
Erweiterte Techniken: Vorausschauende Lenkung
Um schneller zu fahren, kannst du einen Lookahead-Punkt auf der Strecke berechnen. Nutze pathTracker.closestPointOnPath und laufe einige Indizes entlang des Arrays pathTracker.pathCreator.path. Berechne den Winkel zwischen der aktuellen Fahrzeugrichtung und der Richtung zum Lookahead-Punkt. Diesen Winkel kannst du als weitere Fuzzy-Eingabe verwenden, um frühzeitig in Kurven zu lenken.
Vector3 lookaheadPoint = pathTracker.pathCreator.path[Mathf.Min(currentIndex + 5, pathTracker.pathCreator.path.Length - 1)];
float angle = Vector3.SignedAngle(transform.forward, lookaheadPoint - transform.position, Vector3.up);
angleVariable.Evaluate(angle, inputs);Verbindung zu aktuellen Trends
Fuzzy Logic wird nicht nur in Spielen eingesetzt, sondern auch in autonomen Fahrzeugen und Robotik. Aktuelle Entwicklungen im Bereich KI-gesteuerter Rennspiele (z. B. von NVIDIA oder in der Formel 1) zeigen, dass hybride Ansätze aus Fuzzy Logic und Deep Learning oft die besten Ergebnisse liefern. Auch in der Finanzwelt werden Fuzzy-Systeme genutzt, um unscharfe Marktdaten zu bewerten.
Zusammenfassung
Mit diesem Wissen kannst du deinen eigenen Fuzzy-Logik-Agenten für die Rennstrecke implementieren. Denke daran, die Regeln iterativ zu verbessern und die Metriken sinnvoll zu wählen. Viel Erfolg bei CS7632!