123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- using Pathfinding.RVO;
- namespace Pathfinding.Legacy {
- [RequireComponent(typeof(Seeker))]
- [AddComponentMenu("Pathfinding/Legacy/AI/Legacy RichAI (3D, for navmesh)")]
-
-
-
-
-
- [HelpURL("http://arongranberg.com/astar/documentation/stable/class_pathfinding_1_1_legacy_1_1_legacy_rich_a_i.php")]
- public class LegacyRichAI : RichAI {
-
-
-
-
-
-
- public bool preciseSlowdown = true;
- public bool raycastingForGroundPlacement = false;
-
-
-
-
- new Vector3 velocity;
- Vector3 lastTargetPoint;
- Vector3 currentTargetDirection;
- protected override void Awake () {
- base.Awake();
- if (rvoController != null) {
- if (rvoController is LegacyRVOController) (rvoController as LegacyRVOController).enableRotation = false;
- else Debug.LogError("The LegacyRichAI component only works with the legacy RVOController, not the latest one. Please upgrade this component", this);
- }
- }
-
- static float deltaTime;
-
- protected override void Update () {
- deltaTime = Mathf.Min(Time.smoothDeltaTime*2, Time.deltaTime);
- if (richPath != null) {
-
-
- RichPathPart pt = richPath.GetCurrentPart();
- var fn = pt as RichFunnel;
- if (fn != null) {
-
- Vector3 position = UpdateTarget(fn);
-
-
- if (Time.frameCount % 5 == 0 && wallForce > 0 && wallDist > 0) {
- wallBuffer.Clear();
- fn.FindWalls(wallBuffer, wallDist);
- }
-
-
- int tgIndex = 0;
-
-
- Vector3 tg = nextCorners[tgIndex];
- Vector3 dir = tg-position;
- dir.y = 0;
- bool passedTarget = Vector3.Dot(dir, currentTargetDirection) < 0;
-
- if (passedTarget && nextCorners.Count-tgIndex > 1) {
- tgIndex++;
- tg = nextCorners[tgIndex];
- }
- if (tg != lastTargetPoint) {
- currentTargetDirection = (tg - position);
- currentTargetDirection.y = 0;
- currentTargetDirection.Normalize();
- lastTargetPoint = tg;
-
- }
-
- dir = (tg-position);
- dir.y = 0;
- float magn = dir.magnitude;
-
- distanceToSteeringTarget = magn;
-
- dir = magn == 0 ? Vector3.zero : dir/magn;
- Vector3 normdir = dir;
- Vector3 force = Vector3.zero;
- if (wallForce > 0 && wallDist > 0) {
- float wLeft = 0;
- float wRight = 0;
- for (int i = 0; i < wallBuffer.Count; i += 2) {
- Vector3 closest = VectorMath.ClosestPointOnSegment(wallBuffer[i], wallBuffer[i+1], tr.position);
- float dist = (closest-position).sqrMagnitude;
- if (dist > wallDist*wallDist) continue;
- Vector3 tang = (wallBuffer[i+1]-wallBuffer[i]).normalized;
-
-
- float dot = Vector3.Dot(dir, tang) * (1 - System.Math.Max(0, (2*(dist / (wallDist*wallDist))-1)));
- if (dot > 0) wRight = System.Math.Max(wRight, dot);
- else wLeft = System.Math.Max(wLeft, -dot);
- }
- Vector3 norm = Vector3.Cross(Vector3.up, dir);
- force = norm*(wRight-wLeft);
-
- }
-
- bool endPointIsTarget = lastCorner && nextCorners.Count-tgIndex == 1;
- if (endPointIsTarget) {
-
-
- if (slowdownTime < 0.001f) {
- slowdownTime = 0.001f;
- }
- Vector3 diff = tg - position;
- diff.y = 0;
- if (preciseSlowdown) {
-
-
-
-
- dir = (6*diff - 4*slowdownTime*velocity)/(slowdownTime*slowdownTime);
- } else {
- dir = 2*(diff - slowdownTime*velocity)/(slowdownTime*slowdownTime);
- }
- dir = Vector3.ClampMagnitude(dir, acceleration);
- force *= System.Math.Min(magn/0.5f, 1);
- if (magn < endReachedDistance) {
-
- NextPart();
- }
- } else {
- dir *= acceleration;
- }
-
- velocity += (dir + force*wallForce)*deltaTime;
- if (slowWhenNotFacingTarget) {
- float dot = (Vector3.Dot(normdir, tr.forward)+0.5f)*(1.0f/1.5f);
-
- float xzmagn = Mathf.Sqrt(velocity.x*velocity.x + velocity.z*velocity.z);
- float prevy = velocity.y;
- velocity.y = 0;
- float mg = Mathf.Min(xzmagn, maxSpeed * Mathf.Max(dot, 0.2f));
- velocity = Vector3.Lerp(tr.forward * mg, velocity.normalized * mg, Mathf.Clamp(endPointIsTarget ? (magn*2) : 0, 0.5f, 1.0f));
- velocity.y = prevy;
- } else {
-
- float xzmagn = Mathf.Sqrt(velocity.x*velocity.x + velocity.z*velocity.z);
- xzmagn = maxSpeed/xzmagn;
- if (xzmagn < 1) {
- velocity.x *= xzmagn;
- velocity.z *= xzmagn;
-
- }
- }
-
- if (endPointIsTarget) {
- Vector3 trotdir = Vector3.Lerp(velocity, currentTargetDirection, System.Math.Max(1 - magn*2, 0));
- RotateTowards(trotdir);
- } else {
- RotateTowards(velocity);
- }
-
- velocity += deltaTime * gravity;
- if (rvoController != null && rvoController.enabled) {
-
- tr.position = position;
- rvoController.Move(velocity);
- } else
- if (controller != null && controller.enabled) {
-
- tr.position = position;
- controller.Move(velocity * deltaTime);
- } else {
-
- float lasty = position.y;
- position += velocity*deltaTime;
- position = RaycastPosition(position, lasty);
- tr.position = position;
- }
- } else {
- if (rvoController != null && rvoController.enabled) {
-
- rvoController.Move(Vector3.zero);
- }
- }
- if (pt is RichSpecial) {
- if (!traversingOffMeshLink) {
- StartCoroutine(TraverseSpecial(pt as RichSpecial));
- }
- }
-
-
- } else {
- if (rvoController != null && rvoController.enabled) {
-
- rvoController.Move(Vector3.zero);
- } else
- if (controller != null && controller.enabled) {
- } else {
- tr.position = RaycastPosition(tr.position, tr.position.y);
- }
- }
- UpdateVelocity();
- lastDeltaTime = Time.deltaTime;
- }
- new Vector3 RaycastPosition (Vector3 position, float lasty) {
- if (raycastingForGroundPlacement) {
- RaycastHit hit;
- float up = Mathf.Max(height*0.5f, lasty-position.y+height*0.5f);
- if (Physics.Raycast(position+Vector3.up*up, Vector3.down, out hit, up, groundMask)) {
- if (hit.distance < up) {
-
- position = hit.point;
- velocity.y = 0;
- }
- }
- }
- return position;
- }
-
- bool RotateTowards (Vector3 trotdir) {
- trotdir.y = 0;
- if (trotdir != Vector3.zero) {
- Quaternion rot = tr.rotation;
- Vector3 trot = Quaternion.LookRotation(trotdir).eulerAngles;
- Vector3 eul = rot.eulerAngles;
- eul.y = Mathf.MoveTowardsAngle(eul.y, trot.y, rotationSpeed*deltaTime);
- tr.rotation = Quaternion.Euler(eul);
-
- return Mathf.Abs(eul.y-trot.y) < 5f;
- }
- return false;
- }
- }
- }
|