【问题标题】:Run code when button is held down按住按钮时运行代码
【发布时间】:2016-08-28 20:15:07
【问题描述】:

我是统一和构建游戏的新手,我使用 2 个按钮(IncreaseButton,DecreaseButton)我遇到的问题是按钮回调函数只调用一次,当用户点击按钮而不是按钮时按住。按住时如何使按钮重复调用?

代码

    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);
    }
}

【问题讨论】:

  • 把它放在一个循环中,检查按钮何时被按下?

标签: c# unity3d unity5


【解决方案1】:

Unity 的Button 组件没有内置此功能。您必须使用Image 组件作为Button 推出自己的功能。实现IPointerDownHandlerIPointerUpHandler 接口,然后覆盖OnPointerDownOnPointerUp 函数。

当调用OnPointerDown 时,使用structImage 被点击的对象/卷和当前点击pointerId 存储在List 中。 然后您可以检查在Update 函数中单击了哪个Image

如果调用了OnPointerUp,则必须检查释放了哪个pointerId,然后检查List 中是否存在pointerId,如果存在则将其删除。

我已经开始这样做了。以下是您问题中的新脚本:

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;
        }
    }
}

仔细阅读

创建一个名为ButtonDownRelease 的新脚本,然后将下面的代码放入其中。将ButtonDownRelease 脚本附加到Canvas Canvas,它是Images/Buttons UI 游戏对象的父级。创建两个Images(增加和减少)。创建两个tags,分别称为increasedecrease,然后将Images 放在右边的tag 中。

注意

如果您不想使用Image 组件,您仍然可以使用Button 而不是Image 来完成这项工作。只需选择每个Button 并将标签更改为increasedecrease,然后选择每个Button 下的Text 组件并更改它们的标签increasedecrease如果您想在此脚本中使用Button 组件,也必须更改ButtonText 标记。此外,您必须将 ButtonDownRelease 附加到每个 Button,而不是像 Image 组件那样附加到 Canvas

您的ButtonDownRelease 脚本:

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
}

最后,如果您只使用boolean 变量来执行此操作,您将遇到问题。这需要使用pointerId 来完成,就像此答案中提供的脚本一样,以避免移动设备上的错误。这个错误的一个很好的例子是当你点击一个Image然后松开另一个游戏对象的手指,你的布尔逻辑会中断,因为OnPointerUp不会被调用。在移动设备上使用多点触控也会产生问题。

【讨论】:

    【解决方案2】:

    好的,首先你创建 2 个布尔值:

    bool increase = false;
    bool decrease = false;
    

    然后你将它们设置在函数中

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

    然后在你检查的同一个文件内的更新函数中:

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

    关于按钮何时被释放,我找到了一个简单的答案: http://answers.unity3d.com/questions/843319/46-gui-button-onrelease.html

    将事件触发器组件添加到您的按钮(在事件菜单中)。 从那里您可以为 OnPointerUp 添加一个侦听器。对待它只是 与 OnClick 相同。

    并创建另外 2 个将增减设置为 false 的函数!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多