123 lines
3.8 KiB
C#
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);
|
|
}
|
|
}
|
|
} |