4.4 Pathfinding ar A*
Stundas uzdevums: Saprast un implementēt pathfinding (ceļa meklēšana) algoritmu spēles AI.
80 min plāns: Teorija un paraugs (~10 min) · 1. uzdevums (~20 min) - sagatavo navigācijas reģionu · 2. uzdevums (~25 min) - liec ienaidniekam sekot ceļam · 3. uzdevums (~20 min) - salīdzini taisno kustību ar pathfinding · Iesniegšana (~5 min).
Pirms sāc: atver savu projektu ar stāvokļu mašīnu no 4.3 stundas. Šodien ienaidnieks vairs neiestrēgs aiz sienas.
Teorija: A* algoritms un NavigationAgent2D
Reālistiska AI prasa pathfinding - meklēt īsāko ceļu starp diviem punktiem, izvairoties no šķēršļiem.
A* algoritms izmanto:
- g(n) - faktiskais ceļa garums no sākuma līdz n.
- h(n) - heuristika (taisns attālums līdz mērķim).
- f(n) = g(n) + h(n) - kopējais novērtējums.
Godot 4 piedāvā NavigationAgent2D kas to dara automātiski.
using Godot;
public partial class Enemy : CharacterBody2D
{
private NavigationAgent2D navAgent;
private Vector2 playerPos;
[Export] public float Speed = 180.0f;
public override void _Ready()
{
navAgent = GetNode<NavigationAgent2D>("NavigationAgent2D");
navAgent.TargetPosition = playerPos;
}
public override void _PhysicsProcess(double delta)
{
if (navAgent.IsNavigationFinished()) return;
Vector2 nextPos = navAgent.GetNextPathPosition();
Vector2 dir = (nextPos - Position).Normalized();
Velocity = dir * Speed;
MoveAndSlide();
}
}
Kā šo izmantot projektā
Atceries: ar redzamu efektu editorā nepietiek. Paskaidro, kura C# klase glabā stāvokli, kura metode to maina un kā Godot node struktūra izmanto šo kodu.
Pārbaudi: C# kodā pamatoti izvēlēti List, Dictionary vai HashSet, AI stāvokļi ir skaidri, un sarežģītākas sistēmas var profilēt vai atkļūdot.
public class AiDataCheckpoint
{
public string Lesson = "4.4 Pathfinding ar A*";
public bool UsesCSharp = true;
public bool ChoosesContainer = true;
public bool SeparatesAiState = true;
public bool HandlesRemovalSafely = true;
}
Praktiskie uzdevumi
1. uzdevums -
Sagatavo navigācijas reģionu
Beigās Godot zinās, pa kurām vietām drīkst staigāt.
- Pievieno scēnai mezglu
NavigationRegion2D. - Izveido tam
NavigationPolygonresursu Inspector panelī. - Uzzīmē daudzstūri, kas aptver visu staigājamo laukumu.
- Pievieno laukumā divas sienas kā
StaticBody2D. - Izgriez navigācijas daudzstūrī caurumus ap sienām.
- Nospied Bake NavigationPolygon.
- Pārbaudi, ka zilā zona neiet pāri sienām.
Gatavs, kad: navigācijas zona aptver grīdu, bet ne sienas, un tā ir redzama editorā zilā krāsā.
2. uzdevums -
Liec ienaidniekam sekot ceļam
Beigās ienaidnieks apstaigās sienu, nevis iestrēgs tajā.
- Pievieno ienaidniekam bērnu
NavigationAgent2D. - Atver ienaidnieka C# failu un pārliecinies, ka sākumā ir
using Godot;. - Paņem aģentu kodā ar
NavigationAgent2D agent = GetNode<NavigationAgent2D>("NavigationAgent2D");. - Iestati mērķi ar
agent.TargetPosition = playerPos;. - Paņem nākamo punktu ar
Vector2 next = agent.GetNextPathPosition();. - Virzies uz to ar
(next - Position).Normalized() * Speed. - Būvē un noliec spēlētāju aiz sienas.
Gatavs, kad: ienaidnieks apiet sienu apkārt un nonāk pie spēlētāja, nevis spiežas sienā.
3. uzdevums -
Salīdzini taisno kustību ar pathfinding
Beigās tu redzēsi, ko tieši pathfinding atrisina.
- Nomaini kodu uz taisnu kustību tieši pret spēlētāju, bez agenta.
- Noliec spēlētāju aiz sienas un palaid.
- Pieraksti, kur ienaidnieks apstājās.
- Ieliec pathfinding kodu atpakaļ un atkārto to pašu testu.
- Pieraksti, cik ilgi tagad aizņēma nonākšana pie spēlētāja.
- Pārbaudi, kas notiek, ja spēlētājs ir ārpus navigācijas zonas.
- Pieraksti, ko dara
gun kohA* algoritmā.
Gatavs, kad: bez pathfinding ienaidnieks iestrēgst pie sienas, bet ar to - apiet apkārt.
Papildu uzdevums - Zīmē ceļu uz ekrāna
Ja pamatdarbs ir gatavs, parādi, pa kuru ceļu ienaidnieks iet.
- Paņem pilnu ceļu ar
agent.GetCurrentNavigationPath();. - Pievieno scēnai
Line2Dmezglu. - Iestati tā punktus uz ceļa punktiem katrā kadrā.
- Palaid un vēro, kā līnija mainās, kustinot spēlētāju.
- Pieraksti, cik punktu parasti ir ceļā.
Gatavs, kad: ekrānā redzama līnija, kas rāda ienaidnieka plānoto ceļu ap sienu.
Ko sagatavo
Stundas mērķis: Tavā līmenī ir izcepts navigācijas reģions, un ienaidnieks ar NavigationAgent2D apiet sienas, lai nonāktu pie spēlētāja, nevis iestrēgst pret tām.
GitHub krātuvē jābūt:
- README.md ievietota video saite, kurā ienaidnieks apiet sienu, lai nonāktu pie spēlētāja.
- Ekrānuzņēmums ar navigācijas zonu editorā (zilā zona ap sienām).
- Fails
Enemy.csarNavigationAgent2Dkodu. - README.md: ko A* algoritmā nozīmē
gun koh.
Kā iesniedz: Veic commit un push. Skolotāja norādītajā vietā ievieto tikai GitHub krātuves saiti; visiem prasītajiem failiem, README.md pierakstiem un pierādījumiem jābūt pašā krātuvē.
Biežākās kļūdas
- NavigationAgent neatrod ceļu: NavigationPolygon nav baked vai nepareiza forma.
- Ienaidnieki iestrēgst stūros: Path radius pārāk mazs vai šķēršļi pārāk tuvu.
- Slow performance: Pārāk daudz NavigationAgent - pārbaudi update freq.
Godot ekrānuzņēmumi
Koda piemērs (paplašināts)
using Godot;
public partial class Enemy : CharacterBody2D
{
private NavigationAgent2D navAgent;
private Player player;
[Export] public float Speed = 180.0f;
public override void _Ready()
{
navAgent = GetNode<NavigationAgent2D>("NavigationAgent2D");
navAgent.AvoidanceEnabled = true;
UpdateTarget();
}
public override void _PhysicsProcess(double delta)
{
if (navAgent.IsNavigationFinished()) return;
Vector2 next = navAgent.GetNextPathPosition();
Vector2 direction = (next - Position).Normalized();
Velocity = direction * Speed;
MoveAndSlide();
}
private void UpdateTarget()
{
if (player != null) navAgent.TargetPosition = player.Position;
}
}