Run code when button is held down

喜夏-厌秋 提交于 2019-12-12 20:07:01

问题


I am new to unity and building a game, I use 2 buttons (IncreaseButton, DecreaseButton) the problem I have is that the button callback functions are only called once, when the user clicks on the button but not when the button is held down. How can I make the button to be called repeatedly when held down?

Code

    public void IncreaseBPM()
{
    if (speed < 12) 
    {
        speed += 0.05f;
        bpmText.GetComponent<BeatTextControl> ().beats += 1;
        PlayerPrefs.SetFloat ("savedBPM", speed);
    }
}

public void DecreaseBPM()
{
    if (speed > 1.5)
    {
        speed -= 0.05f;
        bpmText.GetComponent<BeatTextControl> ().beats -= 1;
        PlayerPrefs.SetFloat ("savedBPM", speed);
    }
}

回答1:


okay so firstly you create 2 booleans:

bool increase = false;
bool decrease = false;

then you set them inside the functions

public void WhenButtonClicked()
    { increase = true; }
public void WhenOtherButtonClicked()
    { decrease = true; }

Then in the update function inside the same file you check:

Void update(){
   If(increase){ IncreaseBPM(); }
   Else if(decrease){ DecreaseBPM(); } 
}

About when the button gets released, i found a simple answer: http://answers.unity3d.com/questions/843319/46-gui-button-onrelease.html

Add an Event Trigger component to your button (In the event menu). From there you can add a listener for OnPointerUp. Treat it just the same as OnClick.

And create 2 other functions that set increase and decrease to false !




回答2:


Unity's Button component does not have this functionality built in. You have to roll out your own with the Image component as a Button. Implement IPointerDownHandler and IPointerUpHandler interface then override the OnPointerDown and OnPointerUp functions.

When OnPointerDown is called, use struct to store the which object/volume Image is clicked and the current click pointerId in a List. You can then check which Image is clicked in the Update function.

If the OnPointerUp is called, you have to check which pointerId is released then check if that pointerId exist in the List and remove it if it does.

I have gone ahead to do this. Below is the new script in your question:

public class ButtonTest : MonoBehaviour
{
    // Use this for initialization
    void Start()
    {
        //Register to Button events
        ButtonDownRelease.OnButtonActionChanged += ButtonActionChange;
        Debug.Log("Registered!");
    }

    // Update is called once per frame
    void Update()
    {

    }

    //Un-Register to Button events
    void OnDisable()
    {
        ButtonDownRelease.OnButtonActionChanged -= ButtonActionChange;
    }


    //Will be called when there is a Button action
    void ButtonActionChange(ButtonAction buttonAction)
    {
        //Check for held down
        if (buttonAction == ButtonAction.DecreaseButtonDown)
        {
            Debug.Log("Decrease Button held Down!");
            DecreaseBPM();
        }

        if (buttonAction == ButtonAction.IncreaseButtonDown)
        {
            Debug.Log("Increase Button held Down!");
            IncreaseBPM();
        }

        //Check for release
        if (buttonAction == ButtonAction.DecreaseButtonUp)
        {
            Debug.Log("Decrease Button Released!");
        }

        if (buttonAction == ButtonAction.IncreaseButtonUp)
        {
            Debug.Log("Increase Button Released!");
        }
    }

    private void IncreaseBPM()
    {
        if (TempoController.GetComponent<Pendulum>().speed < 12)
        {
            TempoController.GetComponent<Pendulum>().speed += 0.05f;
        }
    }

    private void DecreaseBPM()
    {
        if (TempoController.GetComponent<Pendulum>().speed > 1.5)
        {
            TempoController.GetComponent<Pendulum>().speed -= 0.05f;
        }
    }
}

Read carefully.

Create a new script called ButtonDownRelease then put the code below into it. Attach the ButtonDownRelease script to the Canvas The Canvas which is the parent of your Images/Buttons UI GameObjects. Create two Images (Increase and Decrease). Create two tags called increase and decrease then put both Images in the right tag.

Note:

You can still use Button instead of the Image to make this work if you don't want to use the Image component. Simply select each Button and change the tags to increase and decrease, then select the Text component that is under each Button and change their tags increase and decrease too. You must change the Button's Text tags too if you want to use the Button component with this script. Also, you will have to attach ButtonDownRelease to each Button not to the Canvas like you have to with Image component.

Your ButtonDownRelease script:

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System.Collections.Generic;

public class ButtonDownRelease : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
    List<ButtonInfo> buttonInfo = new List<ButtonInfo>();

    public delegate void ButtonActionChange(ButtonAction buttonAction);
    public static event ButtonActionChange OnButtonActionChanged;

    // Update is called once per frame
    void Update()
    {
        //Send Held Button Down events
        for (int i = 0; i < buttonInfo.Count; i++)
        {
            if (buttonInfo[i].buttonPresed == ButtonAction.DecreaseButtonDown)
            {
                dispatchEvent(ButtonAction.DecreaseButtonDown);
            }

            else if (buttonInfo[i].buttonPresed == ButtonAction.IncreaseButtonDown)
            {
                dispatchEvent(ButtonAction.IncreaseButtonDown);
            }
        }
    }

    void dispatchEvent(ButtonAction btAction)
    {
        if (OnButtonActionChanged != null)
        {
            OnButtonActionChanged(btAction);
        }
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        //Debug.Log("Button Down!");
        ButtonInfo bInfo = new ButtonInfo();
        bInfo.uniqueId = eventData.pointerId;
        if (eventData.pointerCurrentRaycast.gameObject.CompareTag("increase"))
        {
            bInfo.buttonPresed = ButtonAction.IncreaseButtonDown;
            addButton(bInfo);
        }
        else if (eventData.pointerCurrentRaycast.gameObject.CompareTag("decrease"))
        {
            bInfo.buttonPresed = ButtonAction.DecreaseButtonDown;
            addButton(bInfo);
        }
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        //Debug.Log("Button Down!" + eventData.pointerCurrentRaycast);
        removeButton(eventData.pointerId);
    }

    void addButton(ButtonInfo bInfo)
    {
        buttonInfo.Add(bInfo);
    }

    void removeButton(int unqID)
    {
        for (int i = 0; i < buttonInfo.Count; i++)
        {
            if (unqID == buttonInfo[i].uniqueId)
            {
                //Send Release Button Up events
                if (buttonInfo[i].buttonPresed == ButtonAction.DecreaseButtonDown)
                {
                    dispatchEvent(ButtonAction.DecreaseButtonUp);
                }

                else if (buttonInfo[i].buttonPresed == ButtonAction.IncreaseButtonDown)
                {
                    dispatchEvent(ButtonAction.IncreaseButtonUp);
                }
                buttonInfo.RemoveAt(i);
            }
        }

    }

    public struct ButtonInfo
    {
        public int uniqueId;
        public ButtonAction buttonPresed;
    }
}

public enum ButtonAction
{
    None,
    IncreaseButtonDown, IncreaseButtonUp,
    DecreaseButtonDown, DecreaseButtonUp
}

Finally, you will run into problems if you only use boolean variables to do this. This needs to be done with pointerId like the script provided in this answer in order to avoid bugs on mobile devices. A good example of this bug is when you click on an Image then release the finger on another GameObject, your boolean logic would break because OnPointerUp won't be called. Also using multi-touch on mobile devices will cause problems too.



来源:https://stackoverflow.com/questions/39195387/run-code-when-button-is-held-down

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!