PathBerserker2d  1.0
Platformer pathfinding solution
Core Concepts

This page introduces the core concepts of PathBerserker2d and presents its most important components.

NavSurface

NavSurface is the core component of PathBerserker2d. You can have as many as you want of them. Each encodes it's children's collider data in a pathable form. This process is called bake.

In this section will go over what data a NavSurface stores and what that data is used for.

Line Segments

NavSurface's store data organized in line segments. On bake, each collider is reduced to a set of such segments. Movement on a line segment from one point to another is trivial. The NavAgent just has to move in whatever direction the goal lies.

Lets imagine a NavSurface with a rectangular sprite and collider as a child. We'd like to somehow pathfind on this sprite.

At bake time, the rectangle sprite's BoxCollider2d is reduced to 4 line segments. With just these 4 line segments, we could already do some pathfinding. But only if the NavAgents goal lies on the same segment as the agent itself, a path could actually be found.

But what if the goal is on a different segment? In the original collider the segments where connected at their ends. Wouldn't it be cool, if they also where connected for pathfinding purposes?

Corner Links

Links connect two segments with each other. An agent can traverse such a link to get from one place to another. Links can also connect two points on the same segment.

Lets introduce a link that solves the segment connection problem, the corner link. They link one segment end with another segment start, if the segments where connected in the collider. As such, they have zero length. The cost of traversal is instead calculated by the angle between both segments. Corner links are placed automatically when a NavSurface gets loaded.

With the corner links added two all 4 corners the NavAgent can now path to any point on the rectangle. But what if there was an obstacle that prevented all but small NavAgents to pass through?

Clearance

Somehow the clearance for each position on the segment needs to be known to solve this issue. Since there are infinitely many position infinitely small apart from each other on every segment, the clearance values need to be discrete to store them. In PathBerserker2d every segment is divided into cells of configurable size. Every cell stores the lowest clearance over the span it occupies. This happens automatically at bake. It won't be updated at runtime. When pathfinding, those cell values are used to figure out, if a NavAgent could move from one point on a segment to another without hitting its head.

Interaction between NavSurfaces

You might be wondering why you should use multiple NavSurfaces and not just one for all colliders. There are two reasons to use multiple NavSurfaces. One, NavSurface can be loaded and unload at runtime individually at runtime. This come in handy, if for example you want to load pieces of your level from prefabs at runtime.

The second reason to use multiple NavSurfaces is to support moving platforms. The pathfinding data stored in a NavSurface can't be changed outside baking, which would be required for moving platforms. But the data is stored relative to the position of the NavSurface component itself. Just like the child colliders of a NavSurface are relative to the position of their parent and move when their parent is moved. So moving colliders won't be reflected in the pathfinding graph, moving an entire NavSurface will be. Thus, moving platforms should always be their own NavSurface.

Limitations when using multiple NavSurface

There are some limitations to the interaction of multiple NavSurfaces worth knowing.

For one, the baking process only considers child colliders. Hence, colliders of other NavSurfaces won't contribute to cell clearance calculations.

NavSurfaces can also only be moved. Rotating or scaling them won't be reflected in the pathfinding data.

NavTags

NavTags are a build-in way of marking certain sections of segments and links with tags.

Lets imagine the top of our rectangle is very hot and will grill all non heat shielded NavAgents that traverse it. It would be great, if the pathfinder could avoid choosing a path that traverse the top side. But for that it needs to know that the top side is special.

Thats what NavAreaMarkers are for. They mark a part or the whole segment with a NavTag of your choice. The NavAgent in turn has a cost multiplier for each of them. This allows you to make some NavTags cheap to traverse, others more costly and some impossible to traverse.

NavAreaMarker are applied at runtime and thus can be moved and effect multiple NavSurfaces. Links are not effected by NavAreaMarkers. You have to mark them manually.

They can also be used for other purposes. You could maybe change animation when walking on something hot. Or you could use them to determine what foot step sounds to play. (There is a demo scene for the footsteps thing included.)

NavLinks

Till now, our NavAgent was stuck on its Rectangle and couldn't move to other, potentially more appealing platforms. Thats the point where you as level designer has to put some work in. You have the ability to place NavLink or NavLinkClusters to connect points on segments.

NavLinks and NavLinkClusters are mapped at runtime and thus can be moved and connect different NavSurfaces.

Both have some of the same requirements for traversal as a segment, a clearance and a NavTag. Additionally, a link also has a link-type. These types are meant as hints to the NavAgent on how to traverse them. The NavAgent will for example traverse a ladder-link differently then a jump-link.

What differentiates NavLink from NavCluster links is, that a NavLink is just a standard link between two points, while a NavLinkCluster is a bit more complicated. A NavLinkCluster can have as many points as you like. Each of those points is then connected to all others. This is useful to model a link with multiple entries and exits, like an elevator or ladder link might have.