riversong code showcase
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using UnityEngine.VFX;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
public class BuildingDeleteAnimation : MonoBehaviour
|
||||
{
|
||||
private static readonly int IntensityPropertyID = Shader.PropertyToID("Intensity");
|
||||
|
||||
private static readonly int SizePropertyID = Shader.PropertyToID("Size");
|
||||
|
||||
[SerializeField]
|
||||
[ReadOnly]
|
||||
private float _sinkingHeight;
|
||||
|
||||
[SerializeField]
|
||||
private float _sinkingSpeed = 1;
|
||||
|
||||
[SerializeField]
|
||||
private AnimationCurve _sinkingSpeedCurve = AnimationCurve.Constant(0, 1, 1);
|
||||
|
||||
[SerializeField]
|
||||
private float _shakeFrequency = 10;
|
||||
|
||||
[SerializeField]
|
||||
private float _shakeAmplitude = 0.1f;
|
||||
|
||||
[SerializeField]
|
||||
private VisualEffect _vfxPrefab;
|
||||
|
||||
[SerializeField]
|
||||
private int _vfxCount = 1;
|
||||
|
||||
[SerializeField]
|
||||
private float _vfxInterval = 1;
|
||||
|
||||
[SerializeField]
|
||||
private float _vfxIntensityDecay = 0.5f;
|
||||
|
||||
private void ComputeSinkingHeight()
|
||||
{
|
||||
var bounds = default(Bounds);
|
||||
|
||||
var renderers = GetComponentsInChildren<Renderer>();
|
||||
foreach (var renderer in renderers) bounds.Encapsulate(renderer.bounds);
|
||||
|
||||
_sinkingHeight = bounds.size.y;
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_sinkingHeight == 0) ComputeSinkingHeight();
|
||||
}
|
||||
|
||||
public async UniTask PlayAsync(Building building)
|
||||
{
|
||||
var initialPosition = transform.position;
|
||||
var animatedPosition = transform.position;
|
||||
var angularFrequency = 2 * Mathf.PI * _shakeFrequency;
|
||||
var shakeWeights = new Vector3(Random.Range(-1, 1), 0, Random.Range(-1, 1));
|
||||
|
||||
for (var i = 0; i < _vfxCount; i++)
|
||||
{
|
||||
var delay = i * _vfxInterval;
|
||||
var intensity = Mathf.Pow(_vfxIntensityDecay, i);
|
||||
_ = PlayVfxAsync(building, initialPosition, delay, intensity);
|
||||
}
|
||||
|
||||
var t = 0f;
|
||||
while (animatedPosition.y > initialPosition.y - _sinkingHeight)
|
||||
{
|
||||
var dt = Time.deltaTime;
|
||||
|
||||
t += dt;
|
||||
|
||||
var sinkingSpeed = _sinkingSpeed * _sinkingSpeedCurve.Evaluate(t);
|
||||
animatedPosition += Vector3.down * (sinkingSpeed * dt);
|
||||
|
||||
var shake = Mathf.Sin(t * angularFrequency) * _shakeAmplitude * _sinkingSpeed;
|
||||
transform.position = animatedPosition + shake * shakeWeights;
|
||||
|
||||
await UniTask.NextFrame();
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask PlayVfxAsync(Building building, Vector3 position, float delay, float intensity)
|
||||
{
|
||||
if (delay > 0) await UniTask.WaitForSeconds(delay);
|
||||
|
||||
var vfx = Instantiate(_vfxPrefab, position, Quaternion.identity);
|
||||
vfx.SetFloat(IntensityPropertyID, intensity);
|
||||
vfx.SetVector2(SizePropertyID, new Vector2(building.Rect.Width, building.Rect.Height));
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
ComputeSinkingHeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user