From 8722a9920c1f6119bf6e769cba270e63097f8e25 Mon Sep 17 00:00:00 2001 From: chai <215380520@qq.com> Date: Thu, 23 May 2024 10:08:29 +0800 Subject: + astar project --- .../Graphs/Grid/Rules/RuleAnglePenalty.cs | 81 ++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Rules/RuleAnglePenalty.cs (limited to 'Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Rules/RuleAnglePenalty.cs') diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Rules/RuleAnglePenalty.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Rules/RuleAnglePenalty.cs new file mode 100644 index 0000000..1322770 --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Rules/RuleAnglePenalty.cs @@ -0,0 +1,81 @@ +namespace Pathfinding.Graphs.Grid.Rules { + using Pathfinding.Jobs; + using Unity.Jobs; + using Unity.Collections; + using Unity.Burst; + using UnityEngine; + using Unity.Mathematics; + + /// + /// Applies penalty based on the slope of the surface below the node. + /// + /// This is useful if you for example want to discourage agents from walking on steep slopes. + /// + /// The penalty applied is equivalent to: + /// + /// + /// penalty = curve.evaluate(slope angle in degrees) * penaltyScale + /// + /// + /// [Open online documentation to see images] + /// + /// See: grid-rules (view in online documentation for working links) + /// + [Pathfinding.Util.Preserve] + public class RuleAnglePenalty : GridGraphRule { + public float penaltyScale = 10000; + public AnimationCurve curve = AnimationCurve.Linear(0, 0, 90, 1); + NativeArray angleToPenalty; + + public override void Register (GridGraphRules rules) { + if (!angleToPenalty.IsCreated) angleToPenalty = new NativeArray(32, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); + for (int i = 0; i < angleToPenalty.Length; i++) { + angleToPenalty[i] = Mathf.Max(0, curve.Evaluate(90.0f * i / (angleToPenalty.Length - 1)) * penaltyScale); + } + + rules.AddJobSystemPass(Pass.BeforeConnections, context => { + new JobPenaltyAngle { + angleToPenalty = angleToPenalty, + up = context.data.up, + nodeNormals = context.data.nodes.normals, + penalty = context.data.nodes.penalties, + }.Schedule(context.tracker); + }); + } + + public override void DisposeUnmanagedData () { + if (angleToPenalty.IsCreated) angleToPenalty.Dispose(); + } + + [BurstCompile(FloatMode = FloatMode.Fast)] + public struct JobPenaltyAngle : IJob { + public Vector3 up; + + [ReadOnly] + public NativeArray angleToPenalty; + + [ReadOnly] + public NativeArray nodeNormals; + + public NativeArray penalty; + + public void Execute () { + float4 up = new float4(this.up.x, this.up.y, this.up.z, 0); + + for (int i = 0; i < penalty.Length; i++) { + float4 normal = nodeNormals[i]; + if (math.any(normal)) { + float angle = math.acos(math.dot(normal, up)); + // Take the dot product to find out the cosinus of the angle it has + // Add penalty based on the angle from a precalculated array + float x = angle*(angleToPenalty.Length - 1)/math.PI; + int ix = (int)x; + float p1 = angleToPenalty[math.max(ix, 0)]; + float p2 = angleToPenalty[math.min(ix + 1, angleToPenalty.Length - 1)]; + penalty[i] += (uint)math.lerp(p1, p2, x - ix); + } + } + } + } + } +} -- cgit v1.1-26-g67d0