summaryrefslogtreecommitdiff
path: root/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Jobs/JobRaycastAll.cs
diff options
context:
space:
mode:
authorchai <215380520@qq.com>2024-05-23 10:08:29 +0800
committerchai <215380520@qq.com>2024-05-23 10:08:29 +0800
commit8722a9920c1f6119bf6e769cba270e63097f8e25 (patch)
tree2eaf9865de7fb1404546de4a4296553d8f68cc3b /Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Jobs/JobRaycastAll.cs
parent3ba4020b69e5971bb0df7ee08b31d10ea4d01937 (diff)
+ astar project
Diffstat (limited to 'Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Jobs/JobRaycastAll.cs')
-rw-r--r--Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Jobs/JobRaycastAll.cs121
1 files changed, 121 insertions, 0 deletions
diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Jobs/JobRaycastAll.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Jobs/JobRaycastAll.cs
new file mode 100644
index 0000000..fd34a1d
--- /dev/null
+++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Grid/Jobs/JobRaycastAll.cs
@@ -0,0 +1,121 @@
+using Unity.Burst;
+using Unity.Collections;
+using Unity.Jobs;
+using UnityEngine;
+using Pathfinding.Jobs;
+using Unity.Mathematics;
+
+namespace Pathfinding.Jobs {
+ public struct JobRaycastAll {
+ int maxHits;
+ public readonly float minStep;
+
+ NativeArray<RaycastHit> results;
+ NativeArray<RaycastHit> semiResults;
+ NativeArray<RaycastCommand> commands;
+ public PhysicsScene physicsScene;
+
+ [BurstCompile]
+ private struct JobCreateCommands : IJobParallelFor {
+ public NativeArray<RaycastCommand> commands;
+ [ReadOnly]
+ public NativeArray<RaycastHit> raycastHits;
+
+ public float minStep;
+ public PhysicsScene physicsScene;
+
+ public void Execute (int index) {
+ var rayHit = raycastHits[index];
+
+ if (rayHit.normal != default(Vector3)) {
+ var previousCommand = commands[index];
+ // Little hack to bypass same collider hit in specific cases
+ var point = rayHit.point + previousCommand.direction.normalized * minStep;
+ var distance = previousCommand.distance - (point - previousCommand.from).magnitude;
+#if UNITY_2022_2_OR_NEWER
+ // TODO: In 2022.2 with the 'hit multiple faces' option, this whole class might be redundant.
+ var queryParameters = new QueryParameters(previousCommand.queryParameters.layerMask, false, QueryTriggerInteraction.Ignore, false);
+ commands[index] = new RaycastCommand(physicsScene, point, previousCommand.direction, queryParameters, distance);
+#else
+ commands[index] = new RaycastCommand(point, previousCommand.direction, distance, previousCommand.layerMask, 1);
+#endif
+ } else {
+#if UNITY_2022_2_OR_NEWER
+ // Note: Using a default RaycastCommand may cause Unity to crash.
+ // This seems to be primarily because it assumes a non-zero direction.
+ commands[index] = new RaycastCommand(physicsScene, Vector3.zero, Vector3.up, new QueryParameters(0, false, QueryTriggerInteraction.Ignore, false), 1);
+#else
+ commands[index] = new RaycastCommand(Vector3.zero, Vector3.up, 1, 0, 1);
+#endif
+ }
+ }
+ }
+
+ [BurstCompile]
+ private struct JobCombineResults : IJob {
+ public int maxHits;
+ [ReadOnly]
+ public NativeArray<RaycastHit> semiResults;
+ public NativeArray<RaycastHit> results;
+
+ public void Execute () {
+ int layerStride = semiResults.Length / maxHits;
+
+ for (int i = 0; i < layerStride; i++) {
+ int layerOffset = 0;
+
+ for (int j = maxHits - 1; j >= 0; j--) {
+ if (math.any(semiResults[i + j*layerStride].normal)) {
+ results[i + layerOffset] = semiResults[i + j*layerStride];
+ layerOffset += layerStride;
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>Jobified version of Physics.RaycastNonAlloc.</summary>
+ /// <param name="commands">Array of commands to perform.</param>
+ /// <param name="results">Array to store results in.</param>
+ /// <param name="physicsScene">PhysicsScene to use for the raycasts. Only used in Unity 2022.2 or later.</param>
+ /// <param name="maxHits">Max hits count per command.</param>
+ /// <param name="allocator">Allocator to use for the results array.</param>
+ /// <param name="dependencyTracker">Tracker to use for dependencies.</param>
+ /// <param name="minStep">Minimal distance each Raycast should progress.</param>
+ public JobRaycastAll(NativeArray<RaycastCommand> commands, NativeArray<RaycastHit> results, PhysicsScene physicsScene, int maxHits, Allocator allocator, JobDependencyTracker dependencyTracker, float minStep = 0.0001f) {
+ if (maxHits <= 0) throw new System.ArgumentException("maxHits should be greater than zero");
+ if (results.Length < commands.Length * maxHits) throw new System.ArgumentException("Results array length does not match maxHits count");
+ if (minStep < 0f) throw new System.ArgumentException("minStep should be more or equal to zero");
+
+ this.results = results;
+ this.maxHits = maxHits;
+ this.minStep = minStep;
+ this.commands = commands;
+ this.physicsScene = physicsScene;
+
+ semiResults = dependencyTracker.NewNativeArray<RaycastHit>(maxHits * commands.Length, allocator);
+ }
+
+ public JobHandle Schedule (JobHandle dependency) {
+ for (int i = 0; i < maxHits; i++) {
+ var semiResultsPart = semiResults.GetSubArray(i*commands.Length, commands.Length);
+ dependency = RaycastCommand.ScheduleBatch(commands, semiResultsPart, 128, dependency);
+ if (i < maxHits - 1) {
+ var filter = new JobCreateCommands {
+ commands = commands,
+ raycastHits = semiResultsPart,
+ minStep = minStep,
+ physicsScene = physicsScene,
+ };
+ dependency = filter.Schedule(commands.Length, 256, dependency);
+ }
+ }
+
+ return new JobCombineResults {
+ semiResults = semiResults,
+ maxHits = maxHits,
+ results = results
+ }.Schedule(dependency);
+ }
+ }
+}