Advertisement
CassataGames

Untitled

Feb 24th, 2023
540
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.44 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3.  
  4. public class HomingBehavior : BulletBehavior
  5. {
  6.     public string targetTag = "Player"; // todo Prioritize targets based on lowest range and forward momentum angle from target
  7.     public Transform Target { get; private set; }
  8.     public bool IsTracking { get; private set; }
  9.  
  10.     [SerializeField] private float minRange = 2f;
  11.     [SerializeField] private float range = 15;
  12.     [SerializeField] private float acquirementRange = 5f;
  13.     [SerializeField] private float redirectSpeed = 2; // How much rotation is allowed to occur within one second
  14.     [SerializeField] private float minLookAtThreshold = 45;
  15.     [SerializeField] private float maxLookAtThreshold = 145;
  16.     [SerializeField] private float gravityWhileTracking = 0.25f;
  17.    
  18.     [SerializeField] private int positionHistorySize = 20;
  19.     [SerializeField] private float predictionTime = 1;
  20.    
  21.     private Rigidbody _rb;
  22.     private Vector3 _storedVelocity;
  23.     private Vector3 _storedNewVelocity;
  24.     private Vector3 _storedPosition;
  25.  
  26.     private GameObject _visualPrefab;
  27.  
  28.     private readonly List<Vector3> _targetPositionHistory = new ();
  29.  
  30.  
  31.     private bool TrackTarget(float distance)
  32.     {
  33.         if (distance >= range || distance <= minRange) return false;
  34.        
  35.         var targetPosition = Target.position;
  36.         var forwardRatio = 0f;
  37.  
  38.         // Add current target position to the position history list
  39.         _targetPositionHistory.Insert(0, targetPosition);
  40.         if (_targetPositionHistory.Count > positionHistorySize)
  41.         {
  42.             _targetPositionHistory.RemoveAt(_targetPositionHistory.Count - 1);
  43.         }
  44.        
  45.         var predictedPosition = InterpolatePosition(_targetPositionHistory, Time.deltaTime * predictionTime);
  46.        
  47.         if (_targetPositionHistory.Count > 2)
  48.         {
  49.             _storedVelocity = _rb.velocity;
  50.             _storedNewVelocity = (predictedPosition - _rb.position).normalized * _rb.velocity.magnitude;
  51.  
  52.             forwardRatio = ForwardFacingRatio(predictedPosition, minLookAtThreshold, maxLookAtThreshold);
  53.             _rb.velocity = Vector3.Lerp(_storedVelocity, _storedNewVelocity, Time.deltaTime * redirectSpeed * forwardRatio);
  54.         }
  55.         _rb.AddForce(Physics.gravity * -gravityWhileTracking, ForceMode.Force);
  56.        
  57.         return forwardRatio > 0.1f;
  58.     }
  59.  
  60.     private static bool HasLineOfSight()
  61.     {
  62.         // todo Cast ray to verify if target has maintained line of sight
  63.         return false;
  64.     }
  65.  
  66.     private static Vector3 InterpolatePosition(List<Vector3> positions, float time)
  67.     {
  68.         // Find the two positions in the history that are closest to the time we want to predict
  69.         var startIndex = Mathf.FloorToInt((positions.Count - 1) * time);
  70.         var endIndex = Mathf.CeilToInt((positions.Count - 1) * time);
  71.         var start = positions[startIndex];
  72.         var end = positions[endIndex];
  73.  
  74.         // Interpolate between the two positions based on how far we are between them
  75.         var t = (time - startIndex / (float)(positions.Count - 1)) * (positions.Count - 1);
  76.         return Vector3.Lerp(start, end, t);
  77.     }
  78.    
  79.     private float ForwardFacingRatio(Vector3 targetPosition, float minAngle, float maxAngle)
  80.     {
  81.         var projectile = transform;
  82.         var targetDirection = targetPosition - projectile.position;
  83.         var angle = Vector3.Angle(projectile.GetComponent<Rigidbody>().velocity.normalized, targetDirection);
  84.         var forwardFacingRatio = Mathf.InverseLerp(maxAngle, minAngle, angle);
  85.         return forwardFacingRatio;
  86.     }
  87.  
  88.     private void FixedUpdate()
  89.     {
  90.         var acquisitionDistance = Vector3.Distance(transform.position, _storedPosition);
  91.         if (acquisitionDistance >= acquirementRange)
  92.             IsTracking = TrackTarget(Vector3.Distance(_rb.position, Target.position));
  93.     }
  94.  
  95.     private void OnEnable()
  96.     {
  97.         _rb = GetComponent<Rigidbody>();
  98.         _visualPrefab = Resources.Load<GameObject>("Visual Prefabs/HomingVisuals");
  99.         var v = Instantiate(_visualPrefab, transform, false);
  100.         v.transform.localPosition = new Vector3();
  101.        
  102.         Target = GameObject.FindWithTag(targetTag).transform;
  103.         _storedPosition = transform.position;
  104.     }
  105.  
  106.     private void OnDrawGizmos()
  107.     {
  108.         if (!Application.isPlaying) return;
  109.         Gizmos.color = Color.green;
  110.         Gizmos.DrawRay(_rb.position, _rb.velocity);
  111.     }
  112. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement