Advertisement
DugganSC

Untitled

Apr 25th, 2025
270
0
Never
Not a member of Pastebin yet?Sign Up, it unlocks many cool features!
  1. usingSystem.Collections;
  2. usingSystem.Collections.Generic;
  3. usingUnityEngine;
  4. usingUnityEngine.AI;
  5.  
  6. publicclass BackAndForth : MonoBehaviour
  7. {
  8.     [Header("Target Settings")]
  9.     [Tooltip("The point to orbit around.")]
  10.     public Transform _target;
  11.     [Tooltip("The desired horizontal distance to maintain from the target.")]
  12.     publicfloat _radius = 10.0f;
  13.     [Tooltip("The desired height offset relative to the target's Y position.")]
  14.     publicfloat _targetHeight = 5.0f;// Added height parameter
  15.  
  16.     [Header("Movement Settings")]
  17.     [Tooltip("The constant forward speed of the entity.")]
  18.     publicfloat _speed = 5.0f;
  19.     [Tooltip("How quickly the entity can turn (degrees per second). Make this high enough!")]
  20.     publicfloat _rotationSpeed = 180.0f;
  21.  
  22.     [Header("Steering Behavior")]
  23.     [Tooltip("How far ahead (in seconds) to project position for steering. Tune this carefully.")]
  24.     publicfloat _lookAheadTime = 0.5f;
  25.     [Tooltip("How quickly the steering adjusts. Lower values = smoother but less responsive.")]
  26.     [Range(1f, 20f)]
  27.     publicfloat _steeringSmoothness = 5.0f;
  28.  
  29.     private Vector3 _currentSmoothedDirection;
  30.  
  31.     void Start()
  32.     {
  33.         if(_target ==null)
  34.         {
  35.             Debug.LogError("Orbit target is not assigned!", this);
  36.             // Disable the script if the target isn't set, prevents errors in Update
  37.             enabled =false;
  38.             return;
  39.         }
  40.         // Initialize smoothed direction to current facing direction
  41.         _currentSmoothedDirection = transform.forward;
  42.     }
  43.  
  44.     void Update()
  45.     {
  46.         Vector3 targetBasePos = _target.position;// Cache target position for clarity
  47.  
  48.         // --- Steering Calculation ---
  49.  
  50.         // 1. Predict Future Position
  51.         Vector3 futurePosition = transform.position+ transform.forward* _speed * _lookAheadTime;
  52.  
  53.         // 2. Calculate Vector from Target to Future Position
  54.         Vector3 vectorToFuturePos = futurePosition - targetBasePos;
  55.  
  56.         // 3. Project onto Horizontal Plane (XZ) to find the horizontal direction component
  57.         Vector3 horizontalVectorToFuture =new Vector3(vectorToFuturePos.x, 0f, vectorToFuturePos.z);
  58.  
  59.         // 4. Get Normalized Horizontal Direction
  60.         //    Handle the edge case where the future position is directly above or below the target
  61.         Vector3 horizontalDirection;
  62.         // Use sqrMagnitude for efficient zero-check (avoids square root)
  63.         if(horizontalVectorToFuture.sqrMagnitude< 0.001f)
  64.         {
  65.             // If directly above/below, target point is ambiguous horizontally.
  66.             // Choose a direction perpendicular to the entity's current UP direction, projected horizontally.
  67.             // Or simply use the entity's current horizontal right as a fallback.
  68.             Vector3 entityRightHorizontal =new Vector3(transform.right.x, 0f, transform.right.z).normalized;
  69.             // Absolute fallback if entity happens to be pointing straight up/down
  70.             if(entityRightHorizontal.sqrMagnitude< 0.001f)
  71.             {
  72.                 entityRightHorizontal = Vector3.right;// Use world right if local right is vertical
  73.             }
  74.             horizontalDirection = entityRightHorizontal;
  75.         }
  76.         else
  77.         {
  78.             // Normalize the horizontal vector to get just the direction
  79.             horizontalDirection = horizontalVectorToFuture.normalized;
  80.         }
  81.  
  82.         // 5. Calculate the Final Target Orbit Point
  83.         // Start with the horizontal position on the circle...
  84.         Vector3 targetOrbitPoint = targetBasePos + horizontalDirection * _radius;
  85.         // ...then set the desired vertical position.
  86.         targetOrbitPoint.y= targetBasePos.y+ _targetHeight;
  87.  
  88.  
  89.         // 6. Calculate *Raw* Desired Direction towards the height-adjusted orbit point
  90.         Vector3 rawDesiredDirection =(targetOrbitPoint - transform.position).normalized;
  91.         // Handle case where we are already AT the target point
  92.         if(rawDesiredDirection == Vector3.zero)
  93.         {
  94.             rawDesiredDirection = transform.forward;// Maintain current direction
  95.         }
  96.  
  97.  
  98.         // --- Apply Smoothing ---
  99.         // Smoothly interpolate the current steering direction towards the raw desired direction
  100.         _currentSmoothedDirection = Vector3.Lerp(
  101.             _currentSmoothedDirection,
  102.             rawDesiredDirection,
  103.             Time.deltaTime* _steeringSmoothness // Frame-rate independent smoothing
  104.         );
  105.         // Ensure the smoothed direction is normalized (Lerp might slightly change magnitude)
  106.         if(_currentSmoothedDirection != Vector3.zero)
  107.         {
  108.             _currentSmoothedDirection.Normalize();
  109.         }
  110.         else
  111.         {
  112.             _currentSmoothedDirection = transform.forward;// Fallback if somehow zero
  113.         }
  114.  
  115.  
  116.         // --- Apply Rotation and Movement ---
  117.  
  118.         // 7. Rotate Towards the Smoothed Direction
  119.         // This direction now implicitly guides towards the correct height AND horizontal orbit
  120.         Quaternion targetRotation = Quaternion.LookRotation(_currentSmoothedDirection);
  121.         transform.rotation= Quaternion.RotateTowards(transform.rotation, targetRotation, _rotationSpeed * Time.deltaTime);
  122.  
  123.         // 8. Move Forward along the entity's current facing direction
  124.         transform.position+= transform.forward* _speed * Time.deltaTime;
  125.  
  126.         // --- Optional: Visualize (for debugging in Scene view) ---
  127. #if UNITY_EDITOR
  128.         Debug.DrawLine(transform.position, futurePosition, Color.cyan);// Predicted future position
  129.         // Draw the calculated target orbit point (the goal for steering)
  130.         Debug.DrawLine(transform.position, targetOrbitPoint, Color.magenta);// Line from entity to target point
  131.         Debug.DrawRay(targetOrbitPoint, Vector3.up* 0.5f, Color.magenta);// Mark target point location
  132.  
  133.         // Draw the raw and smoothed desired directions
  134.         Debug.DrawLine(transform.position, transform.position+ rawDesiredDirection * 2.0f, Color.red);// Raw target dir
  135.         Debug.DrawLine(transform.position, transform.position+ _currentSmoothedDirection * 2.5f, Color.green);// Smoothed target dir
  136. #endif
  137.     }
  138.  
  139.     // Draw the target orbit circle in the Scene view for easy visualization
  140.     void OnDrawGizmosSelected()
  141.     {
  142.         if(_target !=null)
  143.         {
  144. #if UNITY_EDITOR // Ensure Handles call is only made in the editor
  145.             // Calculate the center of the orbit circle at the target height
  146.             Vector3 orbitCenter = _target.position;
  147.             orbitCenter.y+= _targetHeight;// Adjust gizmo height
  148.             UnityEditor.Handles.color= Color.cyan;
  149.             // Draw the wire disc using the world UP axis
  150.             UnityEditor.Handles.DrawWireDisc(orbitCenter, Vector3.up, _radius);
  151. #endif
  152.         }
  153.     }
  154. }
  155.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement
close