Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

How to create a button that increasingly calls a function

Discussion in 'UGUI & TextMesh Pro' started by Dennooo, Oct 4, 2015.

  1. Dennooo

    Dennooo

    Joined:
    May 12, 2015
    Posts:
    78
    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 :)
     
  2. NeilM0

    NeilM0

    Joined:
    Mar 31, 2009
    Posts:
    135
    What you want to do is create a class which inherits form IPointerDownHandler like so:

    Code (CSharp):
    1. public class MyButtonsScript : MonoBehaviour, IPointerDownHandler
    2. {
    3.  
    4.     public void OnPointerDown(PointerEventData eventData)
    5.     {
    6.        mTimeLeft = 1.0f;
    7.        mMouseDown = true;
    8.        DoAction();
    9.     }
    10. }
    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.

    Code (CSharp):
    1. bool mMouseDown = false;
    2. float mTimeLeft;
    3.  
    4. void Update()
    5. {
    6.    if (mMouseDown)
    7.    {
    8.       mTimeLeft -= Time.deltaTime;
    9.       if (mTimeLeft <= 0.0f)
    10.       {
    11.           DoAction();
    12.       }
    13.    }
    14. }
    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!
     
    Dennooo and Senshi like this.
  3. Dennooo

    Dennooo

    Joined:
    May 12, 2015
    Posts:
    78
    Works like a charm! :) 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?
     
  4. NeilM0

    NeilM0

    Joined:
    Mar 31, 2009
    Posts:
    135
    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:

    Code (CSharp):
    1. public enum MyCustomEnum { Action1, Action2 }
    2. public MyCustomEnum ActionFunction = MyCustomEnum.Action1;
    3.  
    4. private Action mDoAction();
    5.  
    6. void Start()
    7. {
    8.    if (ActionFunction == MyCustomEnum.Action1)
    9.    {
    10.       mDoAction = OnAction1();
    11.    }
    12.    else if (ActionFunction == MyCustomEnum.Action2)
    13.    {
    14.       mDoAction = OnAction2();
    15.    }
    16. }
    17.  
    18. private void DoAction1()
    19. {
    20.    Debug.Log("Action 1");
    21. }
    22.  
    23. private void DoAction2()
    24. {
    25.    Debug.Log("Action 2");
    26. }
    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.
     
  5. phil-Unity

    phil-Unity

    Unity UI Lead Developer Unity Technologies

    Joined:
    Nov 23, 2012
    Posts:
    1,226
    Or you know use the UnityEvent

    Code (CSharp):
    1. [Serializable]
    2. public class MyEvent : UnityEvent { } // There are overloads to let you have parameters
    3.  
    4. [SerializeField]
    5. private MyEvent m_onMyEvent = new MyEvent ();
    6. ...
    7.  
    8. void SomeFunction()
    9. {
    10. m_onMyEvent.Invoke();
    11. }
    12.  
    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)
     
    NeilM0 likes this.
  6. NeilM0

    NeilM0

    Joined:
    Mar 31, 2009
    Posts:
    135
    Fine Phil. Show me up with your fancy up to date knowledge ;)