Ved Sarkar Ved Sarkar - 3 months ago 22
C# Question

Unity: How to Delay button call by time?

I desire to increment an float by 0.5 every time the user clicks the UI button and if the user presses the button for more than 2 second want to continuously increment the float by 0.5, to do so i use Event trigger (PointerDown, PointerUp) and call the functions in update. When i user the down below code i cant increment the float value continuously.

Update Code

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


PointerDown Function

public void WhenIncreaseClicked()
{
if (timeDown < 2.0f)
IncreaseBPM ();
else
increase = true;
}


PinterUp function

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


Start

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


I have set
timeDown = Time.deltaTime
in
Start()
.

Answer

First of all, Unity documentation says about Time.deltaTime

The time in seconds it took to complete the last frame.

When you set timeDown = Time.deltaTime timeDown becomes a tiny fraction, for example 0.01621689. Therefore, timeDown < 2.0f always returns true and your code never reaches increase = true; line.

Second point you should know is Time.time

The time at the beginning of this frame (Read Only). This is the time in seconds since the start of the game.

You used Time.time in your Update() method as Mathf.Sin(Time.time * speed). Bear in mind that Time.time can be enough large number representing the time in seconds since the start of the game as mentioned in document. When you do Time.time * speed the output number may be huge (assuming speed > 1) causing some problems. Luckily, you are using it inside Mathf.Sin() you get number only between [0, 1]. Probably, you intended to use Time.deltaTime instead.


Let's remember Time.time:

The time in seconds since the start of the game

You can use this to check time difference.

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

Note: Unity says about Time.timeScale:

Except for realtimeSinceStartup, timeScale affects all the time and delta time measuring variables of the Time class.

So if you insist on using Time.timeScale, instead of using Time.time you should use Time.realtimeSinceStartup in above example.