如何优化倒数计时器?

时间:2019-07-12 00:33:32

标签: c# unity3d timer game-development

尊敬的stackoverflow社区,

我有倒数计时器来加倍计时,但现在我遇到了问题,因为我的代码在游戏中可以正常工作,但是当计时器处于活动状态时,游戏会滞后,虽然不是太多,但是任何滞后对我的游戏都没有好处,因为玩家需要在没有任何未优化组件的情况下平稳地播放。

我有此代码,我敢打赌游戏会滞后,因为该代码位于更新方法中(我试图将其放在游戏管理器脚本中,但计时器不会倒数,所以这不是解决方案)

这是代码(感谢stackoverflow用户@siusiulala,他为我编写了工作代码) 但似乎需要使用其他方法或其他方法,因为当内部具有倒数计时时,Update方法的运行性能会有所提高。

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

我希望有人能解决滞后问题,因为我看到很多具有加电系统的游戏都没有滞后现象...

谢谢stackoverflow,没有你,我的游戏将永远不会结束:)

2 个答案:

答案 0 :(得分:4)

根据我的经验,Debug.Log()非常昂贵的方法。每帧调用时 都会导致延迟。因此,我的IDE甚至突出显示Debug.Log()Update()的使用作为警告。仅将此方法用于调试,然后删除。

如果要查看计时器值,请在字段中添加[SerializeField]属性,该属性将显示在检查器中。

假设您正在使用Unity 2018.x,则可以通过选择 Window-Analysis-Profiler 来使用分析器。它记录了处理所花费的时间,并有助于查找瓶颈。

答案 1 :(得分:3)

trollingchar's answerDebug.Log的评价是正确的。

使用[SerializeField]可能被某些人视为肮脏而懒惰的骇客。由于它具有副作用,现在已经被序列化,这意味着该值存储在资产中。这还不错,但是如果您是准确的话,则不应使用将在运行时更改的字段来完成操作。

相反,您只需转到检查器,打开上下文菜单并将其设置为Debug模式

enter image description here

这使检查器不使用自定义EditorScripts,而是显示所有(Serializable类型的私有字段)。

例如Transform组件

enter image description here


比起使用带有标志 Update方法更有效的方法是宁愿使用Coroutines

协程可以Update方法启动并并行运行(紧随其后的每一帧),但是好处是:协程完成后-协程完成并且不再继续检查bool标志框架。

因此,每当您启动PowerUp而不是将标志设置为true时,都要使用

StartCoroutine(PowerUpRoutine());

并实现类似

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

要在游戏中显示该文字,您可以使用TextTextMeshPro并设置文字,例如

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