Struct PlatformerGraph
A graph specifically designed for 2D platformer types of games, but can also be used as an advanced waypointing system. What makes this graph unique is that the edges themselves play the main part, not the nodes they connect. This allows for fluid positions anywhere on an edge.
Added functionality since v1.1 is that the graph can now be pre-allocated and then populated from within jobs.
Namespace: AnyPath.Graphs.PlatformerGraph
Assembly: AnyPath.dll
Syntax
public struct PlatformerGraph : IGraph<PlatformerGraphLocation>, IDisposable
Remarks
Since v1.1, any edge that has an enterCost of infinity is considered unwalkable.
The LineGraph provides similar functionality but in 3D.
Constructors
PlatformerGraph(IReadOnlyList<float2>, IReadOnlyList<Edge>, IReadOnlyList<Edge>, Allocator, bool, int, int)
Construct a Platformer Graph from a set of vertices and edge definitions
Declaration
public PlatformerGraph(IReadOnlyList<float2> vertices, IReadOnlyList<PlatformerGraph.Edge> undirectedEdges, IReadOnlyList<PlatformerGraph.Edge> directedEdges, Allocator allocator, bool directedEdgesRaycastable = false, int edgesPerQuadrant = 16, int maxQuadTreeDepth = 5)
Parameters
| Type | Name | Description |
|---|---|---|
| IReadOnlyList<float2> | vertices | Vertices to use |
| IReadOnlyList<PlatformerGraph.Edge> | undirectedEdges | Indices connecting vertices together in an undirected fashion. Every pair of indices (i, i+1) describes an edge that connectets vertex i and vertex i + 1 in both directions |
| IReadOnlyList<PlatformerGraph.Edge> | directedEdges | Indices connecting vertices together in a directed fashion. Every pair of indices (i, i+1) describes an edge that connectets vertex i to vertex i + 1 |
| Allocator | allocator | Allocator to use |
| bool | directedEdgesRaycastable | If true, directed edges can be returned by a raycast query. This comes with the caveat that when you start a path from a directed edge and the goal is on the same edge but behind the starting location, a path will be found that goes in the opposite direction of that edge. |
| int | edgesPerQuadrant | Max edges per quadrant for the internal quadtree |
| int | maxQuadTreeDepth | Max depth of the internal quadtree for raycast accellerating. If your graph is very large it may be benificial to increase this value. Finding a good balance is key to having optimal raycast and closest location performance. |
PlatformerGraph(Allocator, bool, int, int, int, int)
Preallocates an empty graph, to be populated later using any of the Populate(IReadOnlyList<float2>, IReadOnlyList<Edge>, IReadOnlyList<Edge>) methods
Declaration
public PlatformerGraph(Allocator allocator, bool directedEdgesRaycastable = false, int edgesPerQuadrant = 16, int maxQuadTreeDepth = 5, int initialVertexCapacity = 0, int intialEdgeCapacity = 0)
Parameters
| Type | Name | Description |
|---|---|---|
| Allocator | allocator | Allocator to use |
| bool | directedEdgesRaycastable | If true, directed edges can be returned by a raycast query. This comes with the caveat that when you start a path from a directed edge and the goal is on the same edge but behind the starting location, a path will be found that goes in the opposite direction of that edge. |
| int | edgesPerQuadrant | Max edges per quadrant for the internal quadtree |
| int | maxQuadTreeDepth | Max depth of the internal quadtree for raycast accellerating. If your graph is very large it may be benificial to increase this value. Finding a good balance is key to having optimal raycast and closest location performance. |
| int | initialVertexCapacity | Hint to how many vertices are going to be added later, which can boost performance |
| int | intialEdgeCapacity | Hint to how many edges are going to be added later, which can boost performance |
Properties
DirectedEdgesRaycastable
Indicates if a raycast or any overlap query will return directed edges
Declaration
public bool DirectedEdgesRaycastable { get; }
Property Value
| Type | Description |
|---|---|
| bool |
EdgeCount
Amount of edges (directed+undirected) contained in the graph.
Declaration
public int EdgeCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
Edges
Read only access to the edges that make up the graph
Declaration
public NativeArray<PlatformerGraph.Edge>.ReadOnly Edges { get; }
Property Value
| Type | Description |
|---|---|
| NativeArray<PlatformerGraph.Edge>.ReadOnly |
Quadtree
Access to the internal quadtree of the graph for advanced location queries.
Declaration
public NativeQuadtree<int> Quadtree { get; }
Property Value
| Type | Description |
|---|---|
| NativeQuadtree<int> |
Remarks
Warning: do not modify the quadtree as this will corrupt the state of the graph.
UndirectedEdgeCount
Amount of undirected edges. Undirected edges appear first in the raw Edges array. So any undirected edges start from this index.
Declaration
public int UndirectedEdgeCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
Vertices
Read only access to the vertices that make up the graph
Declaration
public NativeArray<float2>.ReadOnly Vertices { get; }
Property Value
| Type | Description |
|---|---|
| NativeArray<float2>.ReadOnly |
Methods
ClosestLocation(NearestNeighbourQuery, float2, float, ClosestPlatformerGraphLocationPredicate, out PlatformerGraphLocation)
Returns the closest location on the graph from a point, with a custom 'filter' predicate. This predicate can be used for instance to check if there is a clear line of sight between the position and the location that is returned.
Declaration
public bool ClosestLocation(NativeQuadtree<int>.NearestNeighbourQuery cache, float2 position, float maxDistance, ClosestPlatformerGraphLocationPredicate predicate, out PlatformerGraphLocation location)
Parameters
| Type | Name | Description |
|---|---|---|
| NativeQuadtree<int>.NearestNeighbourQuery | cache | Re-usable cache for the algorithm. If you need to perform a lot of closest location queries in a row, it is faster to allocate this cache once and re-use it for every query. |
| float2 | position | The center position to search from |
| float | maxDistance | The max search radius. Locations beyond this distance will not be visited. |
| ClosestPlatformerGraphLocationPredicate | predicate | A custom function to determine wether a location is valid as a closest location. If false is returned, the next closest location after that is attempted, and so on. |
| PlatformerGraphLocation | location | Returns the closest location on the graph |
Returns
| Type | Description |
|---|---|
| bool | Wether a location was found within the given radius |
Remarks
This function cannot be used in a burst compiled job context. Use the overload that accepts a Unity.Burst.FunctionPointer<T> instead.
ClosestLocation(NearestNeighbourQuery, float2, float, out PlatformerGraphLocation)
Returns the closest location on the graph from a point.
Declaration
public bool ClosestLocation(NativeQuadtree<int>.NearestNeighbourQuery cache, float2 position, float maxRadius, out PlatformerGraphLocation location)
Parameters
| Type | Name | Description |
|---|---|---|
| NativeQuadtree<int>.NearestNeighbourQuery | cache | Re-usable cache for the algorithm. If you need to perform a lot of closest location queries in a row, it is faster to allocate this cache once and re-use it for every query. |
| float2 | position | The center position to search from |
| float | maxRadius | The max search radius |
| PlatformerGraphLocation | location | Returns the closest location on the graph |
Returns
| Type | Description |
|---|---|
| bool | Wether a location was found within the given radius |
ClosestLocation(NearestNeighbourQuery, float2, float, int, out PlatformerGraphLocation)
Returns the closest location on the graph from a point.
Declaration
public bool ClosestLocation(NativeQuadtree<int>.NearestNeighbourQuery cache, float2 position, float maxRadius, int flagBitMask, out PlatformerGraphLocation location)
Parameters
| Type | Name | Description |
|---|---|---|
| NativeQuadtree<int>.NearestNeighbourQuery | cache | Re-usable cache for the algorithm. If you need to perform a lot of closest location queries in a row, it is faster to allocate this cache once and re-use it for every query. |
| float2 | position | The center position to search from |
| float | maxRadius | The max search radius |
| int | flagBitMask | A bitwise AND is performed on the edge candidates and if any bit is true, the edge is considered. |
| PlatformerGraphLocation | location | Returns the closest location on the graph |
Returns
| Type | Description |
|---|---|
| bool | Wether a location was found within the given radius |
ClosestLocation(NearestNeighbourQuery, float2, float, FunctionPointer<ClosestPlatformerGraphLocationPredicate>, out PlatformerGraphLocation)
Returns the closest location on the graph from a point, with a custom 'filter' predicate. This predicate can be used for instance to check if there is a clear line of sight between the position and the location that is returned.
Declaration
public bool ClosestLocation(NativeQuadtree<int>.NearestNeighbourQuery cache, float2 position, float maxDistance, FunctionPointer<ClosestPlatformerGraphLocationPredicate> predicate, out PlatformerGraphLocation location)
Parameters
| Type | Name | Description |
|---|---|---|
| NativeQuadtree<int>.NearestNeighbourQuery | cache | Re-usable cache for the algorithm. If you need to perform a lot of closest location queries in a row, it is faster to allocate this cache once and re-use it for every query. |
| float2 | position | The center position to search from |
| float | maxDistance | The max search radius. Locations beyond this distance will not be visited. |
| FunctionPointer<ClosestPlatformerGraphLocationPredicate> | predicate | A custom function to determine wether a location is valid as a closest location. If false is returned, the next closest location after that is attempted, and so on. |
| PlatformerGraphLocation | location | Returns the closest location on the graph |
Returns
| Type | Description |
|---|---|
| bool | Wether a location was found within the given radius |
ClosestLocation(float2, float, ClosestPlatformerGraphLocationPredicate, out PlatformerGraphLocation)
Returns the closest location on the graph from a point, with a custom 'filter' predicate. This predicate can be used for instance to check if there is a clear line of sight between the position and the location that is returned.
Declaration
public bool ClosestLocation(float2 position, float maxDistance, ClosestPlatformerGraphLocationPredicate predicate, out PlatformerGraphLocation location)
Parameters
| Type | Name | Description |
|---|---|---|
| float2 | position | The center position to search from |
| float | maxDistance | The max search radius. Locations beyond this distance will not be visited. |
| ClosestPlatformerGraphLocationPredicate | predicate | A custom function to determine wether a location is valid as a closest location. If false is returned, the next closest location after that is attempted, and so on. |
| PlatformerGraphLocation | location | Returns the closest location on the graph |
Returns
| Type | Description |
|---|---|
| bool | Wether a location was found within the given radius |
Remarks
This function cannot be used in a burst compiled job context. Use the overload that accepts a Unity.Burst.FunctionPointer<T> instead.
ClosestLocation(float2, float, out PlatformerGraphLocation)
Returns the closest location on the graph from a point.
Declaration
public bool ClosestLocation(float2 position, float maxRadius, out PlatformerGraphLocation location)
Parameters
| Type | Name | Description |
|---|---|---|
| float2 | position | The center position to search from |
| float | maxRadius | The max search radius |
| PlatformerGraphLocation | location | Returns the closest location on the graph |
Returns
| Type | Description |
|---|---|
| bool | Wether a location was found within the given radius |
ClosestLocation(float2, float, int, out PlatformerGraphLocation)
Returns the closest location on the graph from a point.
Declaration
public bool ClosestLocation(float2 position, float maxRadius, int flagBitMask, out PlatformerGraphLocation location)
Parameters
| Type | Name | Description |
|---|---|---|
| float2 | position | The center position to search from |
| float | maxRadius | The max search radius |
| int | flagBitMask | A bitwise AND is performed on the edge candidates and if any bit is true, the edge is considered. |
| PlatformerGraphLocation | location | Returns the closest location on the graph |
Returns
| Type | Description |
|---|---|
| bool | Wether a location was found within the given radius |
ClosestLocation(float2, float, FunctionPointer<ClosestPlatformerGraphLocationPredicate>, out PlatformerGraphLocation)
Returns the closest location on the graph from a point, with a custom 'filter' predicate. This predicate can be used for instance to check if there is a clear line of sight between the position and the location that is returned.
Declaration
public bool ClosestLocation(float2 position, float maxDistance, FunctionPointer<ClosestPlatformerGraphLocationPredicate> predicate, out PlatformerGraphLocation location)
Parameters
| Type | Name | Description |
|---|---|---|
| float2 | position | The center position to search from |
| float | maxDistance | The max search radius. Locations beyond this distance will not be visited. |
| FunctionPointer<ClosestPlatformerGraphLocationPredicate> | predicate | A custom function to determine wether a location is valid as a closest location. If false is returned, the next closest location after that is attempted, and so on. |
| PlatformerGraphLocation | location | Returns the closest location on the graph |
Returns
| Type | Description |
|---|---|
| bool | Wether a location was found within the given radius |
Collect(PlatformerGraphLocation, ref NativeList<Edge<PlatformerGraphLocation>>)
Implement adding all the directed edges that go from the input node.
Declaration
public void Collect(PlatformerGraphLocation location, ref NativeList<Edge<PlatformerGraphLocation>> edgeBuffer)
Parameters
| Type | Name | Description |
|---|---|---|
| PlatformerGraphLocation | location | |
| NativeList<Edge<PlatformerGraphLocation>> | edgeBuffer | Add edges to other nodes to this buffer. The buffer is automatically cleared each time before this method is called. Warning: do not modify the edgeBuffer itself. Only add to it. The ref keyword is only used for performance reasons. |
ContainsEdgeId(int)
Does an edge with a given Id exist?
Declaration
public bool ContainsEdgeId(int edgeId)
Parameters
| Type | Name | Description |
|---|---|---|
| int | edgeId |
Returns
| Type | Description |
|---|---|
| bool |
GetEdgeIndex(int)
Returns the index of an edge from it's Id. Note that Id's are optional so if you didn't supply Id's upon creation, this method will not work. Also note that if more edges share the same Id, this method will also not work.
Declaration
public int GetEdgeIndex(int edgeId)
Parameters
| Type | Name | Description |
|---|---|---|
| int | edgeId | The Id of the edge |
Returns
| Type | Description |
|---|---|
| int |
GetEnumerator()
Returns an enumerator that enumerates all edges/locations in the graph. This can be used to construct ALT heuristics.
Declaration
public PlatformerGraph.Enumerator GetEnumerator()
Returns
| Type | Description |
|---|---|
| PlatformerGraph.Enumerator |
GetLocationFromEdgeId(int)
Returns a location for pathfinding queries from an edge's Id. Note that this Id must have been manually assigned to the edge's upon creation. id
The exact position on the edge is set at the center by default. But this value can be modified to be anywhere between or on the endpoints using PositionT.
Declaration
public PlatformerGraphLocation GetLocationFromEdgeId(int edgeId)
Parameters
| Type | Name | Description |
|---|---|---|
| int | edgeId | The id of the edge |
Returns
| Type | Description |
|---|---|
| PlatformerGraphLocation |
Remarks
Throws an error if the edgeId isn't present
GetLocationFromEdgeIndex(int)
Returns a location for pathfinding queries from an edge index.
The exact position on the edge is set at the center by default. But this value can be modified to be anywhere between or on the endpoints using PositionT.
Declaration
public PlatformerGraphLocation GetLocationFromEdgeIndex(int edgeIndex)
Parameters
| Type | Name | Description |
|---|---|---|
| int | edgeIndex |
Returns
| Type | Description |
|---|---|
| PlatformerGraphLocation |
GetOverlappingEdgeIndices(AABB2D, NativeHashSet<int>)
Appends all edge indices whose AABB's overlap with a rectangle to a hashset, so that no duplicates can ocur.
Declaration
public void GetOverlappingEdgeIndices(AABB2D aabb, NativeHashSet<int> indices)
Parameters
| Type | Name | Description |
|---|---|---|
| AABB2D | aabb | Rectangle to test against |
| NativeHashSet<int> | indices | The results are appended to this set. The set is not cleared beforehand |
Populate(PlatformerGraph)
Copies the contents of the source graph into this graph. This can be useful if you want almost the exact same graph but will apply small modifications using SetUnwalkable(int) or SetEnterCostAndFlags(int, float, int) on this graph after populating it.
Declaration
public void Populate(PlatformerGraph source)
Parameters
| Type | Name | Description |
|---|---|---|
| PlatformerGraph | source | The source graph to copy |
Remarks
This method is burst compatible, meaning it can be used inside a job to populate the graph with high performance, if you need frequent updates.
Note that this method writes to the graph and as such it should not be used while there are active pathfinding queries running on it. The source graph is allowed be in use though.
Source and destination settings should match
Exceptions
| Type | Condition |
|---|---|
| InvalidOperationException | Throws when the value of DirectedEdgesRaycastable is different than that of the source |
Populate(IReadOnlyList<float2>, IReadOnlyList<Edge>, IReadOnlyList<Edge>)
Populate the graph with vertices and edges
Declaration
public void Populate(IReadOnlyList<float2> vertices, IReadOnlyList<PlatformerGraph.Edge> undirectedEdges, IReadOnlyList<PlatformerGraph.Edge> directedEdges = null)
Parameters
| Type | Name | Description |
|---|---|---|
| IReadOnlyList<float2> | vertices | Vertices to use |
| IReadOnlyList<PlatformerGraph.Edge> | undirectedEdges | Indices connecting vertices together in an undirected fashion. Every pair of indices (i, i+1) describes an edge that connectets vertex i and vertex i + 1 in both directions |
| IReadOnlyList<PlatformerGraph.Edge> | directedEdges | Indices connecting vertices together in a directed fashion. Every pair of indices (i, i+1) describes an edge that connectets vertex i to vertex i + 1 |
Remarks
Do not use this method when the graph is in use for pathfinding, as it writes to the internals of the graph
Populate(NativeArray<float2>, NativeArray<Edge>, NativeArray<Edge>)
Populate the graph with vertices and edges
Declaration
public void Populate(NativeArray<float2> vertices, NativeArray<PlatformerGraph.Edge> undirectedEdges, NativeArray<PlatformerGraph.Edge> directedEdges = default)
Parameters
| Type | Name | Description |
|---|---|---|
| NativeArray<float2> | vertices | Vertices to use |
| NativeArray<PlatformerGraph.Edge> | undirectedEdges | Indices connecting vertices together in an undirected fashion. Every pair of indices (i, i+1) describes an edge that connectets vertex i and vertex i + 1 in both directions |
| NativeArray<PlatformerGraph.Edge> | directedEdges | Indices connecting vertices together in a directed fashion. Every pair of indices (i, i+1) describes an edge that connectets vertex i to vertex i + 1. Leave default to not use any directed edges |
Remarks
This method is burst compatible, meaning it can be used inside a job to populate the graph with high performance, if you need frequent updates.
Do not use this method when the graph is in use for pathfinding, as it writes to the internals of the graph. If you need frequent updates, a common technique is to use a double buffer and swap two graphs as one is updated.
Raycast(Ray2D, out PlatformerGraphLocation)
Performs a raycast against the graph. This can then be used as the starting node for a pathfinding request. The location contains information about the edge as well as the exact location the path should start or end.
Declaration
public bool Raycast(Ray2D ray, out PlatformerGraphLocation location)
Parameters
| Type | Name | Description |
|---|---|---|
| Ray2D | ray | The ray to cast |
| PlatformerGraphLocation | location | The location that can be used as part of a path finding request |
Returns
| Type | Description |
|---|---|
| bool | True if there was a hit |
Raycast(Ray2D, int, out PlatformerGraphLocation)
Performs a raycast against the graph. This can then be used as the starting node for a pathfinding request. The location contains information about the edge as well as the exact location the path should start or end.
Declaration
public bool Raycast(Ray2D ray, int flagBitMask, out PlatformerGraphLocation location)
Parameters
| Type | Name | Description |
|---|---|---|
| Ray2D | ray | The ray to cast |
| int | flagBitMask | A bitwise AND is performed on the edge candidates and if any bit is true, the edge is considered. |
| PlatformerGraphLocation | location | The location that can be used as part of a path finding request |
Returns
| Type | Description |
|---|---|
| bool | True if there was a hit |
SetEnterCostAndFlags(int, float, int)
Overwrites the enter cost and flags for an edge at index. The index can be obtained via GetOverlappingEdgeIndices(AABB2D, NativeHashSet<int>), Raycast(Ray2D, int, out PlatformerGraphLocation) or ClosestLocation(float2, float, int, out PlatformerGraphLocation)
Declaration
public void SetEnterCostAndFlags(int edgeIndex, float enterCost, int flags)
Parameters
| Type | Name | Description |
|---|---|---|
| int | edgeIndex | index of the edge to overwrite |
| float | enterCost | new enter cost for the edge. A value of infinity makes the edge unwalkable, essentialy removing it from the graph. Note that raycasting can still return this edge. |
| int | flags | New flags for this edge |
Remarks
This method writes to the graph and as such it cannot be used while pathfinding queries are active on it
SetUnwalkable(int)
Makes an edge unwalkable, assigning it a cost of infinity. The edge index can be obtained via GetOverlappingEdgeIndices(AABB2D, NativeHashSet<int>), Raycast(Ray2D, int, out PlatformerGraphLocation) or ClosestLocation(float2, float, int, out PlatformerGraphLocation)
Declaration
public void SetUnwalkable(int edgeIndex)
Parameters
| Type | Name | Description |
|---|---|---|
| int | edgeIndex | index of the edge to overwrite |
Remarks
This method writes to the graph and as such it cannot be used while pathfinding queries are active on it
TryGetEdgeIndex(int, out int)
Returns the index of an edge from it's Id. Note that Id's are optional so if you didn't supply Id's upon creation, this method will not work. Also note that if more edges share the same Id, this method will also not work.
Declaration
public bool TryGetEdgeIndex(int edgeId, out int edgeIndex)
Parameters
| Type | Name | Description |
|---|---|---|
| int | edgeId | The Id of the edge |
| int | edgeIndex | If successful, set to the index of the edge that carries the Id |
Returns
| Type | Description |
|---|---|
| bool |