C# 仅在Unity中每隔几秒钟使用一次按钮

C# 仅在Unity中每隔几秒钟使用一次按钮,c#,unity3d,button,pressed,C#,Unity3d,Button,Pressed,我正试图让它成为一个统一的按钮,它只能每隔几秒钟被按下和激活一次。我有一个带有著名引号的数组,当我按下按钮时,它确实会显示这些引号,但是如果你连续按下按钮,那么它将在所有引号中循环,而无法仔细阅读它们。现在,我尝试了下面的方法,但没有效果(因为按钮仍然可以按下,没有明显的效果): 我认为bool和if循环的简单组合就足够了,但这不起作用。我接近这个概念了吗?要使其正常运行,需要进行哪些更改?要实现这一点,您可以做一些事情。您当前的代码从未切换按下的bool。你可以像现在这样用一个本地化的bool

我正试图让它成为一个统一的按钮,它只能每隔几秒钟被按下和激活一次。我有一个带有著名引号的数组,当我按下按钮时,它确实会显示这些引号,但是如果你连续按下按钮,那么它将在所有引号中循环,而无法仔细阅读它们。现在,我尝试了下面的方法,但没有效果(因为按钮仍然可以按下,没有明显的效果):


我认为bool和if循环的简单组合就足够了,但这不起作用。我接近这个概念了吗?要使其正常运行,需要进行哪些更改?

要实现这一点,您可以做一些事情。您当前的代码从未切换按下的bool
。你可以像现在这样用一个本地化的bool捕捉不需要的按钮按下,但是可能有更好的方法

我会考虑改变按钮的难易程度,也告诉终端用户在短时间内不能按按钮。

using UnityEngine.UI;

// button that will be pressed
[SerializeField] private Button btn = null;

// time until the button is re-enabled after being pressed
private float timeToWait = 5f;

// reference to the coroutine that toggles our button
private Coroutine buttonDisabled = null;

private void Start()
{
    // you can either add the OnClick in the inspector, or you can programmatically add it here
    btn.onClick.AddListener(ClickButton);
}

public void ClickButton()
{
    // if we have an ongoing coroutine do not start another
    if(buttonDisabled != null)
        return;

    // start our coroutine to re-enable the button
    buttonDisabled = StartCoroutine(DisableButtonForSeconds(timeToWait));

    // put any other code needed here such as displaying a new quote
}

private IEnumerator DisableButtonForSeconds(float seconds)
{
    // disable the button 
    btn.interactable = false;

    // wait for our amount of time to re-enable
    yield return new WaitForSeconds(seconds);
    
    // re-enable the button
    btn.interactable = true;

    // reset our reference to be called again
    buttonDisabled = null;
}
将编辑器中的按钮指定给
btn
,并设置在按下按钮之间等待
timeToWait
的时间。您还需要将按钮的
OnClick
指定给
ClickButton
,可以是在code中,也可以是在inspector中。使用此解决方案,该函数将无法调用,因为按钮本身将变灰,无法单击。
timeToWait
持续时间结束后,按钮将重新激活。在驱动报价循环的
点击按钮
方法中放置所需的任何其他代码

编辑:这里有类似的代码,但使用
调用
而不是请求的
协同程序

using UnityEngine.UI;

// button that will be pressed
[SerializeField] private Button btn = null;

// time until the button is re-enabled after being pressed
private float timeToWait = 5f;

private void Start()
{
    // you can either add the OnClick in the inspector, or you can programmatically add it here
    btn.onClick.AddListener(ClickButton);
}

public void ClickButton()
{
    // do not start the function if we are already in the process
    if (IsInvoking("ReEnableButton"))
        return;

    // disable our button interactability
    btn.interactable = false;

    // call our function ReenableButton in timeToWait seconds
    Invoke("ReEnableButton", timeToWait);
}

private void ReEnableButton()
{
    // re-enable the button
    btn.interactable = true;
}
编辑2:有几种方法可以让一个按钮禁用所有四个按钮。在一般实践中,您不希望这些按钮相互了解,因此最好制作一个按钮管理器,现在处理
OnClick
,并将事件发送到它知道的所有
按钮

using UnityEngine.UI;

public class ButtonManager : MonoBehaviour
{
    // assign these button references in the inspector by dragging them into the list
    [SerializeField] private List<YourButtonScript> YourButtons = new List<YourButtonScript>();
    
    private void Start()
    {
        // assign the onClick of each button here INSTEAD of the Start() in the button class   
        // you can still have an onClick in the Button itself, but do NOT have it do the disabling
        
        foreach(YourButtonScript btn in YourButtons)
        {
            // assign our onClick to callback to disable all buttons 
            btn.SetDisableOnclick(DisableAllButtons);
        }
    }
    
    public void DisableAllButtons()
    {
        foreach(YourButtonScript btn in YourButtons)
            btn.DisableButton();
    }
}

public class YourButtonScript : MonoBehaviour
{
    using UnityEngine.UI;
        
    // button that will be pressed
    [SerializeField] private Button btn = null;
    
    // time until the button is re-enabled after being pressed
    private float timeToWait = 5f;
    
    // reference to the coroutine that toggles our button
    private Coroutine buttonDisabled = null;
    
    public delegate void DisableButtonCallback();
    
    public void SetDisableOnclick(DisableButtonCallback callback)
    {
        // add the callback to the manager
        btn.onClick.AddListener(delegate{callback();});
    }
    
    private void Start()
    {
        // do NOT call the ClickButton anymore from here as the manager handles it
        // if you have other button specific data put it in HandleSpecificButtonQuoteData() now
        btn.onClick.AddListener(HandleSpecificButtonQuoteData);
    }
    
    private void HandleSpecificButtonQuoteData()
    {
        // put whatever code here that is specific to JUST this button
        // if it handles the quotes or what not, display it here
    }
    
    public void DisableButton()
    {
        // if we have an ongoing coroutine do not start another
        if(buttonDisabled != null)
            return;
    
        // start our coroutine to re-enable the button
        buttonDisabled = StartCoroutine(DisableButtonForSeconds(timeToWait));
    }
    
    private IEnumerator DisableButtonForSeconds(float seconds)
    {
        // disable the button 
        btn.interactable = false;
    
        // wait for our amount of time to re-enable
        yield return new WaitForSeconds(seconds);
        
        // re-enable the button
        btn.interactable = true;
    
        // reset our reference to be called again
        buttonDisabled = null;
    }   
}
使用UnityEngine.UI;
公共类ButtonManager:MonoBehavior
{
//通过将这些按钮参照拖动到列表中,在检查器中指定这些按钮参照
[SerializeField]私有列表按钮=新列表();
私有void Start()
{
//在此处指定每个按钮的onClick,而不是button类中的Start()
//您仍然可以在按钮本身中单击onClick,但不要让它执行禁用操作
foreach(您的按钮在按钮中写btn)
{
//将onClick分配给callback以禁用所有按钮
btn.SetDisableOnclick(禁用按钮);
}
}
public void DisableAllButtons()
{
foreach(您的按钮在按钮中写btn)
btn.DisableButton();
}
}
公共类YourButtonScript:单一行为
{
使用UnityEngine.UI;
//将被按下的按钮
[SerializeField]专用按钮btn=null;
//按钮按下后重新启用之前的时间
专用浮动时间等待=5f;
//对切换按钮的协同程序的引用
private Coroutine buttonDisabled=null;
public delegate void DisableButtonCallback();
public void SetDisableOnclick(DisableButtonCallback回调)
{
//将回调添加到管理器
btn.onClick.AddListener(委托{callback();});
}
私有void Start()
{
//在经理处理时,不要再从这里调用ClickButton
//如果有其他特定于按钮的数据,请立即将其放入HandleSpecificButtonQuoteData()中
btn.onClick.AddListener(HandleSpecificButtonQuoteData);
}
私有void HandleSpecificButtonQuoteData()
{
//在这里输入任何特定于此按钮的代码
//如果它处理引号之类的,请在此处显示它
}
公共无效禁用按钮()
{
//如果我们有一个正在进行的合作项目,不要再开始另一个
如果(按钮禁用!=null)
回来
//启动我们的协同程序以重新启用按钮
buttonDisabled=开始例行程序(禁用ButtonForSeconds(timeToWait));
}
私有IEnumerator DisableButtonForSeconds(浮动秒)
{
//禁用按钮
btn.interactiable=false;
//等待我们的时间量重新启用
产生返回新WaitForSeconds(秒);
//重新启用按钮
btn.interactiable=true;
//重置我们的引用以再次调用
buttonDisabled=null;
}   
}

如果您对此有任何问题,请告诉我。

Clean-我唯一建议的是将方法从
DisableButton
重命名为
EnableButtonAfterDelay
,因为它更好地描述了协同程序正在做什么。@Charleh谢谢!注意并更新。我确实会移动
btn.interactiable=false进入例程,并将其称为
DisableButtonForSeconds(浮动秒)
tbh:D@derHugo我很喜欢。更新!谢谢大家的帮助!您只需在Unity中使用INVOKE作为一个简单的计时器
using UnityEngine.UI;

public class ButtonManager : MonoBehaviour
{
    // assign these button references in the inspector by dragging them into the list
    [SerializeField] private List<YourButtonScript> YourButtons = new List<YourButtonScript>();
    
    private void Start()
    {
        // assign the onClick of each button here INSTEAD of the Start() in the button class   
        // you can still have an onClick in the Button itself, but do NOT have it do the disabling
        
        foreach(YourButtonScript btn in YourButtons)
        {
            // assign our onClick to callback to disable all buttons 
            btn.SetDisableOnclick(DisableAllButtons);
        }
    }
    
    public void DisableAllButtons()
    {
        foreach(YourButtonScript btn in YourButtons)
            btn.DisableButton();
    }
}

public class YourButtonScript : MonoBehaviour
{
    using UnityEngine.UI;
        
    // button that will be pressed
    [SerializeField] private Button btn = null;
    
    // time until the button is re-enabled after being pressed
    private float timeToWait = 5f;
    
    // reference to the coroutine that toggles our button
    private Coroutine buttonDisabled = null;
    
    public delegate void DisableButtonCallback();
    
    public void SetDisableOnclick(DisableButtonCallback callback)
    {
        // add the callback to the manager
        btn.onClick.AddListener(delegate{callback();});
    }
    
    private void Start()
    {
        // do NOT call the ClickButton anymore from here as the manager handles it
        // if you have other button specific data put it in HandleSpecificButtonQuoteData() now
        btn.onClick.AddListener(HandleSpecificButtonQuoteData);
    }
    
    private void HandleSpecificButtonQuoteData()
    {
        // put whatever code here that is specific to JUST this button
        // if it handles the quotes or what not, display it here
    }
    
    public void DisableButton()
    {
        // if we have an ongoing coroutine do not start another
        if(buttonDisabled != null)
            return;
    
        // start our coroutine to re-enable the button
        buttonDisabled = StartCoroutine(DisableButtonForSeconds(timeToWait));
    }
    
    private IEnumerator DisableButtonForSeconds(float seconds)
    {
        // disable the button 
        btn.interactable = false;
    
        // wait for our amount of time to re-enable
        yield return new WaitForSeconds(seconds);
        
        // re-enable the button
        btn.interactable = true;
    
        // reset our reference to be called again
        buttonDisabled = null;
    }   
}