diff options
author | chai <215380520@qq.com> | 2024-05-23 10:08:29 +0800 |
---|---|---|
committer | chai <215380520@qq.com> | 2024-05-23 10:08:29 +0800 |
commit | 8722a9920c1f6119bf6e769cba270e63097f8e25 (patch) | |
tree | 2eaf9865de7fb1404546de4a4296553d8f68cc3b /Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Behaviors/AIDestinationSetter.cs | |
parent | 3ba4020b69e5971bb0df7ee08b31d10ea4d01937 (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.cs | 110 |
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; + } + } +} |