using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.VFX; namespace DanieleMarotta.RiversongCodeShowcase { public class BuildingUpgradeAnimation : MonoBehaviour { [SerializeField] private VisualEffect _vfxPrefab; [SerializeField] private float _stretchDuration = 0.25f; [SerializeField] private float _stretchFactor = 1.2f; [SerializeField] private float _settleDuration = 0.75f; [SerializeField] private float _settleElasticity = 4.5f; public async UniTask PlayAsync(Building building) { var vfx = Instantiate(_vfxPrefab, transform.position, transform.rotation); DustVfxProperties.Setup(vfx, 1, new Vector2(building.Rect.Width, building.Rect.Height)); var fromScale = transform.localScale; var toScale = new Vector3(fromScale.x, fromScale.y * _stretchFactor, fromScale.z); var elapsed = 0f; while (elapsed < _stretchDuration) { elapsed += Time.unscaledDeltaTime; var t = EaseOutBack(Mathf.Clamp01(elapsed / _stretchDuration)); transform.localScale = Vector3.LerpUnclamped(fromScale, toScale, t); await UniTask.NextFrame(); } elapsed = 0; while (elapsed < _settleDuration) { elapsed += Time.unscaledDeltaTime; var t = EaseOutElastic(Mathf.Clamp01(elapsed / _settleDuration), _settleElasticity); transform.localScale = Vector3.LerpUnclamped(toScale, fromScale, t); await UniTask.NextFrame(); } transform.localScale = fromScale; } private static float EaseOutBack(float t) { const float c1 = 1.70158f; const float c3 = c1 + 1; return 1 + c3 * Mathf.Pow(t - 1, 3) + c1 * Mathf.Pow(t - 1, 2); } private static float EaseOutElastic(float t, float elasticity) { var c4 = 2 * Mathf.PI / elasticity; return t switch { 0 => 0, 1 => 1, _ => Mathf.Pow(2, -10 * t) * Mathf.Sin((10 * t - 0.75f) * c4) + 1 }; } } }