summaryrefslogtreecommitdiff
path: root/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Core/ECS/Components/MovementState.cs
blob: 0ea83ad3eff5c636fd0f1cda28a7d5e5b4ffc03b (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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#if MODULE_ENTITIES
using Unity.Entities;
using Unity.Mathematics;

namespace Pathfinding.ECS {
	using Pathfinding;
	using Pathfinding.PID;

	public struct MovementState : IComponentData {
		/// <summary>State of the PID controller for the movement</summary>
		public PIDMovement.PersistentState followerState;

		/// <summary>The next corner in the path</summary>
		public float3 nextCorner;

		/// <summary>
		/// The end of the current path.
		/// Note that the agent may be heading towards an off-mesh link which is not the same as this point.
		/// </summary>
		public float3 endOfPath;

		/// <summary>
		/// The closest point on the navmesh to the agent.
		/// The agent will be snapped to this point.
		/// </summary>
		public float3 closestOnNavmesh;

		/// <summary>
		/// Offset from the agent's internal position to its visual position.
		///
		/// This is used when position smoothing is enabled. Otherwise it is zero.
		/// </summary>
		public float3 positionOffset;

		/// <summary>
		/// The index of the hierarchical node that the agent is currently in.
		/// Will be -1 if the hierarchical node index is not known.
		///
		/// This field is valid during all system updates in the <see cref="AIMovementSystemGroup"/>. It is not guaranteed to be valid after that group has finished running, as graph updates may have changed the graph.
		///
		/// See: <see cref="HierarchicalGraph"/>
		/// </summary>
		public int hierarchicalNodeIndex;

		/// <summary>The remaining distance until the end of the path, or the next off-mesh link</summary>
		public float remainingDistanceToEndOfPart;

		/// <summary>
		/// The current additional rotation that is applied to the agent.
		/// This is used by the local avoidance system to rotate the agent, without this causing a feedback loop.
		///
		/// See: <see cref="ResolvedMovement.targetRotationOffset"/>
		/// </summary>
		public float rotationOffset;

		/// <summary>
		/// An additional, purely visual, rotation offset.
		/// This is used for rotation smoothing, but does not affect the movement of the agent.
		/// </summary>
		public float rotationOffset2;

		/// <summary>
		/// Version number of <see cref="PathTracer.version"/> when the movement state was last updated.
		/// In particular, <see cref="closestOnNavmesh"/>, <see cref="nextCorner"/>, <see cref="endOfPath"/>, <see cref="remainingDistanceToEndOfPart"/>, <see cref="reachedDestination"/> and <see cref="reachedEndOfPath"/> will only
		/// be considered up to date if this is equal to the current version number of the path tracer.
		/// </summary>
		public ushort pathTracerVersion;

		/// <summary>Bitmask for various flags</summary>
		ushort flags;

		const int ReachedDestinationFlag = 1 << 0;
		const int reachedDestinationAndOrientationFlag = 1 << 1;
		const int ReachedEndOfPathFlag = 1 << 2;
		const int reachedEndOfPathAndOrientationFlag = 1 << 3;
		const int ReachedEndOfPartFlag = 1 << 4;
		const int TraversingLastPartFlag = 1 << 5;

		/// <summary>
		/// True if the agent has reached its destination.
		/// The destination will be considered reached if all of these conditions are met:
		/// - The agent has a path
		/// - The path is not stale
		/// - The destination is not significantly below the agent's feet.
		/// - The destination is not significantly above the agent's head.
		/// - The agent is on the last part of the path (there are no more remaining off-mesh links).
		/// - The remaining distance to the end of the path + the distance from the end of the path to the destination is less than <see cref="MovementSettings.stopDistance"/>.
		/// </summary>
		public bool reachedDestination {
			get => (flags & ReachedDestinationFlag) != 0;
			set => flags = (ushort)((flags & ~ReachedDestinationFlag) | (value ? ReachedDestinationFlag : 0));
		}

		/// <summary>
		/// True if the agent has reached its destination and is facing the desired orientation.
		/// This will become true if all of these conditions are met:
		/// - <see cref="reachedDestination"/> is true
		/// - The agent is facing the desired facing direction as specified in <see cref="DestinationPoint.facingDirection"/>.
		/// </summary>
		public bool reachedDestinationAndOrientation {
			get => (flags & reachedDestinationAndOrientationFlag) != 0;
			set => flags = (ushort)((flags & ~reachedDestinationAndOrientationFlag) | (value ? reachedDestinationAndOrientationFlag : 0));
		}

		/// <summary>
		/// True if the agent has reached the end of the path.
		/// The end of the path will be considered reached if all of these conditions are met:
		/// - The agent has a path
		/// - The path is not stale
		/// - The end of the path is not significantly below the agent's feet.
		/// - The end of the path is not significantly above the agent's head.
		/// - The agent is on the last part of the path (there are no more remaining off-mesh links).
		/// - The remaining distance to the end of the path is less than <see cref="MovementSettings.stopDistance"/>.
		/// </summary>
		public bool reachedEndOfPath {
			get => (flags & ReachedEndOfPathFlag) != 0;
			set => flags = (ushort)((flags & ~ReachedEndOfPathFlag) | (value ? ReachedEndOfPathFlag : 0));
		}

		/// <summary>
		/// True if the agent has reached its destination and is facing the desired orientation.
		/// This will become true if all of these conditions are met:
		/// - <see cref="reachedEndOfPath"/> is true
		/// - The agent is facing the desired facing direction as specified in <see cref="DestinationPoint.facingDirection"/>.
		/// </summary>
		public bool reachedEndOfPathAndOrientation {
			get => (flags & reachedEndOfPathAndOrientationFlag) != 0;
			set => flags = (ushort)((flags & ~reachedEndOfPathAndOrientationFlag) | (value ? reachedEndOfPathAndOrientationFlag : 0));
		}

		/// <summary>
		/// True if the agent has reached the end of the current part in the path.
		/// The end of the current part will be considered reached if all of these conditions are met:
		/// - The agent has a path
		/// - The path is not stale
		/// - The end of the current part is not significantly below the agent's feet.
		/// - The end of the current part is not significantly above the agent's head.
		/// - The remaining distance to the end of the part is not significantly larger than the agent's radius.
		/// </summary>
		public bool reachedEndOfPart {
			get => (flags & ReachedEndOfPartFlag) != 0;
			set => flags = (ushort)((flags & ~ReachedEndOfPartFlag) | (value ? ReachedEndOfPartFlag : 0));
		}

		/// <summary>
		/// True if the agent is traversing the last part of the path.
		///
		/// If false, the agent will have to traverse at least one off-mesh link before it gets to its destination.
		/// </summary>
		public bool traversingLastPart {
			get => (flags & TraversingLastPartFlag) != 0;
			set => flags = (ushort)((flags & ~TraversingLastPartFlag) | (value ? TraversingLastPartFlag : 0));
		}

		/// <summary>
		/// The index of the graph that the agent is currently traversing.
		///
		/// Will be <see cref="GraphNode.InvalidGraphIndex"/> if the agent has no path, or the node that the agent is traversing has been destroyed.
		/// </summary>
		public uint graphIndex {
			get => (uint)(flags >> 8);
			internal set => flags = (ushort)((flags & 0xFF) | (ushort)(value << 8));
		}

		/// <summary>
		/// True if the agent is currently on a valid node.
		///
		/// This is true if the agent has a path, and the node that the agent is traversing is walkable and not destroyed.
		///
		/// If false, the <see cref="hierarchicalNodeIndex"/> and <see cref="graphIndex"/> fields are invalid.
		/// </summary>
		public bool isOnValidNode => hierarchicalNodeIndex != -1;

		public MovementState(UnityEngine.Vector3 agentPosition) {
			this = default;
			SetPathIsEmpty(agentPosition);
		}

		/// <summary>Sets the appropriate fields to indicate that the agent has no path</summary>
		public void SetPathIsEmpty (UnityEngine.Vector3 agentPosition) {
			nextCorner = agentPosition;
			endOfPath = agentPosition;
			closestOnNavmesh = agentPosition;
			hierarchicalNodeIndex = -1;
			remainingDistanceToEndOfPart = float.PositiveInfinity;
			reachedEndOfPath = false;
			reachedDestination = false;
			reachedEndOfPart = false;
			reachedDestinationAndOrientation = false;
			reachedEndOfPathAndOrientation = false;
			traversingLastPart = true;
			graphIndex = GraphNode.InvalidGraphIndex;
		}
	}
}
#endif