using Cysharp.Threading.Tasks; using Unity.Mathematics; using UnityEngine; using UnityEngine.AddressableAssets; namespace DanieleMarotta.RiversongCodeShowcase { [Service(typeof(IProjectileManager))] public class ProjectileManagerSystem : GameSystem, IProjectileManager { private const float ProjectileSpeed = 4; [InjectService] private IIntentLogicExecutor _intentLogicExecutor; public ProjectileManagerSystem(IServiceLocator serviceLocator) : base(serviceLocator) { } public float ComputeProjectileTravelTime(Agent source, Agent target) { return math.distance(source.Position, target.Position) / ProjectileSpeed; } public void FireProjectile(Agent source, Agent target) { _ = FireProjectileAsync(source, target, ComputeProjectileTravelTime(source, target)); } private async UniTask FireProjectileAsync(Agent source, Agent target, float travelTime) { var prefabRef = source.Definition.Projectile; var projectile = await prefabRef.InstantiateAsync(); var p0 = (Vector3)source.Position; var p1 = (Vector3)target.Position; // const float peakHeightPerMeter = 0.1f; // var peak = Vector3.Distance(p0, p1) * peakHeightPerMeter; var t = 0f; while (t < 1) { t = Mathf.Clamp01(t + Time.deltaTime / travelTime); var position = Vector3.Lerp(p0, p1, t); //position.y += 4 * peak * t * (1 - t); var rotation = Quaternion.LookRotation((position - projectile.transform.position).normalized); projectile.transform.SetPositionAndRotation(position, rotation); await UniTask.NextFrame(); } Addressables.ReleaseInstance(projectile); _intentLogicExecutor.CancelRemainingIntents(target); } } }