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/ExampleScenes/ExampleScripts/MineBotAnimation.cs | |
parent | 3ba4020b69e5971bb0df7ee08b31d10ea4d01937 (diff) |
+ astar project
Diffstat (limited to 'Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/ExampleScenes/ExampleScripts/MineBotAnimation.cs')
-rw-r--r-- | Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/ExampleScenes/ExampleScripts/MineBotAnimation.cs | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/ExampleScenes/ExampleScripts/MineBotAnimation.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/ExampleScenes/ExampleScripts/MineBotAnimation.cs new file mode 100644 index 0000000..3fcab2a --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/ExampleScenes/ExampleScripts/MineBotAnimation.cs @@ -0,0 +1,109 @@ +using Pathfinding.Util; +using UnityEngine; + +namespace Pathfinding.Examples { + /// <summary> + /// Animation helper specifically made for the spider robot in the example scenes. + /// The spider robot (or mine-bot) which has been copied from the Unity Example Project + /// can have this script attached to be able to pathfind around with animations working properly. + /// + /// This script should be attached to a parent GameObject however since the original bot has Z+ as up. + /// This component requires Z+ to be forward and Y+ to be up. + /// + /// A movement script (e.g AIPath) must also be attached to the same GameObject to actually move the unit. + /// + /// This script will forward the movement speed to the animator component (<see cref="anim)"/> using the following animator parameter: + /// - NormalizedSpeed: Movement speed in world units, divided by <see cref="MineBotAnimation.naturalSpeed"/> and the character's scale. This will be 1 when the agent is moving at the natural speed, and 0 when it is standing still. + /// + /// When the end of path is reached, if the <see cref="endOfPathEffect"/> is not null, it will be instantiated at the current position. However, a check will be + /// done so that it won't spawn effects too close to the previous spawn-point. + /// [Open online documentation to see images] + /// </summary> + [HelpURL("https://arongranberg.com/astar/documentation/stable/minebotanimation.html")] + public class MineBotAnimation : VersionedMonoBehaviour { + /// <summary>Animator component</summary> + public Animator anim; + + /// <summary> + /// Effect which will be instantiated when end of path is reached. + /// See: <see cref="OnTargetReached"/> + /// </summary> + public GameObject endOfPathEffect; + + /// <summary> + /// The natural movement speed is the speed that the animations are designed for. + /// + /// One can for example configure the animator to speed up the animation if the agent moves faster than this, or slow it down if the agent moves slower than this. + /// </summary> + public float naturalSpeed = 5f; + + bool isAtEndOfPath; + + IAstarAI ai; + Transform tr; + + const string NormalizedSpeedKey = "NormalizedSpeed"; + static int NormalizedSpeedKeyHash = Animator.StringToHash(NormalizedSpeedKey); + + protected override void Awake () { + base.Awake(); + ai = GetComponent<IAstarAI>(); + tr = GetComponent<Transform>(); + if (anim != null && !HasParameter(anim, NormalizedSpeedKey)) { + Debug.LogError($"No '{NormalizedSpeedKey}' parameter found on the animator. The animator must have a float parameter called '{NormalizedSpeedKey}'", this); + enabled = false; + } + } + + static bool HasParameter (Animator animator, string paramName) { + foreach (AnimatorControllerParameter param in animator.parameters) if (param.name == paramName) return true; + return false; + } + + /// <summary>Point for the last spawn of <see cref="endOfPathEffect"/></summary> + protected Vector3 lastTarget; + + /// <summary> + /// Called when the end of path has been reached. + /// An effect (<see cref="endOfPathEffect)"/> is spawned when this function is called + /// However, since paths are recalculated quite often, we only spawn the effect + /// when the current position is some distance away from the previous spawn-point + /// </summary> + void OnTargetReached () { + if (endOfPathEffect != null && Vector3.Distance(tr.position, lastTarget) > 1) { + GameObject.Instantiate(endOfPathEffect, tr.position, tr.rotation); + lastTarget = tr.position; + } + } + + void OnEnable () { + // Process all components in a batched fashion to avoid Unity overhead + // See https://blog.unity.com/engine-platform/10000-update-calls + BatchedEvents.Add(this, BatchedEvents.Event.Update, OnUpdate); + } + + void OnDisable () { + BatchedEvents.Remove(this); + } + + static void OnUpdate (MineBotAnimation[] components, int count) { + for (int i = 0; i < count; i++) components[i].OnUpdate(); + } + + void OnUpdate () { + if (ai == null) return; + + if (ai.reachedEndOfPath) { + if (!isAtEndOfPath) OnTargetReached(); + isAtEndOfPath = true; + } else isAtEndOfPath = false; + + // Calculate the velocity relative to this transform's orientation + Vector3 relVelocity = tr.InverseTransformDirection(ai.velocity); + relVelocity.y = 0; + + // Speed relative to the character size + anim.SetFloat(NormalizedSpeedKeyHash, relVelocity.magnitude / (naturalSpeed * anim.transform.lossyScale.x)); + } + } +} |