UI Shadow Effect Resources

Here are the scripts and sprites I use in the video.

CustomButton.cs

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using DG.Tweening;

public enum ButtonIconAnimStyle
{
    Move,
    Scale,
    Rotate
}

public class CustomButton : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler
{
    [Header("Settings")]
    public ButtonIconAnimStyle iconAnimStyle = ButtonIconAnimStyle.Scale;
    [SerializeField] protected float pressedScale = 0.9f;
    [SerializeField] protected float scaleDuration = 0.2f;

    [Header("References")]
    public Image outerGlowImage;
    public Color glowStartColor;
    public RectTransform iconRect;

    [Header("Events")]
    public UnityEvent onPointerClick;
    public bool isInteractable = true;

    private Vector2 _iconDefaultPos;
    private Vector3 _iconDefaultScale;

    protected virtual void Start()
    {
        SetInteractable(isInteractable);

        if (outerGlowImage != null)
        {
            Color c = outerGlowImage.color;
            c.a = 0;
            outerGlowImage.color = c;
        }

        if (iconRect != null)
        {
            _iconDefaultPos = iconRect.anchoredPosition;
            _iconDefaultScale = iconRect.localScale;
        }
    }

    public virtual void SetInteractable(bool isInteractable)
    {
        this.isInteractable = isInteractable;
    }

    protected virtual void OnDisable()
    {
        transform.DOKill();
        if (outerGlowImage != null) outerGlowImage.DOKill();
        if (iconRect != null) iconRect.DOKill();

        transform.localScale = Vector3.one;
        if (iconRect != null)
        {
            iconRect.localScale = _iconDefaultScale;
            iconRect.localRotation = Quaternion.identity;
            iconRect.anchoredPosition = _iconDefaultPos;
        }
    }

    public virtual void OnPointerClick(PointerEventData eventData)
    {
        if (!isInteractable) return;

        if (outerGlowImage != null)
        {
            outerGlowImage.DOKill();
            outerGlowImage.color = glowStartColor;
            outerGlowImage.DOFade(0f, 1.2f).SetEase(Ease.OutQuad);
        }

        if (iconRect != null)
        {
            PlayIconAnimation();
        }

        transform.DOKill();
        transform.localScale = Vector3.one;
        transform.DOPunchScale(new Vector3(0.25f, 0.25f, 0.25f), 1.1f, 3, 0.1f);

        NavigationButtonsManager.I.OnNavButtonClicked(this);
        onPointerClick?.Invoke();
    }

    private void PlayIconAnimation()
    {
        iconRect.DOKill();

        iconRect.localScale = _iconDefaultScale;
        iconRect.localRotation = Quaternion.identity;
        iconRect.anchoredPosition = _iconDefaultPos;

        Sequence seq = DOTween.Sequence();

        switch (iconAnimStyle)
        {
            case ButtonIconAnimStyle.Move:
                float moveDist = 10f;
                float moveSpeed = 0.1f;

                seq.Append(iconRect.DOAnchorPosX(_iconDefaultPos.x + moveDist, moveSpeed).SetEase(Ease.OutQuad));
                seq.Append(iconRect.DOAnchorPosX(_iconDefaultPos.x - moveDist, moveSpeed).SetEase(Ease.InOutQuad));
                seq.Append(iconRect.DOAnchorPosX(_iconDefaultPos.x + moveDist, moveSpeed).SetEase(Ease.InOutQuad));
                seq.Append(iconRect.DOAnchorPosX(_iconDefaultPos.x - moveDist, moveSpeed).SetEase(Ease.InOutQuad));
                seq.Append(iconRect.DOAnchorPosX(_iconDefaultPos.x, moveSpeed).SetEase(Ease.OutQuad));
                break;

            case ButtonIconAnimStyle.Scale:
                float scaleMultiplier = 1.4f;
                float dampFactor = 0.1f;
                float scaleSpeed = 0.12f;

                for (int i = 0; i < 4; i++)
                {
                    seq.Append(iconRect.DOScale(_iconDefaultScale * scaleMultiplier, scaleSpeed).SetEase(Ease.OutQuad));
                    seq.Append(iconRect.DOScale(_iconDefaultScale, scaleSpeed).SetEase(Ease.InQuad));
                    scaleMultiplier -= dampFactor;
                }
                break;

            case ButtonIconAnimStyle.Rotate:
                float rotAngle = 20f;
                float rotSpeed = 0.1f;

                seq.Append(iconRect.DOLocalRotate(new Vector3(0, 0, -rotAngle), rotSpeed).SetEase(Ease.OutQuad));
                seq.Append(iconRect.DOLocalRotate(new Vector3(0, 0, rotAngle), rotSpeed).SetEase(Ease.InOutQuad));
                seq.Append(iconRect.DOLocalRotate(new Vector3(0, 0, -rotAngle), rotSpeed).SetEase(Ease.InOutQuad));
                seq.Append(iconRect.DOLocalRotate(new Vector3(0, 0, rotAngle), rotSpeed).SetEase(Ease.InOutQuad));
                seq.Append(iconRect.DOLocalRotate(Vector3.zero, rotSpeed).SetEase(Ease.OutQuad));
                break;
        }
    }

    public virtual void OnPointerDown(PointerEventData eventData)
    {
        if (!isInteractable) return;
        transform.DOKill();
        transform.DOScale(pressedScale, scaleDuration).SetEase(Ease.OutBack);
    }

    public virtual void OnPointerUp(PointerEventData eventData)
    {

    }
}

NavigationButtonsManager.cs

using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;

public class NavigationButtonsManager : MonoBehaviour
{
    public List<CustomButton> navigationButtons = new List<CustomButton>();
    public Transform uiLightTransform;
    public static NavigationButtonsManager I;

    void Awake()
    {
        if (I == null) I = this;
        else Destroy(gameObject);
    }


    public void OnNavButtonClicked(CustomButton clickedButton)
    {
        uiLightTransform.DOKill();
        var targetWorldX = clickedButton.transform.position.x;
        uiLightTransform.DOMoveX(targetWorldX, 0.3f).SetEase(Ease.OutQuad);
    }
}

Button Sprites


Yorumlar

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir