123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- namespace Pathfinding {
- using Pathfinding.RVO;
- using Pathfinding.Util;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [AddComponentMenu("Pathfinding/AI/AIPath (2D,3D)")]
- public partial class AIPath : AIBase, IAstarAI {
-
-
-
-
-
-
-
-
-
-
-
- public float maxAcceleration = -2.5f;
-
-
-
-
-
- [UnityEngine.Serialization.FormerlySerializedAs("turningSpeed")]
- public float rotationSpeed = 360;
-
- public float slowdownDistance = 0.6F;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public float pickNextWaypointDist = 2;
-
-
-
-
- public float endReachedDistance = 0.2F;
-
- public bool alwaysDrawGizmos;
-
-
-
-
- public bool slowWhenNotFacingTarget = true;
-
-
-
-
-
-
-
-
-
-
- public CloseToDestinationMode whenCloseToDestination = CloseToDestinationMode.Stop;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public bool constrainInsideGraph = false;
-
- protected Path path;
-
- protected PathInterpolator interpolator = new PathInterpolator();
- #region IAstarAI implementation
-
- public override void Teleport (Vector3 newPosition, bool clearPath = true) {
- reachedEndOfPath = false;
- base.Teleport(newPosition, clearPath);
- }
-
- public float remainingDistance {
- get {
- return interpolator.valid ? interpolator.remainingDistance + movementPlane.ToPlane(interpolator.position - position).magnitude : float.PositiveInfinity;
- }
- }
-
- public bool reachedDestination {
- get {
- if (!reachedEndOfPath) return false;
- if (!interpolator.valid || remainingDistance + movementPlane.ToPlane(destination - interpolator.endPoint).magnitude > endReachedDistance) return false;
-
- if (orientation != OrientationMode.YAxisForward) {
-
- float yDifference;
- movementPlane.ToPlane(destination - position, out yDifference);
- var h = tr.localScale.y * height;
- if (yDifference > h || yDifference < -h*0.5) return false;
- }
- return true;
- }
- }
-
- public bool reachedEndOfPath { get; protected set; }
-
- public bool hasPath {
- get {
- return interpolator.valid;
- }
- }
-
- public bool pathPending {
- get {
- return waitingForPathCalculation;
- }
- }
-
- public Vector3 steeringTarget {
- get {
- return interpolator.valid ? interpolator.position : position;
- }
- }
-
- float IAstarAI.radius { get { return radius; } set { radius = value; } }
-
- float IAstarAI.height { get { return height; } set { height = value; } }
-
- float IAstarAI.maxSpeed { get { return maxSpeed; } set { maxSpeed = value; } }
-
- bool IAstarAI.canSearch { get { return canSearch; } set { canSearch = value; } }
-
- bool IAstarAI.canMove { get { return canMove; } set { canMove = value; } }
- #endregion
-
- public void GetRemainingPath (List<Vector3> buffer, out bool stale) {
- buffer.Clear();
- buffer.Add(position);
- if (!interpolator.valid) {
- stale = true;
- return;
- }
- stale = false;
- interpolator.GetRemainingPath(buffer);
- }
- protected override void OnDisable () {
- base.OnDisable();
-
- if (path != null) path.Release(this);
- path = null;
- interpolator.SetPath(null);
- reachedEndOfPath = false;
- }
-
-
-
-
-
-
-
-
- public virtual void OnTargetReached () {
- }
-
-
-
-
-
- protected override void OnPathComplete (Path newPath) {
- ABPath p = newPath as ABPath;
- if (p == null) throw new System.Exception("This function only handles ABPaths, do not use special path types");
- waitingForPathCalculation = false;
-
-
- p.Claim(this);
-
-
- if (p.error) {
- p.Release(this);
- SetPath(null);
- return;
- }
-
- if (path != null) path.Release(this);
-
- path = p;
-
-
-
- if (path is RandomPath rpath) {
- destination = rpath.originalEndPoint;
- } else if (path is MultiTargetPath mpath) {
- destination = mpath.originalEndPoint;
- }
-
- if (path.vectorPath.Count == 1) path.vectorPath.Add(path.vectorPath[0]);
- interpolator.SetPath(path.vectorPath);
- var graph = path.path.Count > 0 ? AstarData.GetGraph(path.path[0]) as ITransformedGraph : null;
- movementPlane = graph != null ? graph.transform : (orientation == OrientationMode.YAxisForward ? new GraphTransform(Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(-90, 270, 90), Vector3.one)) : GraphTransform.identityTransform);
-
- reachedEndOfPath = false;
-
-
-
-
-
- interpolator.MoveToLocallyClosestPoint((GetFeetPosition() + p.originalStartPoint) * 0.5f);
- interpolator.MoveToLocallyClosestPoint(GetFeetPosition());
-
-
-
- interpolator.MoveToCircleIntersection2D(position, pickNextWaypointDist, movementPlane);
- var distanceToEnd = remainingDistance;
- if (distanceToEnd <= endReachedDistance) {
- reachedEndOfPath = true;
- OnTargetReached();
- }
- }
- protected override void ClearPath () {
- CancelCurrentPathRequest();
- if (path != null) path.Release(this);
- path = null;
- interpolator.SetPath(null);
- reachedEndOfPath = false;
- }
-
- protected override void MovementUpdateInternal (float deltaTime, out Vector3 nextPosition, out Quaternion nextRotation) {
- float currentAcceleration = maxAcceleration;
-
- if (currentAcceleration < 0) currentAcceleration *= -maxSpeed;
- if (updatePosition) {
-
-
- simulatedPosition = tr.position;
- }
- if (updateRotation) simulatedRotation = tr.rotation;
- var currentPosition = simulatedPosition;
-
- interpolator.MoveToCircleIntersection2D(currentPosition, pickNextWaypointDist, movementPlane);
- var dir = movementPlane.ToPlane(steeringTarget - currentPosition);
-
- float distanceToEnd = dir.magnitude + Mathf.Max(0, interpolator.remainingDistance);
-
- var prevTargetReached = reachedEndOfPath;
- reachedEndOfPath = distanceToEnd <= endReachedDistance && interpolator.valid;
- if (!prevTargetReached && reachedEndOfPath) OnTargetReached();
- float slowdown;
-
- var forwards = movementPlane.ToPlane(simulatedRotation * (orientation == OrientationMode.YAxisForward ? Vector3.up : Vector3.forward));
-
- bool stopped = isStopped || (reachedDestination && whenCloseToDestination == CloseToDestinationMode.Stop);
- if (interpolator.valid && !stopped) {
-
-
-
- slowdown = distanceToEnd < slowdownDistance? Mathf.Sqrt(distanceToEnd / slowdownDistance) : 1;
- if (reachedEndOfPath && whenCloseToDestination == CloseToDestinationMode.Stop) {
-
- velocity2D -= Vector2.ClampMagnitude(velocity2D, currentAcceleration * deltaTime);
- } else {
- velocity2D += MovementUtilities.CalculateAccelerationToReachPoint(dir, dir.normalized*maxSpeed, velocity2D, currentAcceleration, rotationSpeed, maxSpeed, forwards) * deltaTime;
- }
- } else {
- slowdown = 1;
-
- velocity2D -= Vector2.ClampMagnitude(velocity2D, currentAcceleration * deltaTime);
- }
- velocity2D = MovementUtilities.ClampVelocity(velocity2D, maxSpeed, slowdown, slowWhenNotFacingTarget && enableRotation, forwards);
- ApplyGravity(deltaTime);
- if (rvoController != null && rvoController.enabled) {
-
-
-
-
-
-
-
-
- var rvoTarget = currentPosition + movementPlane.ToWorld(Vector2.ClampMagnitude(velocity2D, distanceToEnd), 0f);
- rvoController.SetTarget(rvoTarget, velocity2D.magnitude, maxSpeed);
- }
-
- var delta2D = lastDeltaPosition = CalculateDeltaToMoveThisFrame(movementPlane.ToPlane(currentPosition), distanceToEnd, deltaTime);
- nextPosition = currentPosition + movementPlane.ToWorld(delta2D, verticalVelocity * lastDeltaTime);
- CalculateNextRotation(slowdown, out nextRotation);
- }
- protected virtual void CalculateNextRotation (float slowdown, out Quaternion nextRotation) {
- if (lastDeltaTime > 0.00001f && enableRotation) {
- Vector2 desiredRotationDirection;
- if (rvoController != null && rvoController.enabled) {
-
-
-
-
- var actualVelocity = lastDeltaPosition/lastDeltaTime;
- desiredRotationDirection = Vector2.Lerp(velocity2D, actualVelocity, 4 * actualVelocity.magnitude / (maxSpeed + 0.0001f));
- } else {
- desiredRotationDirection = velocity2D;
- }
-
-
- var currentRotationSpeed = rotationSpeed * Mathf.Max(0, (slowdown - 0.3f) / 0.7f);
- nextRotation = SimulateRotationTowards(desiredRotationDirection, currentRotationSpeed * lastDeltaTime);
- } else {
-
- nextRotation = rotation;
- }
- }
- static NNConstraint cachedNNConstraint = NNConstraint.Default;
- protected override Vector3 ClampToNavmesh (Vector3 position, out bool positionChanged) {
- if (constrainInsideGraph) {
- cachedNNConstraint.tags = seeker.traversableTags;
- cachedNNConstraint.graphMask = seeker.graphMask;
- cachedNNConstraint.distanceXZ = true;
- var clampedPosition = AstarPath.active.GetNearest(position, cachedNNConstraint).position;
-
-
- var difference = movementPlane.ToPlane(clampedPosition - position);
- float sqrDifference = difference.sqrMagnitude;
- if (sqrDifference > 0.001f*0.001f) {
-
-
- velocity2D -= difference * Vector2.Dot(difference, velocity2D) / sqrDifference;
-
-
-
- if (rvoController != null && rvoController.enabled) {
- rvoController.SetCollisionNormal(difference);
- }
- positionChanged = true;
-
- return position + movementPlane.ToWorld(difference);
- }
- }
- positionChanged = false;
- return position;
- }
- #if UNITY_EDITOR
- [System.NonSerialized]
- int gizmoHash = 0;
- [System.NonSerialized]
- float lastChangedTime = float.NegativeInfinity;
- protected static readonly Color GizmoColor = new Color(46.0f/255, 104.0f/255, 201.0f/255);
- protected override void OnDrawGizmos () {
- base.OnDrawGizmos();
- if (alwaysDrawGizmos) OnDrawGizmosInternal();
- }
- protected override void OnDrawGizmosSelected () {
- base.OnDrawGizmosSelected();
- if (!alwaysDrawGizmos) OnDrawGizmosInternal();
- }
- void OnDrawGizmosInternal () {
- var newGizmoHash = pickNextWaypointDist.GetHashCode() ^ slowdownDistance.GetHashCode() ^ endReachedDistance.GetHashCode();
- if (newGizmoHash != gizmoHash && gizmoHash != 0) lastChangedTime = Time.realtimeSinceStartup;
- gizmoHash = newGizmoHash;
- float alpha = alwaysDrawGizmos ? 1 : Mathf.SmoothStep(1, 0, (Time.realtimeSinceStartup - lastChangedTime - 5f)/0.5f) * (UnityEditor.Selection.gameObjects.Length == 1 ? 1 : 0);
- if (alpha > 0) {
-
- if (!alwaysDrawGizmos) UnityEditor.SceneView.RepaintAll();
- Draw.Gizmos.Line(position, steeringTarget, GizmoColor * new Color(1, 1, 1, alpha));
- Gizmos.matrix = Matrix4x4.TRS(position, transform.rotation * (orientation == OrientationMode.YAxisForward ? Quaternion.Euler(-90, 0, 0) : Quaternion.identity), Vector3.one);
- Draw.Gizmos.CircleXZ(Vector3.zero, pickNextWaypointDist, GizmoColor * new Color(1, 1, 1, alpha));
- Draw.Gizmos.CircleXZ(Vector3.zero, slowdownDistance, Color.Lerp(GizmoColor, Color.red, 0.5f) * new Color(1, 1, 1, alpha));
- Draw.Gizmos.CircleXZ(Vector3.zero, endReachedDistance, Color.Lerp(GizmoColor, Color.red, 0.8f) * new Color(1, 1, 1, alpha));
- }
- }
- #endif
- protected override int OnUpgradeSerializedData (int version, bool unityThread) {
-
- if (version < 1) rotationSpeed *= 90;
- return base.OnUpgradeSerializedData(version, unityThread);
- }
- }
- }
|