Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections.Generic;
- using UnityEngine;
- public class HomingBehavior : BulletBehavior
- {
- public string targetTag = "Player"; // todo Prioritize targets based on lowest range and forward momentum angle from target
- public Transform Target { get; private set; }
- public bool IsTracking { get; private set; }
- [SerializeField] private float minRange = 2f;
- [SerializeField] private float range = 15;
- [SerializeField] private float acquirementRange = 5f;
- [SerializeField] private float redirectSpeed = 2; // How much rotation is allowed to occur within one second
- [SerializeField] private float minLookAtThreshold = 45;
- [SerializeField] private float maxLookAtThreshold = 145;
- [SerializeField] private float gravityWhileTracking = 0.25f;
- [SerializeField] private int positionHistorySize = 20;
- [SerializeField] private float predictionTime = 1;
- private Rigidbody _rb;
- private Vector3 _storedVelocity;
- private Vector3 _storedNewVelocity;
- private Vector3 _storedPosition;
- private GameObject _visualPrefab;
- private readonly List<Vector3> _targetPositionHistory = new ();
- private bool TrackTarget(float distance)
- {
- if (distance >= range || distance <= minRange) return false;
- var targetPosition = Target.position;
- var forwardRatio = 0f;
- // Add current target position to the position history list
- _targetPositionHistory.Insert(0, targetPosition);
- if (_targetPositionHistory.Count > positionHistorySize)
- {
- _targetPositionHistory.RemoveAt(_targetPositionHistory.Count - 1);
- }
- var predictedPosition = InterpolatePosition(_targetPositionHistory, Time.deltaTime * predictionTime);
- if (_targetPositionHistory.Count > 2)
- {
- _storedVelocity = _rb.velocity;
- _storedNewVelocity = (predictedPosition - _rb.position).normalized * _rb.velocity.magnitude;
- forwardRatio = ForwardFacingRatio(predictedPosition, minLookAtThreshold, maxLookAtThreshold);
- _rb.velocity = Vector3.Lerp(_storedVelocity, _storedNewVelocity, Time.deltaTime * redirectSpeed * forwardRatio);
- }
- _rb.AddForce(Physics.gravity * -gravityWhileTracking, ForceMode.Force);
- return forwardRatio > 0.1f;
- }
- private static bool HasLineOfSight()
- {
- // todo Cast ray to verify if target has maintained line of sight
- return false;
- }
- private static Vector3 InterpolatePosition(List<Vector3> positions, float time)
- {
- // Find the two positions in the history that are closest to the time we want to predict
- var startIndex = Mathf.FloorToInt((positions.Count - 1) * time);
- var endIndex = Mathf.CeilToInt((positions.Count - 1) * time);
- var start = positions[startIndex];
- var end = positions[endIndex];
- // Interpolate between the two positions based on how far we are between them
- var t = (time - startIndex / (float)(positions.Count - 1)) * (positions.Count - 1);
- return Vector3.Lerp(start, end, t);
- }
- private float ForwardFacingRatio(Vector3 targetPosition, float minAngle, float maxAngle)
- {
- var projectile = transform;
- var targetDirection = targetPosition - projectile.position;
- var angle = Vector3.Angle(projectile.GetComponent<Rigidbody>().velocity.normalized, targetDirection);
- var forwardFacingRatio = Mathf.InverseLerp(maxAngle, minAngle, angle);
- return forwardFacingRatio;
- }
- private void FixedUpdate()
- {
- var acquisitionDistance = Vector3.Distance(transform.position, _storedPosition);
- if (acquisitionDistance >= acquirementRange)
- IsTracking = TrackTarget(Vector3.Distance(_rb.position, Target.position));
- }
- private void OnEnable()
- {
- _rb = GetComponent<Rigidbody>();
- _visualPrefab = Resources.Load<GameObject>("Visual Prefabs/HomingVisuals");
- var v = Instantiate(_visualPrefab, transform, false);
- v.transform.localPosition = new Vector3();
- Target = GameObject.FindWithTag(targetTag).transform;
- _storedPosition = transform.position;
- }
- private void OnDrawGizmos()
- {
- if (!Application.isPlaying) return;
- Gizmos.color = Color.green;
- Gizmos.DrawRay(_rb.position, _rb.velocity);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement