Files
2026-05-21 16:04:49 +02:00

123 lines
3.8 KiB
C#

using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Playables;
using UnityEngine.VFX;
namespace DanieleMarotta.RiversongCodeShowcase
{
[RequireComponent(typeof(Animator))]
public class BuildingPlacementAnimation : MonoBehaviour, IAnimationClipSource
{
[SerializeField]
private AnimationClip _animationClip;
[SerializeField]
private float _playbackSpeed = 1;
[SerializeField]
private Vector3 _positionLerpWeights = new(1.5f, 1, 1.5f);
[SerializeField]
private float _rotationLerpWeight = 1.5f;
[SerializeField]
private VisualEffect _impactVfxPrefab;
[SerializeField]
private float _impactIntensityDecay = 0.75f;
[SerializeField]
[HideInInspector]
private float _animationProgress;
[SerializeField]
[HideInInspector]
private float _bounce;
private PlayableGraph _playableGraph;
private AnimationClipPlayable _playableClip;
private BuildingDefinition _building;
private Vector3 _startPosition;
private Vector3 _finalPosition;
private Quaternion _finalRotation;
public bool IsPlaying { get; private set; }
private void Awake()
{
_playableGraph = PlayableGraph.Create();
_playableGraph.SetTimeUpdateMode(DirectorUpdateMode.Manual);
_playableClip = AnimationClipPlayable.Create(_playableGraph, _animationClip);
_playableClip.SetSpeed(_playbackSpeed);
var animator = GetComponent<Animator>();
var output = AnimationPlayableOutput.Create(_playableGraph, nameof(BuildingPlacementAnimation), animator);
output.SetSourcePlayable(_playableClip);
}
private void OnDestroy()
{
_playableGraph.Destroy();
}
private void Update()
{
if (!IsPlaying) return;
_playableGraph.Evaluate(Time.unscaledDeltaTime);
var position = transform.position;
position.x = Mathf.Lerp(_startPosition.x, _finalPosition.x, _positionLerpWeights.x * _animationProgress);
position.y = Mathf.Lerp(_startPosition.y, _finalPosition.y, _positionLerpWeights.y * _bounce);
position.z = Mathf.Lerp(_startPosition.z, _finalPosition.z, _positionLerpWeights.z * _animationProgress);
transform.position = position;
transform.rotation = Quaternion.Lerp(transform.rotation, _finalRotation, _rotationLerpWeight * _animationProgress);
}
public async UniTask PlayAsync(BuildingDefinition building, Vector3 startPosition, Vector3 finalPosition, Quaternion finalRotation)
{
IsPlaying = true;
_building = building;
_startPosition = startPosition;
_finalPosition = finalPosition;
_finalRotation = finalRotation;
_playableClip.SetTime(0);
_playableClip.SetTime(0);
_playableGraph.Play();
_animationProgress = 0;
while (_animationProgress < 1) await UniTask.NextFrame();
_playableGraph.Stop();
transform.SetPositionAndRotation(finalPosition, finalRotation);
IsPlaying = false;
}
public void GetAnimationClips(List<AnimationClip> results)
{
if (_animationClip) results.Add(_animationClip);
}
private void OnImpact(int impact)
{
var impactVfx = Instantiate(_impactVfxPrefab, transform.position, transform.rotation);
var intensity = Mathf.Pow(_impactIntensityDecay, impact);
var size = new Vector2(_building.Width, _building.Height);
DustVfxProperties.Setup(impactVfx, intensity, size);
}
}
}