using UnityEditor;
using UnityEngine;
using UnityEngine.Serialization;
using Random = UnityEngine.Random;

namespace SR.Item
{
	public class SRProjectileLauncher : MonoBehaviour
	{
		[SerializeField]
		private UnityEngine.Transform launchPoint;
		
		[SerializeField]
		private UnityEngine.Transform targetSphere;

		[SerializeField] 
		private SRTrajectoryPredictor srTrajectoryPredictor;
		
		[SerializeField]
		private LayerMask physLayerMask;
		
		[SerializeField]
		private float torqueForce = -14f;
		
		[SerializeField]
		private float smallA = -0.04f;
		
		[SerializeField]
		private float bigA = -0.01f;
		
		[SerializeField]
		private float lerpSpeed = 4f;
		
		[SerializeField]
		private float currentA = -0.04f;
		
		[SerializeField]
		private float currentTorque;
		
		public Rigidbody RigidBody => rigidBody;
		private Rigidbody rigidBody;
		
		private CapsuleCollider capsuleCollider;
		
		private int indexLineAfterWhichObstacle;

		private bool isAim;
		private float throwMaxRange;
		private Vector3 cameraPosition;
		private Vector3 cameraLookDirection;
		private float timeBeforeTheExplosion;
		
		private void Awake()
		{
			if (targetSphere != null)
			{
				targetSphere.gameObject.SetActive(false);
			}
			
			currentA = smallA;

			PhysController(false);
		}


		public void PhysController(bool phisEnabled)
		{
			rigidBody = GetComponent<Rigidbody>();
			rigidBody.useGravity = phisEnabled;
			rigidBody.isKinematic = !phisEnabled;
			
			capsuleCollider = GetComponent<CapsuleCollider>();
			capsuleCollider.isTrigger = !phisEnabled;
		}
		
		private void LateUpdate()
		{
			if (!isAim)
			{
				if (srTrajectoryPredictor == null)
				{
					return;
				}

				if (srTrajectoryPredictor.enabled)
				{
					srTrajectoryPredictor.enabled = false;
				}

				if (targetSphere.gameObject.activeSelf)
				{
					targetSphere.gameObject.SetActive(false);
				}

				return;
			}

			float distanceBetweenCameraAndGrenade = Vector3.Distance(cameraPosition, launchPoint.position);
			Vector3 shootPosition = cameraPosition + cameraLookDirection * distanceBetweenCameraAndGrenade;

			if (Raycast(shootPosition, cameraLookDirection, out var hit))
			{
				float distanceBetweenShootPositionAndHitPoint = Vector3.Distance(shootPosition, hit.point);

				if (distanceBetweenShootPositionAndHitPoint > throwMaxRange)
				{
					Vector3 direction = hit.point - shootPosition;
					direction.Normalize();
					Vector3 calcPointOnEdgeOfCircle = shootPosition + direction * throwMaxRange;

					Vector3 obstacle = CheckObstacles();
					targetSphere.transform.position = obstacle != Vector3.zero ? obstacle : calcPointOnEdgeOfCircle;
					
					RenderLaunch(launchPoint.position, calcPointOnEdgeOfCircle);
					
					srTrajectoryPredictor.enabled = true;
					targetSphere.gameObject.SetActive(true);
					
					return;
				}
				
				Vector3 obstacle2 = CheckObstacles();
				targetSphere.transform.position = obstacle2 != Vector3.zero ? obstacle2 : hit.point;
				
				RenderLaunch(launchPoint.position, hit.point);

				srTrajectoryPredictor.enabled = true;
				targetSphere.gameObject.SetActive(true);
			}
			else
			{
				srTrajectoryPredictor.enabled = false;
				targetSphere.gameObject.SetActive(false);
			}
		}

		private Vector3 CheckObstacles()
		{
			if (srTrajectoryPredictor.PositionCount > 0)
			{
				float radius = capsuleCollider.radius;
				
				for (int i = 0; i < srTrajectoryPredictor.Positions.Length - 1;  i++)
				{
					//last iteration in loop
					if (i >= srTrajectoryPredictor.Positions.Length - 2)
					{
						break;
					}
					
					Vector3 startPoint = srTrajectoryPredictor.Positions[i];
					Vector3 endPoint = srTrajectoryPredictor.Positions[i + 1];
					
					Vector3 direction = endPoint - startPoint;
					float distance = direction.magnitude;

					if (UnityEngine.Physics.SphereCast(startPoint, radius, direction, out var hit, distance, physLayerMask))
					{
						indexLineAfterWhichObstacle = i + 1;
						return hit.point;
					}
				}
			}

			indexLineAfterWhichObstacle = 0;
			return Vector3.zero;
		}

		private bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hit)
		{
			return UnityEngine.Physics.Raycast(origin, direction, out hit, Mathf.Infinity, physLayerMask);
		}
		
		private void RenderLaunch(Vector3 origin, Vector3 target)
		{
			Vector3 velocity = SRProjectile.VelocityByA(origin, target, currentA);
			srTrajectoryPredictor.Render(origin, velocity, target, indexLineAfterWhichObstacle);
		}
	}
}
Это код на C# для unity. Попробуй код в методе LateUpdate() сделать более лучшим, красивым.