123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790 |
- using UnityEngine;
- using System.Collections;
- using UnityEngine.Serialization;
- namespace Pathfinding {
- using Pathfinding.RVO;
- using Pathfinding.Util;
-
-
-
-
-
-
-
-
- [RequireComponent(typeof(Seeker))]
- public abstract class AIBase : VersionedMonoBehaviour {
-
- public float radius = 0.5f;
-
- public float height = 2;
-
-
-
-
-
-
-
-
-
-
-
-
- public float repathRate {
- get {
- return this.autoRepath.period;
- }
- set {
- this.autoRepath.period = value;
- }
- }
-
-
-
-
- public bool canSearch {
- get {
- return this.autoRepath.mode != AutoRepathPolicy.Mode.Never;
- }
- set {
- if (value) {
- if (this.autoRepath.mode == AutoRepathPolicy.Mode.Never) {
- this.autoRepath.mode = AutoRepathPolicy.Mode.EveryNSeconds;
- }
- } else {
- this.autoRepath.mode = AutoRepathPolicy.Mode.Never;
- }
- }
- }
-
- public bool canMove = true;
-
- [UnityEngine.Serialization.FormerlySerializedAs("speed")]
- public float maxSpeed = 1;
-
-
-
-
-
- public Vector3 gravity = new Vector3(float.NaN, float.NaN, float.NaN);
-
-
-
-
-
-
-
- public LayerMask groundMask = -1;
-
-
-
-
-
-
-
-
-
-
- [System.Obsolete("Use the height property instead (2x this value)")]
- public float centerOffset {
- get { return height * 0.5f; } set { height = value * 2; }
- }
- [SerializeField]
- [HideInInspector]
- [FormerlySerializedAs("centerOffset")]
- float centerOffsetCompatibility = float.NaN;
- [SerializeField]
- [HideInInspector]
- [UnityEngine.Serialization.FormerlySerializedAs("repathRate")]
- float repathRateCompatibility = float.NaN;
- [SerializeField]
- [HideInInspector]
- [UnityEngine.Serialization.FormerlySerializedAs("canSearch")]
- [UnityEngine.Serialization.FormerlySerializedAs("repeatedlySearchPaths")]
- bool canSearchCompability = false;
-
-
-
-
-
-
-
-
-
-
-
- [UnityEngine.Serialization.FormerlySerializedAs("rotationIn2D")]
- public OrientationMode orientation = OrientationMode.ZAxisForward;
-
-
-
-
-
- [System.Obsolete("Use orientation instead")]
- public bool rotationIn2D {
- get { return orientation == OrientationMode.YAxisForward; }
- set { orientation = value ? OrientationMode.YAxisForward : OrientationMode.ZAxisForward; }
- }
-
-
-
-
- public bool enableRotation = true;
-
-
-
-
- protected Vector3 simulatedPosition;
-
-
-
-
- protected Quaternion simulatedRotation;
-
-
-
-
-
-
-
- public Vector3 position { get { return updatePosition ? tr.position : simulatedPosition; } }
-
-
-
-
- public Quaternion rotation {
- get { return updateRotation ? tr.rotation : simulatedRotation; }
- set {
- if (updateRotation) {
- tr.rotation = value;
- } else {
- simulatedRotation = value;
- }
- }
- }
-
- Vector3 accumulatedMovementDelta = Vector3.zero;
-
-
-
-
- protected Vector2 velocity2D;
-
-
-
-
-
-
-
- protected float verticalVelocity;
-
- protected Seeker seeker;
-
- protected Transform tr;
-
- protected Rigidbody rigid;
-
- protected Rigidbody2D rigid2D;
-
- protected CharacterController controller;
-
- protected RVOController rvoController;
-
-
-
-
-
- public IMovementPlane movementPlane = GraphTransform.identityTransform;
-
-
-
-
-
-
-
-
-
-
-
-
- [System.NonSerialized]
- public bool updatePosition = true;
-
-
-
-
-
-
-
- [System.NonSerialized]
- public bool updateRotation = true;
-
-
-
-
- public AutoRepathPolicy autoRepath = new AutoRepathPolicy();
-
- protected bool usingGravity { get; set; }
-
- protected float lastDeltaTime;
-
- protected int prevFrame;
-
- protected Vector3 prevPosition1;
-
- protected Vector3 prevPosition2;
-
- protected Vector2 lastDeltaPosition;
-
- protected bool waitingForPathCalculation = false;
- [UnityEngine.Serialization.FormerlySerializedAs("target")][SerializeField][HideInInspector]
- Transform targetCompatibility;
-
-
-
-
-
- bool startHasRun = false;
-
-
-
-
-
-
-
-
-
- [System.Obsolete("Use the destination property or the AIDestinationSetter component instead")]
- public Transform target {
- get {
- var setter = GetComponent<AIDestinationSetter>();
- return setter != null ? setter.target : null;
- }
- set {
- targetCompatibility = null;
- var setter = GetComponent<AIDestinationSetter>();
- if (setter == null) setter = gameObject.AddComponent<AIDestinationSetter>();
- setter.target = value;
- destination = value != null ? value.position : new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
- }
- }
-
- public Vector3 destination { get; set; }
-
- public Vector3 velocity {
- get {
- return lastDeltaTime > 0.000001f ? (prevPosition1 - prevPosition2) / lastDeltaTime : Vector3.zero;
- }
- }
-
-
-
-
- public Vector3 desiredVelocity { get { return lastDeltaTime > 0.00001f ? movementPlane.ToWorld(lastDeltaPosition / lastDeltaTime, verticalVelocity) : Vector3.zero; } }
-
- public bool isStopped { get; set; }
-
- public System.Action onSearchPath { get; set; }
-
- protected virtual bool shouldRecalculatePath {
- get {
- return !waitingForPathCalculation && autoRepath.ShouldRecalculatePath(position, radius, destination);
- }
- }
- protected AIBase () {
-
-
-
- destination = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
- }
-
-
-
-
-
-
- public virtual void FindComponents () {
- tr = transform;
- seeker = GetComponent<Seeker>();
- rvoController = GetComponent<RVOController>();
-
- controller = GetComponent<CharacterController>();
- rigid = GetComponent<Rigidbody>();
- rigid2D = GetComponent<Rigidbody2D>();
- }
-
- protected virtual void OnEnable () {
- FindComponents();
-
- seeker.pathCallback += OnPathComplete;
- Init();
- }
-
-
-
-
-
- protected virtual void Start () {
- startHasRun = true;
- Init();
- }
- void Init () {
- if (startHasRun) {
-
-
- if (canMove) Teleport(position, false);
- autoRepath.Reset();
- if (shouldRecalculatePath) SearchPath();
- }
- }
-
- public virtual void Teleport (Vector3 newPosition, bool clearPath = true) {
- if (clearPath) ClearPath();
- prevPosition1 = prevPosition2 = simulatedPosition = newPosition;
- if (updatePosition) tr.position = newPosition;
- if (rvoController != null) rvoController.Move(Vector3.zero);
- if (clearPath) SearchPath();
- }
- protected void CancelCurrentPathRequest () {
- waitingForPathCalculation = false;
-
- if (seeker != null) seeker.CancelCurrentPathRequest();
- }
- protected virtual void OnDisable () {
- ClearPath();
-
- seeker.pathCallback -= OnPathComplete;
- velocity2D = Vector3.zero;
- accumulatedMovementDelta = Vector3.zero;
- verticalVelocity = 0f;
- lastDeltaTime = 0;
- }
-
-
-
-
- protected virtual void Update () {
- if (shouldRecalculatePath) SearchPath();
-
-
-
- usingGravity = !(gravity == Vector3.zero) && (!updatePosition || ((rigid == null || rigid.isKinematic) && (rigid2D == null || rigid2D.isKinematic)));
- if (rigid == null && rigid2D == null && canMove) {
- Vector3 nextPosition;
- Quaternion nextRotation;
- MovementUpdate(Time.deltaTime, out nextPosition, out nextRotation);
- FinalizeMovement(nextPosition, nextRotation);
- }
- }
-
-
-
-
- protected virtual void FixedUpdate () {
- if (!(rigid == null && rigid2D == null) && canMove) {
- Vector3 nextPosition;
- Quaternion nextRotation;
- MovementUpdate(Time.fixedDeltaTime, out nextPosition, out nextRotation);
- FinalizeMovement(nextPosition, nextRotation);
- }
- }
-
- public void MovementUpdate (float deltaTime, out Vector3 nextPosition, out Quaternion nextRotation) {
- lastDeltaTime = deltaTime;
- MovementUpdateInternal(deltaTime, out nextPosition, out nextRotation);
- }
-
- protected abstract void MovementUpdateInternal(float deltaTime, out Vector3 nextPosition, out Quaternion nextRotation);
-
-
-
-
-
-
- protected virtual void CalculatePathRequestEndpoints (out Vector3 start, out Vector3 end) {
- start = GetFeetPosition();
- end = destination;
- }
-
- public virtual void SearchPath () {
- if (float.IsPositiveInfinity(destination.x)) return;
- if (onSearchPath != null) onSearchPath();
- Vector3 start, end;
- CalculatePathRequestEndpoints(out start, out end);
-
- ABPath p = ABPath.Construct(start, end, null);
- SetPath(p, false);
- }
-
-
-
-
-
-
-
-
- public virtual Vector3 GetFeetPosition () {
- return position;
- }
-
- protected abstract void OnPathComplete(Path newPath);
-
-
-
-
-
-
-
-
- protected abstract void ClearPath();
-
- public void SetPath (Path path, bool updateDestinationFromPath = true) {
- if (updateDestinationFromPath && path is ABPath abPath && !(path is RandomPath)) {
- this.destination = abPath.originalEndPoint;
- }
- if (path == null) {
- CancelCurrentPathRequest();
- ClearPath();
- } else if (path.PipelineState == PathState.Created) {
-
- waitingForPathCalculation = true;
- seeker.CancelCurrentPathRequest();
- seeker.StartPath(path);
- autoRepath.DidRecalculatePath(destination);
- } else if (path.PipelineState == PathState.Returned) {
-
-
- if (seeker.GetCurrentPath() != path) seeker.CancelCurrentPathRequest();
- else throw new System.ArgumentException("If you calculate the path using seeker.StartPath then this script will pick up the calculated path anyway as it listens for all paths the Seeker finishes calculating. You should not call SetPath in that case.");
- OnPathComplete(path);
- } else {
-
- throw new System.ArgumentException("You must call the SetPath method with a path that either has been completely calculated or one whose path calculation has not been started at all. It looks like the path calculation for the path you tried to use has been started, but is not yet finished.");
- }
- }
-
-
-
-
-
- protected void ApplyGravity (float deltaTime) {
-
- if (usingGravity) {
- float verticalGravity;
- velocity2D += movementPlane.ToPlane(deltaTime * (float.IsNaN(gravity.x) ? Physics.gravity : gravity), out verticalGravity);
- verticalVelocity += verticalGravity;
- } else {
- verticalVelocity = 0;
- }
- }
-
- protected Vector2 CalculateDeltaToMoveThisFrame (Vector2 position, float distanceToEndOfPath, float deltaTime) {
- if (rvoController != null && rvoController.enabled) {
-
-
- return movementPlane.ToPlane(rvoController.CalculateMovementDelta(movementPlane.ToWorld(position, 0), deltaTime));
- }
-
- return Vector2.ClampMagnitude(velocity2D * deltaTime, distanceToEndOfPath);
- }
-
-
-
-
-
-
-
-
-
-
- public Quaternion SimulateRotationTowards (Vector3 direction, float maxDegrees) {
- return SimulateRotationTowards(movementPlane.ToPlane(direction), maxDegrees);
- }
-
-
-
-
-
-
-
-
-
-
- protected Quaternion SimulateRotationTowards (Vector2 direction, float maxDegrees) {
- if (direction != Vector2.zero) {
- Quaternion targetRotation = Quaternion.LookRotation(movementPlane.ToWorld(direction, 0), movementPlane.ToWorld(Vector2.zero, 1));
-
- if (orientation == OrientationMode.YAxisForward) targetRotation *= Quaternion.Euler(90, 0, 0);
- return Quaternion.RotateTowards(simulatedRotation, targetRotation, maxDegrees);
- }
- return simulatedRotation;
- }
-
- public virtual void Move (Vector3 deltaPosition) {
- accumulatedMovementDelta += deltaPosition;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public virtual void FinalizeMovement (Vector3 nextPosition, Quaternion nextRotation) {
- if (enableRotation) FinalizeRotation(nextRotation);
- FinalizePosition(nextPosition);
- }
- void FinalizeRotation (Quaternion nextRotation) {
- simulatedRotation = nextRotation;
- if (updateRotation) {
- if (rigid != null) rigid.MoveRotation(nextRotation);
- else if (rigid2D != null) rigid2D.MoveRotation(nextRotation.eulerAngles.z);
- else tr.rotation = nextRotation;
- }
- }
- void FinalizePosition (Vector3 nextPosition) {
-
- Vector3 currentPosition = simulatedPosition;
- bool positionDirty1 = false;
- if (controller != null && controller.enabled && updatePosition) {
-
-
- tr.position = currentPosition;
- controller.Move((nextPosition - currentPosition) + accumulatedMovementDelta);
-
-
- currentPosition = tr.position;
- if (controller.isGrounded) verticalVelocity = 0;
- } else {
-
- float lastElevation;
- movementPlane.ToPlane(currentPosition, out lastElevation);
- currentPosition = nextPosition + accumulatedMovementDelta;
-
- if (usingGravity) currentPosition = RaycastPosition(currentPosition, lastElevation);
- positionDirty1 = true;
- }
-
- bool positionDirty2 = false;
- currentPosition = ClampToNavmesh(currentPosition, out positionDirty2);
-
- if ((positionDirty1 || positionDirty2) && updatePosition) {
-
-
- if (rigid != null) rigid.MovePosition(currentPosition);
- else if (rigid2D != null) rigid2D.MovePosition(currentPosition);
- else tr.position = currentPosition;
- }
- accumulatedMovementDelta = Vector3.zero;
- simulatedPosition = currentPosition;
- UpdateVelocity();
- }
- protected void UpdateVelocity () {
- var currentFrame = Time.frameCount;
- if (currentFrame != prevFrame) prevPosition2 = prevPosition1;
- prevPosition1 = position;
- prevFrame = currentFrame;
- }
-
-
-
-
-
-
-
-
- protected virtual Vector3 ClampToNavmesh (Vector3 position, out bool positionChanged) {
- positionChanged = false;
- return position;
- }
-
-
-
-
-
-
-
-
-
- protected Vector3 RaycastPosition (Vector3 position, float lastElevation) {
- RaycastHit hit;
- float elevation;
- movementPlane.ToPlane(position, out elevation);
- float rayLength = tr.localScale.y * height * 0.5f + Mathf.Max(0, lastElevation-elevation);
- Vector3 rayOffset = movementPlane.ToWorld(Vector2.zero, rayLength);
- if (Physics.Raycast(position + rayOffset, -rayOffset, out hit, rayLength, groundMask, QueryTriggerInteraction.Ignore)) {
-
-
-
-
-
-
-
-
- verticalVelocity *= System.Math.Max(0, 1 - 5 * lastDeltaTime);
- return hit.point;
- }
- return position;
- }
- protected virtual void OnDrawGizmosSelected () {
-
-
-
- if (Application.isPlaying) FindComponents();
- }
- public static readonly Color ShapeGizmoColor = new Color(240/255f, 213/255f, 30/255f);
- protected virtual void OnDrawGizmos () {
- if (!Application.isPlaying || !enabled) FindComponents();
- var color = ShapeGizmoColor;
- if (rvoController != null && rvoController.locked) color *= 0.5f;
- if (orientation == OrientationMode.YAxisForward) {
- Draw.Gizmos.Cylinder(position, Vector3.forward, 0, radius * tr.localScale.x, color);
- } else {
- Draw.Gizmos.Cylinder(position, rotation * Vector3.up, tr.localScale.y * height, radius * tr.localScale.x, color);
- }
- if (!float.IsPositiveInfinity(destination.x) && Application.isPlaying) Draw.Gizmos.CircleXZ(destination, 0.2f, Color.blue);
- autoRepath.DrawGizmos(position, radius);
- }
- protected override void Reset () {
- ResetShape();
- base.Reset();
- }
- void ResetShape () {
- var cc = GetComponent<CharacterController>();
- if (cc != null) {
- radius = cc.radius;
- height = Mathf.Max(radius*2, cc.height);
- }
- }
- protected override int OnUpgradeSerializedData (int version, bool unityThread) {
- if (unityThread && !float.IsNaN(centerOffsetCompatibility)) {
- height = centerOffsetCompatibility*2;
- ResetShape();
- var rvo = GetComponent<RVOController>();
- if (rvo != null) radius = rvo.radiusBackingField;
- centerOffsetCompatibility = float.NaN;
- }
- #pragma warning disable 618
- if (unityThread && targetCompatibility != null) target = targetCompatibility;
- #pragma warning restore 618
- if (version <= 3) {
- repathRate = repathRateCompatibility;
- canSearch = canSearchCompability;
- }
- return 5;
- }
- }
- }
|