83 lines
2.9 KiB
C#
83 lines
2.9 KiB
C#
using Pathfinding.Jobs;
|
|
|
|
namespace Pathfinding.Graphs.Grid.Rules {
|
|
/// <summary>
|
|
/// Modifies nodes based on the layer of the surface under the node.
|
|
///
|
|
/// You can for example make all surfaces with a specific layer make the nodes get a specific tag.
|
|
///
|
|
/// This uses the information from the height testing system to determine which layer the surface is on.
|
|
/// As a consequence, this rule does not do anything when using 2D physics, or height testing is disabled on the grid graph.
|
|
///
|
|
/// [Open online documentation to see images]
|
|
///
|
|
/// See: grid-rules (view in online documentation for working links)
|
|
/// </summary>
|
|
[Pathfinding.Util.Preserve]
|
|
public class RulePerLayerModifications : GridGraphRule {
|
|
public PerLayerRule[] layerRules = new PerLayerRule[0];
|
|
const int SetTagBit = 1 << 30;
|
|
|
|
public struct PerLayerRule {
|
|
/// <summary>Layer this rule applies to</summary>
|
|
public int layer;
|
|
/// <summary>The action to apply to matching nodes</summary>
|
|
public RuleAction action;
|
|
/// <summary>
|
|
/// Tag for the RuleAction.SetTag action.
|
|
/// Must be between 0 and <see cref="Pathfinding.GraphNode.MaxTagIndex"/>
|
|
/// </summary>
|
|
public int tag;
|
|
}
|
|
|
|
public enum RuleAction {
|
|
/// <summary>Sets the tag of all affected nodes to <see cref="PerLayerRule.tag"/></summary>
|
|
SetTag,
|
|
/// <summary>Makes all affected nodes unwalkable</summary>
|
|
MakeUnwalkable,
|
|
}
|
|
|
|
public override void Register (GridGraphRules rules) {
|
|
int[] layerToTag = new int[32];
|
|
bool[] layerToUnwalkable = new bool[32];
|
|
for (int i = 0; i < layerRules.Length; i++) {
|
|
var rule = layerRules[i];
|
|
if (rule.action == RuleAction.SetTag) {
|
|
layerToTag[rule.layer] = SetTagBit | rule.tag;
|
|
} else {
|
|
layerToUnwalkable[rule.layer] = true;
|
|
}
|
|
}
|
|
|
|
rules.AddMainThreadPass(Pass.BeforeConnections, context => {
|
|
if (!context.data.heightHits.IsCreated) {
|
|
UnityEngine.Debug.LogError("RulePerLayerModifications requires height testing to be enabled on the grid graph", context.graph.active);
|
|
return;
|
|
}
|
|
|
|
var raycastHits = context.data.heightHits;
|
|
var nodeWalkable = context.data.nodes.walkable;
|
|
var nodeTags = context.data.nodes.tags;
|
|
var slice = new Slice3D(context.data.nodes.bounds, context.data.heightHitsBounds);
|
|
var size = slice.slice.size;
|
|
for (int y = 0; y < size.y; y++) {
|
|
for (int z = 0; z < size.z; z++) {
|
|
var rowOffset = y * size.x * size.z + z * size.x;
|
|
for (int x = 0; x < size.x; x++) {
|
|
var innerIndex = rowOffset + x;
|
|
var outerIndex = slice.InnerCoordinateToOuterIndex(x, y, z);
|
|
var coll = raycastHits[innerIndex].collider;
|
|
if (coll != null) {
|
|
var layer = coll.gameObject.layer;
|
|
if (layerToUnwalkable[layer]) nodeWalkable[outerIndex] = false;
|
|
var tag = layerToTag[layer];
|
|
if ((tag & SetTagBit) != 0) nodeTags[outerIndex] = tag & 0xFF;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|