How to create a button that increasingly calls a function

Hey there,

I want to create a button that calls a function in another script as long as the button is hold down. I want to work it in the following way:

  • Button is clicked: call function once
  • Wait 1 second
  • when button is still pressed, call the function for every frame that the button is held down

Thanks in advance :slight_smile:

What you want to do is create a class which inherits form IPointerDownHandler like so:

public class MyButtonsScript : MonoBehaviour, IPointerDownHandler
{

    public void OnPointerDown(PointerEventData eventData)
    {
       mTimeLeft = 1.0f;
       mMouseDown = true;
       DoAction();
    }
}

That will fire an event when the button is first pressed down. If your class also inherits IPointerUpHandler and you create a public void OnPointerUp(PointerEventData eventData) function, you can track when the button has been released.

In OnPointerDown() you’re going to want to set a member variable to a value that a void Update() will decrement. In this case mTimeLeft.

bool mMouseDown = false;
float mTimeLeft;

void Update()
{
   if (mMouseDown)
   {
      mTimeLeft -= Time.deltaTime;
      if (mTimeLeft <= 0.0f)
      {
          DoAction();
      }
   }
}

In the update, check to see if the mouse is down and if it is decrement the time left. That will give you one second of time. Once that one second has passed, call the DoAction() function every frame. Hope this helps!

2 Likes

Works like a charm! :slight_smile: Thanks a lot !
In my game I need several of these buttons which work all the same, except that they call different functions. Do you know how I can set the DoAction() in the inspector?

I would typically just make one small script per action, but yes, it is possible.

I think the easiest way to do it would be to have a public enum in the class so that you would get a drop down and then in Start() or Awake() you could do something like this:

public enum MyCustomEnum { Action1, Action2 }
public MyCustomEnum ActionFunction = MyCustomEnum.Action1;

private Action mDoAction();

void Start()
{
   if (ActionFunction == MyCustomEnum.Action1)
   {
      mDoAction = OnAction1();
   }
   else if (ActionFunction == MyCustomEnum.Action2)
   {
      mDoAction = OnAction2();
   }
}

private void DoAction1()
{
   Debug.Log("Action 1");
}

private void DoAction2()
{
   Debug.Log("Action 2");
}

And instead of calling DoAction(), call mDoAction(); instead.
Note: The “Action” class is one available in C#. Its name just so happened to be the same as the class in my previous examples. Hope that isn’t confusing.

Or you know use the UnityEvent

[Serializable]
public class MyEvent : UnityEvent { } // There are overloads to let you have parameters

[SerializeField]
private MyEvent m_onMyEvent = new MyEvent ();
...

void SomeFunction()
{
m_onMyEvent.Invoke();
}

You then have the Inspector drawer drawing the same sort of thing you see for a OnClick event in the button for example.

SomeFunction is the function that you want to use to call the invoke function (the DoAction in NeilMo example)

1 Like

Fine Phil. Show me up with your fancy up to date knowledge :wink: