Download the full presentation here: http://www.guerrilla-games.com/read/putting-the-ai-back-into-air
Abstract: In this talk, we explain the technology behind the aerial navigation in Horizon Zero Dawn. In Horizon, we've represented the flyable air space by use of a run-time generated height map. Queries can be done on this height map for positional information and navigation. We present a hierarchical path planning algorithm for finding a progressively more detailed path between two points. Additionally, we will touch on some gameplay related subjects, to show the additional challenges we faced in implementing the different flying behaviors, such as transitioning from air to ground and guided crash-landing.
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
Putting the AI Back Into Air: Navigating the Air Space of Horizon Zero Dawn
1. Putting the AI back into Air
Navigating the Air Space of Horizon Zero Dawn
Game AI North Copenhagen,
October 17, 2017
Wouter Josemans
Guerrilla Games
2. Contents
• Introduction
• Problem Specification
• Navigation Data Generation
• Path Planning
• Path Smoothing/Following
• Gameplay/AI System Interactions
• Conclusion
3. Introduction
• Guerrilla
– Studio in Amsterdam
– Previously known for Killzone games
– Team of around 250 people in total
• Horizon Zero Dawn
– Large, open world game
– Robotic wildlife
– Flying enemies
– AI programmers: around 10 people
during peak development
5. Problem Specification
• Flying agents should be able to fly from point A to
point B in a natural looking way without flying
through geometry
• Navigation should support agents of more than one
size
• Navigation data should be memory-efficient and
queries should be of similar performance to their
NavMesh counterparts
• Support same set of features as ground-based
agents
6. Considered Air Navigation
Approaches
• Full 3D approaches
– Waypoint graphs (Used in previous projects)
– Regular voxel grids (too expensive for
games)
– Sparse Voxel Octrees (as used in Warframe
[BRE17])
• Other approaches
– Multiple NavMesh layers with flight
connections in between
– Height maps (which we ended up using)
7. Height Maps
• A height map maps the 𝑥, 𝑦 coordinates of a position to a height
• World positions are discretized in square blocks on the height map called cells
• Cells of a height map have a certain size depending on the agent
• In Horizon, the height map describes the highest piece of collision for that cell
- There’s only one height per cell (can’t fly underneath arches)
+ In general height maps are easy to work with and cost a lot less memory than many
alternatives
8.
9.
10.
11. Height Map Generation
• Generate at runtime
• Cells are grouped together in tiles, the minimum
generation unit
• Minimum flying height is determined by finding the
highest piece of collision in that cell, and adding the
agent radius on top of that
• Agents have a generation bubble around them, so
height map is only generated for tiles that lie within a
generation bubble
• Generation gets callbacks from the streaming system,
so tiles are updated when things are streamed in/out
12. Height Map Generation
• Each tile is generated in a separate job:
– Find all physics polygons in a tile
– For each poly
• Rasterize the polygon to the cell grid
• Cell height becomes the maximum of the poly’s height and the
current height
– Dilate the height map by the agent radius using the van
Herk–Gil–Werman algorithm [HER92, GIL93]
13. Height Map Queries
• “Safe Height” queries
– Height map lookup
• Raycasts
– Bresenham’s line drawing algorithm
[BRE65] for finding cells, then checking
intersections
• Path queries
– Full path planning algorithm
14. Path Planning - Considerations
• If start and end position lie above the
height map, we know that there is always a
path
• However, we don’t want to fly over a
mountain if going around it would be much
faster
• So we can not simply fly from start to end,
going up or down when needed
15. Path Planning
• A* on a discrete regular grid with non-uniform cost
• No diagonal transitions
• Change height if necessary when transitioning to a
neighbor
• Node:
– Tile XY, cell XY coordinates
– Expansion Height (not necessarily the height map height at the
node’s position)
N
W C E
S
16. Path Planning
• Estimated cost between two nodes is Euclidean XY distance
• Actual cost of going from 𝑥1, 𝑦1 to (𝑥2, 𝑦2):
• If ℎ(𝑥1, 𝑦1) higher than ℎ(𝑥2, 𝑦2): XY distance
• If ℎ(𝑥1, 𝑦1) lower than ℎ(𝑥2, 𝑦2): XYZ distance
• Penalize going up, but not going down
• Set the Expansion Height for node B to max(ℎ(𝑥1, 𝑦1) , ℎ(𝑥2, 𝑦2))
• Goal is reached when in the right cell, then a final path node is added to the goal
height
17. Path Planning - Results
• Approach worked well in terms of resulting
paths
• Unfortunately, we soon ran into
performance issues:
– Algorithm does not scale well with distance
– For large parts of the search space, costs are
actually uniform and then there exist many
equally good paths, as described in [HAR11],
which leads to the expansion of lots of nodes
18. Path Planning
• So: performance not satisfactory (having to
sacrifice height map detail for performance gain
was not something we wanted to do)
• Need something more sophisticated: Jump
Point Search? Non-regular grid?
…Or something else?
19. Path Planning
• So: performance not satisfactory (having to
sacrifice height map detail for performance gain
was not something we wanted to do)
• Need something more sophisticated: Jump
Point Search? Non-regular grid?
…Or something else?
Our solution: hierarchical path planning over
mipmaps
20. Height Map Generation with Mipmaps
• Use mipmaps for several levels of detail
• Level 1 mipmap samples 4 neighboring cells from the
original height map, sets its value as the max of these
height values
• Level 2 mipmap samples 4 neighboring cells from the
Level 1 mipmap
• Etc.
• Until we get to the level where one cell is equal to one
tile, so we have log2(𝑡𝑖𝑙𝑒_𝑟𝑒𝑠𝑜𝑙𝑢𝑡𝑖𝑜𝑛) + 1 MIP levels
21.
22.
23.
24.
25.
26.
27. Height Map Generation with Mipmaps
• Introduces extra memory overhead:
– For a 64x64 height map we add 32x32
+ 16x16 + 8x8 + 4x4 + 2x2 + 1x1 cells =
1365 extra cells per tile
– Roughly 33% extra memory
– Acceptable overhead (initially around
150 KB for a Stormbird height map, now
about 190 KB)
28. Hierarchical Path Planning
• Allow a fixed number of A* iterations across
one query
• Plan a coarse path on a higher mipmap level
• Consider this as a rough path corridor, only
allow expansion of nodes on lower mipmap
level that lie within the corridor
• Keep refining the path at lower mipmap levels
until we run out of A* iterations
• Return the most detailed (finished) path at the
time that we run out of iterations
29. Hierarchical Path Planning
• Final configuration (Glinthawk/Stormbird):
– Allow 1024 cycles
– Plan initial path at mipmap level 3
– Refine path at mipmap level 1 and then 0
• To investigate: scale mipmap level planning
policies with respect to the distance between start
and end
30. Hierarchical Path Planning
• Pros:
+ There is an upper limit to the cost of path planning
+ We always find a path, even if we run into the upper limit
+ Can in theory plan really long paths
• Cons:
– We lose optimality because we restrict the path search
– Quality of the path depends on the length of the path
• We like the pros, and we can live with the cons
31. Path Smoothing
• Path we get from path planning is quite angular, with steep
slopes
• Robots flying straight up or down doesn’t look good
• Algorithm:
– Do a (height map) raycast from start to end
– If a hit occurs, split the path in the middle, repeat the process
for both segments until they are free of hits
– If no hit occurs, add the segment to the final path
• Misses a couple of cases, but we keep running the algorithm
while flying around, so eventually the shortcuts are found
32. Path Following/Air Movement
• Simple particle physics:
– Velocity/Angular Velocity + Acceleration/Angular
Acceleration
• AI drives acceleration/deceleration vector to follow the path
as closely as possible
• AI drives angular velocity based on flight method:
– “Hover” : forward not necessarily movement heading
– “Glide” : forward always in movement heading
• Mostly code driven movement, animation driven movement
during certain animations (e.g. landing)
• Drive certain movement animation based on shape of the
path
33. Interactions with other AI Systems
On Ground In Air
CollisionAvoidance (Entities) ✓ ✕
Position Evaluation ✓ ✓
Area Restrictions Convex hulls Cylinders only
Formation Movement ✓ ✕
Melee Attack System
(Clamping)
✓
(NavMesh)
✓
(Physics)
Combat System (ticketing) ✓ ✓
34. Flying Behaviors
• Transitioning from air to ground and vice versa
• Landing:
– Generate candidate positions on the NavMesh
– Filter positions where height map is more than on
agent radius higher
– Adjust the angle of approach
– After landing, switch from air to ground-based
movement
• Guided crashing:
– Special state when knocked down or killed
– Find landing position in the direction of the velocity
35. Flying Behaviors
• Dive Attack
– Stormbird flies up high into the sky
– Dive straight at the target, crashing into the
ground at its position
– Fly in front of the sun/moon for added effect
36. Conclusion
• Representing flyable air space using a height map proved to
be sufficient for the environments in the game
• Regular-grid planning proved to not scale well in performance
terms
• Hierarchical queries on mipmaps offer a good trade-off
between finding a natural looking path and keeping
performance at an acceptable level
• Air navigation was relatively easy to integrate into our
gameplay systems, but for some cases (such as collision
avoidance) work remains to be done
38. Citations
• [BRE17] D. Brewer, 3D Flight Navigation Using Sparse Voxel Octrees, Game AI
Pro 3, 2017
• [BRE65] J. E. Bresenham, Algorithm for computer control of a digital plotter. IBM
Syst. J. 4, 1965
• [HAR11] D. Harabor, A. Botea, and P. Kilby., Path Symmetries in Uniform-cost
Grid Maps. In Symposium on Abstraction Reformulation and Approximation
(SARA), 2011.
• [GIL93] J. Gil and M. Werman. Computing 2-d min, median, and max filters., IEEE
Transactions on Pattern Analysis and Machine Intelligence, 15(5):504.507, May
1993.
• [HER92] M. van Herk. A fast algorithm for local minimum and maximum filters
on rectangular and octagonal kernels. Pattern Recognition Letters, 13(7):517.521,
July 1992
Editor's Notes
250 people in studio, plus 120 outsource artists, 80 QA
In the trailer, we saw two flying enemies, both are quite different in scale. Note that the larger bird does not only fight the player while flying, but can also land and fight there.
Could not find a lot of literature on air navigation approaches in video games
Full 3D navigation is quite expensive, unless you have a very sparse representation of your data -> Warframe by Daniel Brewer
However, we felt this approach was complex and were not sure if it was going to be the best fit for our kind of terrain
Height map approach is simpler computationally and possibly cheaper memory-wise
Since we have a large open world, where most encounters happen outdoors under mostly open skies, these restrictions were acceptable for us
Another drawback is that it is not easy to represent an upper limit to how high a robot can fly
Glinthawk height map
Stormbird height map
So what can we do with a height map? Well, we can do a number of queries:
Safe height query returns the minimum safe flying height at an X, Y position in the world
Raycast checks if and where a line going from A to B intersects with the height map
For diagonal transitions: if N and W are both much higher than C, then the NW neighbor can not be reached without changing height or passing through the AirNav
Due to path symmetry, many paths are equally good
Non-regular grid would not give us a lot of performance gains, since our artists generally don’t make flat (or uniform) surfaces
Due to path symmetry, many paths are equally good
Non-regular grid would not give us a lot of performance gains, since our artists generally don’t make flat (or uniform) surfaces
On 64x64 tiles, we have 2^6 tiles, plus one more for cell == tile case
MIP = multum in parvo (much in little)
On 64x64 tiles, we have 2^6 tiles, plus one more for cell == tile case
MIP level 0, 4 tiles of 16x16
MIP level 1, 4 tiles of 8x8
MIP level 2, 4 tiles of 4x4
MIP level 3, 4 tiles of 2x2
MIP level 4, 4 tiles of 1x1
Converges to 1/3 as shown by Archimedes
Stormbird: typically 9 tiles active, of 64 x 64 resolution x 4 bytes per float
In practice, we found that paths don’t lose a lot of detail, especially in the environments where we have our encounters
Forested areas are the most problematic, but we did not have
Hover = like a helicopter, Glide = like a plane
Collision Avoidance was never necessary, due to the way our claiming system works (two robots passing through each other in movement was not really noticed) and robots are positioned by the group
We clamp on physics instead of Nav because otherwise the melee attacks wouldn’t be able to reach the player on uneven terrain
Combat system: we had problems with ground-based robots indicating which one was actively attacking you, but for flying robots this was easy to communicate by having the non-attacking ones circle around the player, while the attacker tries to hover in front of your face
We do not reason about ground navigation while in the air other than for generating landing positions. We cannot chain ground based and air paths at the moment.
Dying while in the air: going straight into ragdoll did not look good, and game design preferred the robot to land on a reachable bit of geometry (in practice this was often quite obvious, and broke immersion for some players, but they did appreciate the fact that their loot didn’t go to waste)
Representing flyable air space as a height maps also costs less memory