如何优化倒数计时器?

How to optimise countdown timer?

亲爱的 Whosebug 社区,

我有双倍加电倒数计时器,现在我遇到了问题,因为我的代码在游戏中运行良好,但是当计时器处于活动状态时,游戏会滞后,不会太多,但任何滞后对我的游戏都不利,因为播放器需要流畅播放,没有任何未优化的组件..

我有这段代码,我敢打赌游戏是滞后的,因为代码在更新方法中(我试图把它放在游戏管理器脚本中,但计时器不会倒计时,所以这不是解决方案)

这是代码(感谢 Whosebug 用户@siusiulala,他给我写了工作代码) 但似乎需要使用另一种方法或其他方法,因为更新方法 运行 性能在内部有倒计时。

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

我希望有人能解决 lagg 的问题,因为我看到很多游戏都有 power up 系统,里面没有任何 laggs...

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

根据我的经验,Debug.Log() 是一种非常 昂贵的方法。它在每帧调用时造成延迟。因此,我的 IDE 甚至将 Debug.Log()Update() 中的用法突出显示为警告。此方法仅用于调试,然后删除。

如果您希望能够看到计时器值,请将 [SerializeField] 属性添加到您的字段,它会显示在检查器中。

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

关于 Debug.Log 的说法是正确的。

使用 [SerializeField] 可能会被一些人认为是 肮脏和懒惰的 黑客行为。因为它有 side-effect 现在是 序列化 ,这意味着价值存储在资产中。这还不错,但如果你是准确的,那么无论如何都不应该使用将在 运行 时间更改的字段。

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

这使得 Inspector 不使用自定义 EditorScript,而是显示所有私有字段(Serializable 类型)。

例如 Transform 组件


然而,比使用带有标志 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());
}

为了在您的游戏中显示它,您可以使用 Text or TextMeshPro 并设置文本,例如

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