using DentedPixel;
using UnityEngine;
using UnityEngine.EventSystems;
namespace BulletHellTemplate
{
///
/// EnhancedButtonAnimation provides advanced button interaction animations such as scale, position shift, fade, shake, and a looping pulse effect.
/// Attach this script to a UI button or any UI element to animate hover, press, and release interactions.
///
public class EnhancedButtonAnimation : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler
{
///
/// Enum for selecting the axis along which to move the UI element.
///
public enum MovementAxis
{
None,
Horizontal,
Vertical,
Both
}
[Header("Button Transform Settings")]
///
/// The transform of the button to animate.
///
[Tooltip("The transform of the button to animate.")]
public Transform buttonTransform;
///
/// Optional CanvasGroup for fade animations. If not assigned, it will be added automatically.
///
[Tooltip("Optional CanvasGroup for fade animations. If not assigned, it will be added automatically.")]
public CanvasGroup canvasGroup;
private Vector3 originalScale;
private Vector3 originalPosition;
[Header("Scale Animation Settings")]
///
/// Scale factor applied when the button is hovered.
///
[Tooltip("Scale factor applied when the button is hovered.")]
public float hoverScaleFactor = 1.05f;
///
/// Scale factor applied when the button is pressed.
///
[Tooltip("Scale factor applied when the button is pressed.")]
public float pressScaleFactor = 0.95f;
///
/// Duration for scale animations.
///
[Tooltip("Duration for scale animations.")]
public float scaleAnimationDuration = 0.1f;
[Header("Position Shift Settings")]
///
/// Axis along which the button will shift on hover.
///
[Tooltip("Axis along which the button will shift on hover.")]
public MovementAxis hoverMovementAxis = MovementAxis.None;
///
/// Distance in pixels for the position shift on hover.
///
[Tooltip("Distance in pixels for the position shift on hover.")]
public float hoverMoveDistance = 10f;
[Header("Fade Animation Settings")]
///
/// If true, the button will fade when hovered.
///
[Tooltip("If true, the button will fade when hovered.")]
public bool applyFadeOnHover = false;
///
/// Target alpha for the fade effect on hover.
///
[Tooltip("Target alpha for the fade effect on hover.")]
public float hoverFadeAlpha = 0.8f;
///
/// Duration for fade animations.
///
[Tooltip("Duration for fade animations.")]
public float fadeAnimationDuration = 0.1f;
[Header("Shake Animation Settings")]
///
/// If true, a shake effect will be applied when the button is clicked.
///
[Tooltip("If true, a shake effect will be applied when the button is clicked.")]
public bool applyShakeOnClick = false;
///
/// Duration of the shake effect.
///
[Tooltip("Duration of the shake effect.")]
public float shakeDuration = 0.2f;
///
/// Strength of the shake effect in pixels.
///
[Tooltip("Strength of the shake effect in pixels.")]
public float shakeStrength = 10f;
[Header("Loop Animation Settings (Pulse)")]
///
/// If true, the button will continuously pulse (scale up and down).
///
[Tooltip("If true, the button will continuously pulse (scale up and down).")]
public bool enablePulseLoop = false;
///
/// Scale factor for the pulse loop.
///
[Tooltip("Scale factor for the pulse loop.")]
public float pulseScaleFactor = 1.1f;
///
/// Duration for one pulse cycle.
///
[Tooltip("Duration for one pulse cycle.")]
public float pulseDuration = 0.5f;
private void Awake()
{
if (buttonTransform == null)
{
buttonTransform = transform;
}
originalScale = buttonTransform.localScale;
originalPosition = buttonTransform.localPosition;
if (applyFadeOnHover && canvasGroup == null)
{
canvasGroup = buttonTransform.GetComponent();
if (canvasGroup == null)
{
canvasGroup = buttonTransform.gameObject.AddComponent();
}
}
}
private void Start()
{
// Optionally start a pulse loop animation
if (enablePulseLoop)
{
StartPulseLoop();
}
}
///
/// Starts a continuous pulse animation on the button.
///
public void StartPulseLoop()
{
LeanTween.scale(buttonTransform.gameObject, originalScale * pulseScaleFactor, pulseDuration)
.setEase(LeanTweenType.easeInOutSine)
.setLoopPingPong();
}
///
/// Called when the pointer enters the button area.
///
/// Pointer event data.
public void OnPointerEnter(PointerEventData eventData)
{
// Scale animation on hover
LeanTween.scale(buttonTransform.gameObject, originalScale * hoverScaleFactor, scaleAnimationDuration)
.setEase(LeanTweenType.easeOutQuad);
// Position shift on hover based on selected axis
Vector3 targetPos = originalPosition;
switch (hoverMovementAxis)
{
case MovementAxis.Horizontal:
targetPos.x += hoverMoveDistance;
break;
case MovementAxis.Vertical:
targetPos.y += hoverMoveDistance;
break;
case MovementAxis.Both:
targetPos += new Vector3(hoverMoveDistance, hoverMoveDistance, 0f);
break;
default:
break;
}
LeanTween.moveLocal(buttonTransform.gameObject, targetPos, scaleAnimationDuration)
.setEase(LeanTweenType.easeOutQuad);
// Fade effect on hover
if (applyFadeOnHover && canvasGroup != null)
{
LeanTween.alphaCanvas(canvasGroup, hoverFadeAlpha, fadeAnimationDuration)
.setEase(LeanTweenType.easeOutQuad);
}
}
///
/// Called when the pointer exits the button area.
///
/// Pointer event data.
public void OnPointerExit(PointerEventData eventData)
{
// Revert scale animation
LeanTween.scale(buttonTransform.gameObject, originalScale, scaleAnimationDuration)
.setEase(LeanTweenType.easeOutQuad);
// Revert position shift
LeanTween.moveLocal(buttonTransform.gameObject, originalPosition, scaleAnimationDuration)
.setEase(LeanTweenType.easeOutQuad);
// Revert fade effect
if (applyFadeOnHover && canvasGroup != null)
{
LeanTween.alphaCanvas(canvasGroup, 1f, fadeAnimationDuration)
.setEase(LeanTweenType.easeOutQuad);
}
}
///
/// Called when the pointer is pressed on the button.
///
/// Pointer event data.
public void OnPointerDown(PointerEventData eventData)
{
LeanTween.scale(buttonTransform.gameObject, originalScale * pressScaleFactor, scaleAnimationDuration)
.setEase(LeanTweenType.easeOutQuad);
}
///
/// Called when the pointer is released from the button.
///
/// Pointer event data.
public void OnPointerUp(PointerEventData eventData)
{
LeanTween.scale(buttonTransform.gameObject, originalScale, scaleAnimationDuration)
.setEase(LeanTweenType.easeOutQuad);
// Optionally apply a shake effect on click release
if (applyShakeOnClick)
{
ApplyShakeEffect();
}
}
///
/// Applies a shake effect to the button.
///
private void ApplyShakeEffect()
{
Vector3 currentPos = buttonTransform.localPosition;
LeanTween.value(gameObject, 0f, 1f, shakeDuration)
.setOnUpdate((float val) =>
{
// Generate a random offset inside a circle
Vector2 shakeOffset = Random.insideUnitCircle * shakeStrength;
buttonTransform.localPosition = currentPos + new Vector3(shakeOffset.x, shakeOffset.y, 0f);
})
.setOnComplete(() =>
{
buttonTransform.localPosition = currentPos;
});
}
///
/// Ensures all LeanTween animations on the button are canceled when the object is destroyed.
///
private void OnDestroy()
{
if (buttonTransform != null)
{
LeanTween.cancel(buttonTransform.gameObject);
}
}
}
}