Unity:如何按时间延迟按钮调用

本文关键字:按钮 调用 时间延迟 何按 Unity | 更新日期: 2023-09-27 18:05:41

我希望每次用户点击UI按钮时增加一个浮动0.5,如果用户按下按钮超过2秒,想要持续增加浮动0.5,为此,我使用事件触发器(PointerDown, PointerUp)并调用更新中的函数。当我使用下面的代码时,它不能连续增加浮点值。

<<p> 更新代码/strong>
void Update () {
    transform.rotation = Quaternion.Lerp (qStart, qEnd, (Mathf.Sin(Time.time * speed) + 1.0f) / 2.0f);
    if(Time.timeScale == 0)
        transform.rotation =  Quaternion.Euler(0,0,0);
    clickCondition ();      
}
<<p> PointerDown函数/strong>
public void WhenIncreaseClicked()
{ 
    if (timeDown < 2.0f)
        IncreaseBPM ();
    else
        increase = true;    
}
<<p> PinterUp函数/strong>
public void WhenIncreaseNotClicked()
{ 
    increase = false; 
    Time.timeScale = 1;
}

IncreaseBPM

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

ClickCondition

public void clickCondition()
{   
    if(increase)
    { 
        IncreaseBPM();
    }
    else if(decrease)
    { 
        DecreaseBPM();
    }
}

void Start () {
    qStart = Quaternion.AngleAxis ( angle, Vector3.forward);
    qEnd   = Quaternion.AngleAxis (-angle, Vector3.forward);
    timeDown = Time.deltaTime;
    if (PlayerPrefs.HasKey ("savedBPM"))
        speed = PlayerPrefs.GetFloat ("savedBPM");
    else
        speed = 1.5f;
}

我在Start()中设置了timeDown = Time.deltaTime

Unity:如何按时间延迟按钮调用

假设没有其他代码改变您的increase变量,您将无法连续增加它,因为它永远不会被设置为true

Start()中你有一行timeDown = Time.deltaTime;,所以timeDown将等于从上一帧开始的秒数。这不仅是一个问题,因为timeDown永远不会改变(Start()只被调用一次),但这是一个问题,因为它不可能超过2.0f,因为一个帧极不可能花2秒来完成。它通常是一个非常小的数字,例如0.06f

因此,在WhenIncreaseClicked()方法中,if (timeDown < 2.0f)将始终等于true。因此,else子句永远不会被执行,increase也永远不会被设置为true。

要解决这个问题,你可以创建一个新的布尔变量,例如clicked,并在WhenIncreaseClicked()开始时设置为true,在WhenIncreaseNotClicked()开始时设置为false。然后在Update()中,如果clickedtrue,则可以将Time.deltaTime添加到timeDown。您还需要将if/else从WhenIncreaseClicked()移到Update()中,确保它仅在clickedtrue时运行。

例如:

void Update () {
    transform.rotation = Quaternion.Lerp (qStart, qEnd, (Mathf.Sin(Time.time * speed) + 1.0f) / 2.0f);
    if(Time.timeScale == 0)
        transform.rotation =  Quaternion.Euler(0,0,0);
    if(clicked) {
        timeDown += Time.deltaTime;
        if (timeDown >= 2.0f) // note the >= not <
            increase = true;
    }
    clickCondition ();
}

and WhenIncreaseClicked():

public void WhenIncreaseClicked()
{ 
    clicked = true;
    IncreaseBPM();   
}

and WhenIncreaseNotClicked():

public void WhenIncreaseNotClicked()
{ 
    clicked = false;
    increase = false;
    Time.timeScale = 1;
}

你也可以在Start()中删除对timeDown的赋值,因为它没有用。

首先,Unity文档中提到了Time.deltaTime

以秒为单位完成最后一帧所需的时间。

设置timeDown = Time.deltaTime时,timeDown变成一个微小的分数,例如0.01621689。因此,timeDown < 2.0f总是返回true,你的代码永远不会到达increase = true;行。

第二点你应该知道的是Time.time

帧开始的时间(只读)。这是以秒为单位的时间,从游戏开始。

你在Update()方法中使用Time.time作为Mathf.Sin(Time.time * speed)。请记住,Time.time可以是足够大的数字,表示从文件中提到的游戏开始的时间(以秒为单位)。当您执行Time.time * speed时,输出数量可能会很大(假设是speed > 1),从而导致一些问题。幸运的是,您在Mathf.Sin()中使用它,您只获得[0,1]之间的数字。可能,您打算使用Time.deltaTime代替。


让我们记住Time.time:

游戏开始后的秒数

你可以用这个来检查时差

float lastDownTime;
bool isDown;

void OnPointerDown() // Method name itself says when it should be called
{
    lastDownTime = Time.time;
    isDown = true;
}

void OnPointerUp()
{
    isDown = false;
}

void Update () 
{
    if (isDown)
    {
        if  (Time.time - lastDownTime  > 2) // 2 seconds
        {
            IncreaseBPM ();
        }
    }
}

注意: Unity说关于Time.timeScale:

realtimeSinceStartup外,timeScale影响time类的所有时间和增量时间度量变量。

所以如果你坚持使用Time.timeScale,而不是使用时间。在上面的例子中,你应该使用Time.realtimeSinceStartup