【问题标题】:How to optimise countdown timer?如何优化倒计时?
【发布时间】:2019-07-12 23:53:02
【问题描述】:

尊敬的 stackoverflow 社区,

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

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

这是代码(感谢 stackoverflow 用户 @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;
    }

我希望有人能给出延迟的解决方案,因为我看到很多游戏都有通电系统,内部没有任何延迟...

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

【问题讨论】:

  • 除非Debug.Log() 效率极低或者您调用它数百万次,否则这段代码应该不会产生明显的开销。请分析您的代码,看看您的假设是否正确。
  • 如何分析我的代码?谢谢你的评论。 Debug.Log 只被调用了 15 次..
  • This page in the official documentation 可能会有所帮助。

标签: c# unity3d timer game-development


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    trollingchar's answer 关于Debug.Log 的说法是正确的。

    使用[SerializeField] 可能被某些人认为是一种肮脏和懒惰的黑客行为。因为它具有现在序列化的副作用,这意味着值存储在资产中。这还不错,但是如果您确切的话,无论如何都不应该使用将在运行时更改的字段。

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

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

    例如Transform 组件


    然而,比使用带有标志at allUpdate方法更有效的方法是使用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;
    }
    

    【讨论】:

    • 我认为我的表现不好,因为它一直在检查脚本是否处于活动状态。但我不知道如何为同一份工作制作 courutine。感谢您帮助我指出我的 courutine .. 直到现在我开始使用 isDoublepoints=true;现在我应该只调用这个文本来启动它吗? “启动协程(PowerUpRoutine());” ,谢谢你再一次指出我如何使用 courutine.. 还有一个问题,我可以在游戏中显示倒数计时器吗?你是最棒的!
    • 更新了如何在游戏中显示文字的答案..也通过一般UI Manuals
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-13
    • 1970-01-01
    • 1970-01-01
    • 2012-02-11
    • 1970-01-01
    相关资源
    最近更新 更多