I denne opplæringen vil jeg forklare vektor feltopplæring og dens fordeler over mer tradisjonelle pathfinding algoritmer, for eksempel Dijkstra. En grunnleggende forståelse av både Dijkstras algoritme og potensielle felt vil hjelpe deg å forstå denne artikkelen, men er ikke nødvendig.
Pathfinding er et problem med mange løsninger, og hver har sine fordeler og ulemper. Mange pathfinding-algoritmer virker ved å beregne en bane til målet for hver søker, noe som betyr at treningen vil ta dobbelt så lang tid å beregne med dobbelt så mange veibeskrivere. Dette er akseptabelt i mange situasjoner, men når du arbeider med tusenvis av søppelpostere, er det mulig med en mer effektiv tilnærming.
Kjent som vektor feltopplæring, denne tilnærmingen beregner banen fra målet til hver knutepunkt i grafen. For å størkne denne forklaringen av vektorfeltopplæring, vil jeg forklare algoritmen ved å bruke min spesielle implementering som et eksempel.
Merk: Vectorfeltopplæring kan abstraheres til noder og grafer generelt; bare fordi jeg forklarer det ved hjelp av min fliser og nettbasert tilnærming betyr ikke at denne algoritmen er begrenset til fliserbaserte verdener!
Vektorfeltopplæring er sammensatt av tre trinn.
Denne videoen viser deg de endelige resultatene, og gir deg en generell oversikt over konseptene som presenteres i hele opplæringen nedenfor:
Varmekartet lagrer strekningen fra målet til alle fliser på kartet. Banavstand er forskjellig fra euklidisk avstand fordi det er en beregning av avstand mellom to punkter som bare går gjennom traverserbart terreng. En GPS, for eksempel, beregner alltid veiavstand, med veier som er det eneste traversable terrenget.
Nedenfor kan du se forskjellen mellom vei avstand og lineær avstand fra målet (merket i rødt) til en vilkårlig fliser (merket med rosa). Ikke-traversable fliser er trukket i grønt. Som du ser, er stiavstanden (vist i gul) 9, mens den lineære avstanden (vist i lyseblå) er omtrentlig 4.12.
Tallene øverst til venstre på hver flis viser banen avstanden til målet beregnet av varmekartgenereringsalgoritmen. Legg merke til at det er mer enn en mulig veiavstand mellom to punkter; I denne artikkelen er vi bare interessert i den korteste.
Varmekartgenereringsalgoritmen er a bølgefrontalgoritme. Det starter ved målet med en verdi på 0, og strømmer deretter utover for å fylle hele traversable regionen. Det er to trinn til bølgefrontalgoritmen:
0
.forrige flisens vei avstand + 1
.Merk: Bølgefrontalgoritmen går rett og slett på et bredde første søk på rutenettet og lagrer hvor mange trinn det tok å komme til hver flis underveis. Denne algoritmen kalles også noen ganger også børstefirealgoritme.
Nå som veiavstanden fra hver flis til målet er beregnet, kan vi enkelt bestemme stien som må tas for å komme nærmere målet. Det er mulig å gjøre dette på kjøretid for hver sti til hver ramme, men det er ofte bedre å beregne et vektorfelt en gang, og så har alle stifterne referert til vektorfeltet ved kjøretid.
Vektorfeltet lagrer bare en vektor som peker nedover gradienten av avstandsfunksjonen (mot målet) ved hver flis. Her er en visualisering av vektorfeltet, med vektorer som peker fra midten av flisene langs den korteste banen til målet (igjen vist i rødt).
Dette vektorfeltet genereres en flis om gangen ved å se på varmekartet. X- og y-komponentene til vektoren beregnes separat, som vist i pseudokoden nedenfor:
Vector.x = left_tile.distance - right_tile.distance Vector.y = up_tile.distance - down_tile.distance
Merk: Hver flis distansvariabel lagrer banenavstanden til målet som beregnet av bølgefrontalgoritmen ovenfor.
Hvis noen av flisene referert (venstre / høyre / opp / ned) er ikke-traversable og dermed ikke har noen brukbar avstand lagret, brukes avstanden som er knyttet til nåværende flis i stedet for den manglende verdien. Når banevektoren er blitt grovt beregnet, blir den normalisert for å unngå uoverensstemmelser senere.
Nå som vektorfeltet er beregnet, er det veldig enkelt å beregne bevegelse for en sti. Forutsatt at vector_field (x, y) returnerer vektoren vi tidligere har beregnet på flisen (X, y)
, og at ønsket_velocity er en skalar, pseudokoden for å beregne hastigheten til en partikkel ved flis (X, y)
ser slik ut:
velocity_vector = vector_field (x, y) * ønsket_velocity
Partiklene trenger bare å begynne å bevege seg i retningen som er angitt av vektoren. Dette er den enkleste måten å gjøre dette på, men mer kompliserte bevegelsessystemer kan enkelt implementeres ved hjelp av flytfelt.
For eksempel kan teknikkene som er forklart i Forståelse styringsadferd, brukes til bevegelsesbevegelse. I en slik situasjon, velocity_vector
vi beregnet ovenfor ville bli brukt som ønsket hastighet, og styringsadferdene ville bli brukt til å beregne den faktiske bevegelsen ved hver gang trinn.
Ved beregning av bevegelse er det et problem som noen ganger kan oppstå, kjent som lokale optima. Dette skjer når det er to optimale (korteste) veier å ta for å nå målet fra en gitt flis.
Dette problemet kan sees på bildet nedenfor. Flisen (vist i rosa) umiddelbart til venstre for midten av veggen har en banevektor hvis komponenter (x og y) er lik 0.
Lokale optima forårsaker at stifinderen blir sittende fast; de vil referere til vektorfeltet som ikke vil indikere en retning for å gå inn. Når dette skjer vil bevegelsene forbli på samme sted med mindre en rettelse er implementert.
Den mest elegante måten (jeg har funnet) for å løse problemet er å dele opp både varmekartet og vektorfeltet en gang. Hver enkelt varmekart og vektorfelt er nå delt inn i fire mindre fliser. Problemet forblir det samme med et oppdelt grid; det har bare blitt litt minimert.
Det virkelige trikset som løser det lokale optima-problemet, er å først legge til fire mål noder, i stedet for bare en. For å gjøre dette må vi bare modifisere det første trinnet i varmekartgenereringsalgoritmen. Da vi bare brukte å legge til ett mål med en sti avstand på 0, legger vi nå de fire flisene som er nærmest målet.
Det er flere måter å velge de fire fliser på, men hvordan de velges er i stor grad irrelevant - så lenge de fire fliser er tilstøtende (og traversable), bør denne teknikken fungere.
Her er den endrede pseudokoden for varmekartgenerasjonen:
0
.forrige flisens vei avstand + 1
.Og nå, her er de endelige resultatene som tydelig viser at det lokale optima-problemet har blitt eliminert:
Selv om denne løsningen er elegant, er den langt fra ideell. Ved å bruke det betyr at kalkulering av varmekartet og vektorfeltet tar fire ganger lengre på grunn av det økte antall fliser.
Andre løsninger krever å sjekke og deretter bestemme hvilken retning å gå til i hvert enkelt tilfelle, noe som reduserer partikkelbevegelsesberegningene betydelig. I mitt tilfelle var oppdeling av kartene det bedre alternativet.
Forhåpentligvis har denne opplæringen lært deg hvordan du implementerer målbasert opplæring i en flisbasert verden. Vær oppmerksom på at denne typen opplæring er i utgangspunktet enkel: partikler følger gradienten av avstandsfunksjonen mot målet.
Implementeringen er mer kompleks, men kan brytes ned i følgende tre håndterbare trinn:
Jeg håper å se folk utvide på ideene som presenteres her. Som alltid, hvis du har spørsmål, kan du spørre dem i kommentarene nedenfor!