summaryrefslogtreecommitdiff
path: root/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Core/ECS/Jobs/JobManagedOffMeshLinkTransition.cs
blob: 8055cc854497014482faf0281ae6f29297d3008e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#pragma warning disable 0282 // Allows the 'partial' keyword without warnings
#if MODULE_ENTITIES
using Unity.Entities;
using Unity.Collections;
using UnityEngine;
using Unity.Transforms;
using Unity.Collections.LowLevel.Unsafe;

namespace Pathfinding.ECS {
	using Pathfinding;

	public partial struct JobManagedOffMeshLinkTransition : IJobEntity {
		public EntityCommandBuffer commandBuffer;
		public float deltaTime;

		public void Execute (Entity entity, ManagedState state, ref LocalTransform transform, ref AgentMovementPlane movementPlane, ref MovementControl movementControl, ref MovementSettings movementSettings, ref AgentOffMeshLinkTraversal linkInfo, ManagedAgentOffMeshLinkTraversal managedLinkInfo) {
			if (!MoveNext(entity, state, ref transform, ref movementPlane, ref movementControl, ref movementSettings, ref linkInfo, managedLinkInfo, deltaTime)) {
				commandBuffer.RemoveComponent<AgentOffMeshLinkTraversal>(entity);
				commandBuffer.RemoveComponent<ManagedAgentOffMeshLinkTraversal>(entity);
			}
		}

		public static bool MoveNext (Entity entity, ManagedState state, ref LocalTransform transform, ref AgentMovementPlane movementPlane, ref MovementControl movementControl, ref MovementSettings movementSettings, ref AgentOffMeshLinkTraversal linkInfo, ManagedAgentOffMeshLinkTraversal managedLinkInfo, float deltaTime) {
			unsafe {
				managedLinkInfo.context.SetInternalData(entity, ref transform, ref movementPlane, ref movementControl, ref movementSettings, ref linkInfo, state, deltaTime);
			}

			// Initialize the coroutine during the first step.
			// This can also happen if the entity is duplicated, since the coroutine cannot be cloned.
			if (managedLinkInfo.coroutine == null) {
				// If we are calculating a path right now, cancel that path calculation.
				// We don't want to calculate a path while we are traversing an off-mesh link.
				state.CancelCurrentPathRequest();

				if (managedLinkInfo.stateMachine == null) {
					managedLinkInfo.stateMachine = managedLinkInfo.handler != null? managedLinkInfo.handler.GetOffMeshLinkStateMachine(managedLinkInfo.context) : null;
				}
				managedLinkInfo.coroutine = managedLinkInfo.stateMachine != null? managedLinkInfo.stateMachine.OnTraverseOffMeshLink(managedLinkInfo.context).GetEnumerator() : JobStartOffMeshLinkTransition.DefaultOnTraverseOffMeshLink(managedLinkInfo.context).GetEnumerator();
			}

			bool finished;
			bool error = false;
			bool popParts = true;
			try {
				finished = !managedLinkInfo.coroutine.MoveNext();
			} catch (AgentOffMeshLinkTraversalContext.AbortOffMeshLinkTraversal) {
				error = true;
				finished = true;
				popParts = false;
			}
			catch (System.Exception e) {
				Debug.LogException(e, managedLinkInfo.context.gameObject);
				// Teleport the agent to the end of the link as a fallback, if there's an exception
				managedLinkInfo.context.Teleport(managedLinkInfo.context.link.relativeEnd);
				finished = true;
				error = true;
			}

			if (finished) {
				try {
					if (managedLinkInfo.stateMachine != null) {
						if (error) managedLinkInfo.stateMachine.OnAbortTraversingOffMeshLink();
						else managedLinkInfo.stateMachine.OnFinishTraversingOffMeshLink(managedLinkInfo.context);
					}
				} catch (System.Exception e) {
					// If an exception happens when exiting the state machine, log it, and then continue with the cleanup
					Debug.LogException(e, managedLinkInfo.context.gameObject);
				}

				managedLinkInfo.context.Restore();
				if (popParts) {
					// Pop the part leading up to the link, and the link itself
					state.PopNextLinkFromPath();
				}
			}
			return !finished;
		}
	}

	public partial struct JobManagedOffMeshLinkTransitionCleanup : IJobEntity {
		public void Execute (ManagedAgentOffMeshLinkTraversal managedLinkInfo) {
			managedLinkInfo.stateMachine.OnAbortTraversingOffMeshLink();
		}
	}
}
#endif