RepeatButton 누르고 있는 동안 이벤트가 반복 발생하는 버튼

유니티 & C#|2020. 8. 30. 15:43
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
using UnityEngine.UI;

namespace UI
{
    public class RepeatButton : Selectable, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler
    {
        [SerializeField] private float interval = 0.1f;
        [SerializeField] private float delay = 1.0f;
        [SerializeField] private ButtonRepeatEvent onRepeat = new ButtonRepeatEvent();

        private bool isPointDown = false;
        private float lastInvokeTime;
    
        private float delayTime = 0f;
    
        public ButtonRepeatEvent OnRepeat => onRepeat;

        // Use this for initialization
        protected override void Start()
        {
            base.Start();
            delayTime = delay;
        }

        protected override void OnDisable()
        {
            base.OnDisable();
            
            isPointDown = false;
            delayTime = delay;
        }

        void Update()
        {
            if (!IsInteractable() && isPointDown)
            {
                isPointDown = false;
                delayTime = delay;

                return;
            }

            if (isPointDown)
            {
                if ((delayTime -= Time.deltaTime) > 0f)
                {
                    return;
                }
    
                if (Time.time - lastInvokeTime > interval)
                {
                    Repeat();
                    lastInvokeTime = Time.time;
                }
            }
        }

        private void Repeat()
        {
            if (!IsActive() || !IsInteractable())
                return;

            onRepeat.Invoke();
        }

        public virtual void OnPointerClick(PointerEventData eventData)
        {
            if (eventData.button != PointerEventData.InputButton.Left)
                return;

            Repeat();
        }

        public override void OnPointerDown(PointerEventData eventData)
        {
            base.OnPointerExit(eventData);

            isPointDown = true;
            delayTime = delay;

            if (IsInteractable())
            {
                DoStateTransition(SelectionState.Pressed, false);
            }
        }
    
        public override void OnPointerUp(PointerEventData eventData)
        {
            base.OnPointerExit(eventData);

            isPointDown = false;
            delayTime = delay;

            DoStateTransition(currentSelectionState, false);
        }
    
        public override void OnPointerExit(PointerEventData eventData)
        {
            base.OnPointerExit(eventData);

            isPointDown = false;
            delayTime = delay;

            DoStateTransition(currentSelectionState, false);
        }

        [Serializable]
        public class ButtonRepeatEvent : UnityEvent { }
    }
}

댓글()