summaryrefslogtreecommitdiff
path: root/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Behaviors/AIDestinationSetter.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/Behaviors/AIDestinationSetter.cs
parent3ba4020b69e5971bb0df7ee08b31d10ea4d01937 (diff)
+ astar project
Diffstat (limited to 'Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Behaviors/AIDestinationSetter.cs')
-rw-r--r--Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Behaviors/AIDestinationSetter.cs110
1 files changed, 110 insertions, 0 deletions
diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Behaviors/AIDestinationSetter.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Behaviors/AIDestinationSetter.cs
new file mode 100644
index 0000000..5834f6f
--- /dev/null
+++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Behaviors/AIDestinationSetter.cs
@@ -0,0 +1,110 @@
+using UnityEngine;
+using Pathfinding.Util;
+#if MODULE_ENTITIES
+using Unity.Entities;
+#endif
+
+namespace Pathfinding {
+ /// <summary>
+ /// Sets the destination of an AI to the position of a specified object.
+ /// This component should be attached to a GameObject together with a movement script such as AIPath, RichAI or AILerp.
+ /// This component will then make the AI move towards the <see cref="target"/> set on this component.
+ ///
+ /// Essentially the only thing this component does is to set the <see cref="Pathfinding.IAstarAI.destination"/> property to the position of the target every frame.
+ /// There is some additional complexity to make sure that the destination is updated immediately before the AI searches for a path as well, in case the
+ /// target moved since the last Update. There is also some complexity to reduce the performance impact, by using the <see cref="BatchedEvents"/> system to
+ /// process all AIDestinationSetter components in a single batch.
+ ///
+ /// When using ECS, this component is instead added as a managed component to the entity.
+ /// The destination syncing is then handled by the <see cref="SyncDestinationTransformSystem"/> for better performance.
+ ///
+ /// See: <see cref="Pathfinding.IAstarAI.destination"/>
+ ///
+ /// [Open online documentation to see images]
+ /// </summary>
+ [UniqueComponent(tag = "ai.destination")]
+ [AddComponentMenu("Pathfinding/AI/Behaviors/AIDestinationSetter")]
+ [HelpURL("https://arongranberg.com/astar/documentation/stable/aidestinationsetter.html")]
+ public class AIDestinationSetter : VersionedMonoBehaviour
+#if MODULE_ENTITIES
+ , IComponentData, IRuntimeBaker
+#endif
+ {
+ /// <summary>The object that the AI should move to</summary>
+ public Transform target;
+
+ /// <summary>
+ /// If true, the agent will try to align itself with the rotation of the <see cref="target"/>.
+ ///
+ /// This can only be used together with the <see cref="FollowerEntity"/> movement script.
+ /// Other movement scripts will ignore it.
+ ///
+ /// [Open online documentation to see videos]
+ ///
+ /// See: <see cref="FollowerEntity.SetDestination"/>
+ /// </summary>
+ public bool useRotation;
+
+ IAstarAI ai;
+#if MODULE_ENTITIES
+ Entity entity;
+ World world;
+#endif
+
+ void OnEnable () {
+ ai = GetComponent<IAstarAI>();
+#if MODULE_ENTITIES
+ if (ai is FollowerEntity follower) {
+ // This will call OnCreatedEntity on this component, if the entity has already been created.
+ follower.RegisterRuntimeBaker(this);
+ } else
+#endif
+ {
+ // Update the destination right before searching for a path as well.
+ // This is enough in theory, but this script will also update the destination every
+ // frame as the destination is used for debugging and may be used for other things by other
+ // scripts as well. So it makes sense that it is up to date every frame.
+ if (ai != null) ai.onSearchPath += UpdateDestination;
+
+ // Will make OnUpdate be called once every frame with all components.
+ // This is significantly faster than letting Unity call the Update method
+ // on each component.
+ // See https://blog.unity.com/technology/1k-update-calls
+ BatchedEvents.Add(this, BatchedEvents.Event.Update, OnUpdate, 0);
+ }
+ }
+
+ void OnDisable () {
+#if MODULE_ENTITIES
+ if (world != null && world.IsCreated && world.EntityManager.Exists(entity)) {
+ world.EntityManager.RemoveComponent<AIDestinationSetter>(entity);
+ }
+ if (ai != null && !(ai is FollowerEntity)) ai.onSearchPath -= UpdateDestination;
+#else
+ if (ai != null) ai.onSearchPath -= UpdateDestination;
+#endif
+ BatchedEvents.Remove(this);
+ }
+
+#if MODULE_ENTITIES
+ void IRuntimeBaker.OnCreatedEntity (World world, Entity entity) {
+ // Do nothing except add the component. Actual syncing is handled by the SyncDestinationTransformSystem.
+ this.entity = entity;
+ this.world = world;
+ world.EntityManager.AddComponentData<AIDestinationSetter>(entity, this);
+ }
+#endif
+
+ /// <summary>Updates the AI's destination every frame</summary>
+ static void OnUpdate (AIDestinationSetter[] components, int count) {
+ for (int i = 0; i < count; i++) {
+ components[i].UpdateDestination();
+ }
+ }
+
+ /// <summary>Updates the AI's destination immediately</summary>
+ void UpdateDestination () {
+ if (target != null && ai != null) ai.destination = target.position;
+ }
+ }
+}