using DG.Tweening; using Unity.Mathematics; using UnityEngine; [AddComponentMenu("KFAttachments/Binding Helpers/Animation Random Recoil")] public class AnimationRandomRecoil : AnimationProceduralRecoildAbs, IPlayableGraphRelated #if UNITY_EDITOR , ISerializationCallbackReceiver #endif { [Header("Targets")] [SerializeField] private Transform target; [SerializeField, HideInInspector] private string targetName; [SerializeField] private Transform pivot; [SerializeField, HideInInspector] private string pivotName; [Header("Rotation")] //[SerializeField] private Vector3 minRotation = new Vector3(-5, -2, -2); //[SerializeField] private Vector3 maxRotation = new Vector3(0, 2, 2); [SerializeField] private Vector3 randomRotationMin = new Vector3(-3, -1, -1); [SerializeField] private Vector3 randomRotationMax = new Vector3(-1, 1, 1); [Header("Kickback")] //[SerializeField] private Vector3 minKickback = new Vector3(0, 0, -0.05f); //[SerializeField] private Vector3 maxKickback = new Vector3(0, 0, 0); [SerializeField] private Vector3 randomKickbackMin = new Vector3(0, 0, -0.025f); [SerializeField] private Vector3 randomKickbackMax = new Vector3(0, 0, -0.01f); [Header("Recoil")] [SerializeField, Range(0, 0.1f)] private float tweenInDuration = 0.04f; [SerializeField, Range(0, 5)] private float tweenOutDuration = 1.5f; [Header("Return")] [SerializeField, Range(1, 5)] private float elasticAmplitude = 1f; [SerializeField, Range(0, 1)] private float elasticPeriod = 0.5f; private Vector3 targetRotation = Vector3.zero; private Vector3 targetPosition = Vector3.zero; private Vector3 currentRotation = Vector3.zero; private Vector3 currentPosition = Vector3.zero; private Sequence seq; //private bool isTweeningIn = true; public override void AddRecoil(Vector3 positionMultiplier, Vector3 rotationMultiplier) { if (target && pivot) { targetPosition = Vector3.Scale(KFExtensions.Random(randomKickbackMin, randomKickbackMax), positionMultiplier); targetRotation = Vector3.Scale(KFExtensions.Random(randomRotationMin, randomRotationMax), rotationMultiplier); GameObject targetObj = target.gameObject; RecreateSeq(); } } private void OnEnable() { ResetSeq(); } private void OnDisable() { ResetSeq(); } private void ResetSeq() { seq?.Rewind(false); if (target) { target.localEulerAngles = Vector3.zero; target.localPosition = Vector3.zero; } } private void RecreateSeq() { currentPosition = Vector3.zero; currentRotation = Vector3.zero; seq?.Kill(false); seq = DOTween.Sequence() //.InsertCallback(0, () => isTweeningIn = true) .Insert(0, DOTween.To(() => currentRotation, (rot) => currentRotation = rot, targetRotation, tweenInDuration).SetEase(Ease.OutCubic)) .Insert(0, DOTween.To(() => currentPosition, (pos) => currentPosition = pos, targetPosition, tweenInDuration).SetEase(Ease.OutCubic)) //.InsertCallback(tweenInDuration, () => isTweeningIn = false) .Insert(tweenInDuration, DOTween.To(() => currentRotation, (rot) => currentRotation = rot, Vector3.zero, tweenOutDuration).SetEase(Ease.OutElastic, elasticAmplitude, elasticPeriod)) .Insert(tweenInDuration, DOTween.To(() => currentPosition, (rot) => currentPosition = rot, Vector3.zero, tweenOutDuration).SetEase(Ease.OutElastic, elasticAmplitude, elasticPeriod)) .OnUpdate(UpdateTransform) .SetAutoKill(true) .SetRecyclable(); } private void UpdateTransform() { if (target) { target.localEulerAngles = Vector3.zero; target.localPosition = Vector3.zero; target.RotateAroundPivot(pivot, currentRotation); target.localPosition += currentPosition; } //if (!isTweeningIn) //{ // targetRotation = currentRotation; // targetPosition = currentPosition; //} } public MonoBehaviour Init(Transform playerAnimatorTrans, bool isLocalPlayer) { if (isLocalPlayer) { var copy = playerAnimatorTrans.AddMissingComponent(); copy.enabled = true; if (target) { copy.target = this.target; } else { copy.target = playerAnimatorTrans.FindInAllChildren(targetName); } if (pivot) { copy.pivot = pivot; } else { copy.pivot = playerAnimatorTrans.FindInAllChildren(pivotName); } copy.randomRotationMin = this.randomRotationMin; copy.randomRotationMax = this.randomRotationMax; copy.randomKickbackMin = this.randomKickbackMin; copy.randomKickbackMax = this.randomKickbackMax; copy.tweenInDuration = this.tweenInDuration; copy.tweenOutDuration = this.tweenOutDuration; copy.elasticAmplitude = this.elasticAmplitude; copy.elasticPeriod = this.elasticPeriod; return copy; } return null; } public void Disable(Transform playerAnimatorTrans) { enabled = false; } #if UNITY_EDITOR public void OnBeforeSerialize() { if (target) { targetName = target.name; } if (pivot) { pivotName = pivot.name; } } public void OnAfterDeserialize() { } #endif }