Unity学习笔记--Time.timeScale=0暂停的时候实现动画效果

首先上效果图
在这里插入图片描述

重点


重点一

首先当你想用Time.timeScale=0使游戏暂停的时候,FixedUpdate是不会被调用的,Animation也不会继续播放,所以我们只能用代码去控制动画的播放了。


重点二

不可以用Lerp插值和SmoothDamp函数来用代码实现动画的播放。
他们都需要用到Time.timeScale,但是Time.timeScale=0,所以他们也不考虑了。


重点三

realtimeSinceStartuptimeScale无关。
我们来看看realtimeSinceStartup的官方描述

定义:游戏开始以来的实际时间(只读)。

在几乎所有情况下,您都可以并且应该使用 Time.time。
realtimeSinceStartup 返回自启动以来的时间,不受 Time.timeScale 的影响。 在播放器暂停期间(在后台),realtimeSinceStartup 仍会不断增加。 当您需要通过将 Time.timeScale 设置为 0 来暂停游戏,但仍希望能够以某种方式测量时间时, realtimeSinceStartup 非常有用。
注意,realtimeSinceStartup 返回系统计时器报告的时间。 根据平台和硬件的不同,它可能会在数个连续帧中报告相同的时间。 如果您需要用某个值除以时间差,一定要考虑到这一点 (时间差可能会变为 0!)。

这就给了我们制作暂停动画的可能。

具体实现

先给上UI的原来的坐标(正常游戏的坐标,此时UI是在屏幕之外)
在这里插入图片描述
在这里插入图片描述

UI变换之后的坐标(此时UI在屏幕的中间)
在这里插入图片描述
在这里插入图片描述

总效果

在这里插入图片描述

代码

当玩家按下暂停键的时候调用如下代码:

    private IEnumerator Pause()
    {
    
    
        Time.timeScale = 0f;
        RectTransform rectTransform = GetComponent<RectTransform>();//需要移动的UI的RectTransform
        float lastFrameTime;//上一帧的时间
        float currentFrameTime;//当前帧的时间
        float deltaTime;//相邻两帧的时间间隔
        while (rectTransform.anchoredPosition3D.y > Mathf.Epsilon)//如果UI的y坐标大于0(Mathf.Epsilon代表浮点数的最小值,浮点数运算尽量别用整数)
        {
    
    
            lastFrameTime = Time.realtimeSinceStartup;//更新上一帧的时间
            yield return null;//跳过这一帧,为了在下一帧计算相邻两帧的间隔
            currentFrameTime = Time.realtimeSinceStartup;//更新当前帧的时间
            deltaTime = currentFrameTime - lastFrameTime;//计算相邻两帧的时间间隔
            /*
             * menuOriginPosY代表UI的原来的y坐标
             * rectTransform.anchoredPosition3D + Vector3.down * menuOriginPosY的意思是将UI的y坐标从原来的位置变换到y=0的位置,也就是中心位置
             */
            rectTransform.anchoredPosition3D = Vector3.Lerp(
                rectTransform.anchoredPosition3D,
                rectTransform.anchoredPosition3D + Vector3.down * menuOriginPosY,//可以理解为 y = y + (-1) * y;
                deltaTime * animationDeltaTimeRate);//animationDeltaTimeRate是变换频率,如果该值过高变换速度快
        }
        //指定到暂停的位置,因为Lerp不能准确定位到一个整数,所以我们这里给它定位一下
        rectTransform.anchoredPosition3D = m_menuPausePos;
    }

下面实现下继续游戏的代码(步骤基本一样我就不写注释了)

    public IEnumerator Resume()
    {
    
    
        RectTransform rectTransform = GetComponent<RectTransform>();
        float lastFrameTime;
        float currentFrameTime;
        float deltaTime;
        while (rectTransform.anchoredPosition3D.y < menuOriginPosY)
        {
    
    
            lastFrameTime = Time.realtimeSinceStartup;
            yield return null;
            currentFrameTime = Time.realtimeSinceStartup;
            deltaTime = currentFrameTime - lastFrameTime;
            rectTransform.anchoredPosition3D = Vector3.Lerp(
                rectTransform.anchoredPosition3D, 
                rectTransform.anchoredPosition3D + Vector3.up * menuOriginPosY,
                deltaTime * animationDeltaTimeRate);
        }
        //恢复到原位
        rectTransform.anchoredPosition3D = m_menuOriginPos;
        Time.timeScale = 1f;
    }

猜你喜欢

转载自blog.csdn.net/qq_52855744/article/details/121374994