简体   繁体   中英

How to optimise countdown timer?

Dear stackoverflow community,

I have countdown timer for my double points power up and now I have problem because my code works fine in game,but when timer is active game is lagging , not too much but any lag is not good for my game because the player needs to play smoothly without any unoptimised component..

I have this code and I bet the game is lagging because the code is in update method ( I tried to put it in game manager script but then timer won't countdown so that is not solution )

This is the code ( Thanks to stackoverflow user @siusiulala , who wrote me the working code) but seems like it needs to be in another method or something because Update method running performance when has countdown inside.

 private void Update(){ if (isDoublePoints) { // Countdown the timer with update time powerUpTimer -= Time.deltaTime; Debug.Log("TIMER ISS " + powerUpTimer); if (powerUpTimer <= 0) { // End of power up time isDoublePoints = false; } } } public void OnPickPowerUp(float buffTime) { powerUpTimer += buffTime; } 

I hope someone will give solution to lagg because I saw a lot of games that has power up systems without any laggs inside...

Thank you stackoverflow, without you my game would not ever come to end :)

From my experience, Debug.Log() is a very expensive method. It will cause lag when called every frame. My IDE even highlights usage of Debug.Log() in Update() as warning because of that. Use this method only for debugging, and then remove.

If you want to be able to see the timer value, add [SerializeField] attribute to your field and it will show up in the inspector.

You can use the profiler by selecting Window-Analysis-Profiler , assuming you are using Unity 2018.x. It records how much time processing takes, and helps locating bottlenecks.

what trollingchar's answer says about the Debug.Log is correct.

To use the [SerializeField] might be considered as a dirty and lazy hack by some people. Because it has the side-effect that it is now serialized , that means the value is stored in the assets. It's not bad but if you are exact it shouldn't be done with fields that will be changed on runtime anyway.

Instead you can simply go to the Inspector, open the context menu and set it to Debug Mode

在此处输入图片说明

this makes the Inspector not use the Custom EditorScripts but instead reveal all private fields (of Serializable types).

For example for the Transform component

在此处输入图片说明


However way more efficient than using the Update method with a flag at all would be to rather use a Coroutines .

Coroutines can be started and run parallel (every frame right after) the Update method but the advantage: when a coroutine is finished - it is finished and doesn't continue checking the bool flag every frame.

So whenever you pickup a PowerUp instead of setting the flag to true rather use

StartCoroutine(PowerUpRoutine());

and implement a routine like

private IEnumerator PowerUpRoutine()
{
    isDoublePoints = true;

    while(powerUpTimer > 0)
    {
        // Countdown the timer with update time
        powerUpTimer -= Time.deltaTime;
        //Debug.Log("TIMER ISS " + powerUpTimer);

        // yield in simple words makes Unity "pause"
        // the execution here, render this frame and continue from here
        // in the next frame
        yield return null;
    }

    // End of power up time 
    isDoublePoints = false;
}

public void OnPickPowerUp(float buffTime)
{
    powerUpTimer += buffTime;

    // avoid concurrent routines
    if(!isDoublePoints) StartCoroutine(PowerUpRoutine());
}

In order to display it in your game you can use a Text or TextMeshPro and set the text like eg

[SerializeField] private Text _text;

private IEnumerator PowerUpRoutine()
{
    isDoublePoints = true;

    while(powerUpTimer > 0)
    {
        // Countdown the timer with update time
        powerUpTimer -= Time.deltaTime;
        //Debug.Log("TIMER ISS " + powerUpTimer);

        // set the text of the Text component to display the value
        // for the $ symbol google for "c# string interpolation"
        _text.text = $"TIMER IS {powerUpTimer:00.00}";

        // yield in simple words makes Unity "pause"
        // the execution here, render this frame and continue from here
        // in the next frame
        yield return null;
    }

    // End of power up time 
    isDoublePoints = false;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM