Button Repeat

I guess I’m blind - I am some times.

In GUI, there’s something called GUI.ButtonRepeat which fires every frame as long as the button is pressed. I was expecting - hoping - that the new GUI button would have event similar to Button Repeat, or that there would a similar class.

However, I simply can’t find it.

On top, extending the existing GUI class appear to be a small puzzle on itself as the existing class have quite the extensive custom editor - and I deeply hate writing custom editor.

So, how should go using the new GUI to make a button that fires every frame it is held down?

add PointerDown & PointerUp events to set a bool?

1 Like

Add? What? Where? The only event in the button Inspector is “On Click”.

Add an Event Trigger Component to the Button object and click on “Add New”. There you have every event you can use on that button, including PointerDown and PointerUp.

1 Like

Thanks!

EDIT: Huh… OnPointerDown is fired only once, the moment the mouse button is pressed. Ok, so how do I make this event repeat itself as long as it’s held down?

Set it up so a bool is set to true on the OnPointerDown event and set to false on the OnPointerUp event.
In your Update method check that boolean. If its true, the button is held down.

1 Like

It’s a rather backward way to do it, but I guess it will have to do…

I have noted that this might be desirable to add in the future.

3 Likes

You think?
Personally it strikes me that reproducing all the old GUI system’s elements at release might have been a good idea.

1 Like

Personally, I think the system is lacking some very important thing… Like… I dunno… C# Events?

Is there a simpler way to handle onButtonDown events each frame now?

nope still the **** pointerDown / pointerUp and bool technic, sad thing ><

For anyone else that stumbles onto this like I did, I made the following script to streamline the repeat button functionality per the previously suggested solution until Unity comes up with something better. Did the trick for me. Probably add a cooldown or something (as needed) unless you really want it firing every frame.
Just throw this MonoBehaviour on the same object as your button, assign the button property, and you’re in business.

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

[RequireComponent(typeof(Button))]
public class ButtonRepeater : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
public bool shouldRepeat { get { return _pointerData != null; } }
public Button button = null;
private PointerEventData _pointerData = null;

private void Update()
{
if(shouldRepeat)
{
button.OnSubmit(_pointerData);
}
}

public void OnPointerDown(PointerEventData eventData)
{
_pointerData = eventData;
}

public void OnPointerUp(PointerEventData eventData)
{
_pointerData = null;
}
}

Hi Dchipman.

I could not make work your solution. I have a weird "Unexpected symbol ‘’ " in the console that prevent me from compiling the code. Also I was a bit confused with the bool shouldRepeat. Why to not call it : “pointerIsDown”.

since earlier code had hidden symbols that broke compile here is one that works…
button should be assigned automatically, while I introduced a delay for the repeat to start and interval for it to work.
might have a bug, but seems to work

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

[RequireComponent(typeof(Button))]
public class ButtonRepeat : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
    [SerializeField]
    private float m_repeatDelay = 1f;
    [SerializeField]
    private float m_repeatRetriggerInterval = 0.1f;
    private Button m_button;
    private PointerEventData m_pointerData = null;
    private float m_lastTrigger = 0;

    private void Awake()
    {
        m_button = transform.GetComponent<Button>();
    }

    private void Update()
    {
        if (m_pointerData != null)
        {
            if(Time.realtimeSinceStartup - m_lastTrigger >= m_repeatDelay)
            {
                m_lastTrigger = Time.realtimeSinceStartup - (m_repeatDelay - m_repeatRetriggerInterval);
                m_button.OnSubmit(m_pointerData);
            }
        }
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        m_lastTrigger = Time.realtimeSinceStartup;
        m_pointerData = eventData;
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        m_pointerData = null;
        m_lastTrigger = 0f;
    }
}
1 Like

i think people want a mouse held event like this…
ex:

Thank you. Always grateful for code that saves me having to do something. Especially when free. Worked fine.

still works, one gotcha to watch out inside editor:
For the first click, it fires OnPointerUp() right after OnPointerDown(), even if you are holding mouse down!

So click game view first to activate it(?), then click and hold the button to see real results…