【Unity】Unity使用动画实现场景转换

这篇具有很好参考价值的文章主要介绍了【Unity】Unity使用动画实现场景转换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

哈喽,大家好,我是FEZ98.
由于今天需要实现一个小项目中的场景转换效果,于是使用了Animator简单的实现了这个需求,同时也与大家分享一下今日的收获,如果哪里有错误,还望朋友们指正。
使用动画实现简单的场景转换的思路是向场景中添加一个专门处理转换效果的Image(UGUI),同时向其添加一个Animator,向Aniamtor中加入两个State,一个设置为Set as Layer Defalut State,即默认状态,播放进入场景后需要的效果,另一个则设置为关闭场景需要的效果,添加一个转换,并设置相应的参数,这样当我们加载下一场景时,只需要在脚本中设置相应的参数即可调用关闭场景需要的效果。


一、制作LevelLoader

首先我们需要制作一个GameObject用来存放场景转换效果所需对象与脚本,同时可以单独加一个Camera用来单独显示转换特效。如下图:
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui

二、制作相应场景转换特效

1.淡入淡出效果

向LevelLoader中添加一个Canvas,命名为Crossfade,添加一个Image,命名为Mask_Img,这个将这个Image设置为全黑色,如下:
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
此时,我们可以通过Animator来直接控制ImageColorAlpha来调整该图片的透明度,使其实现逐渐透明的效果,这样就可以实现淡出淡出的效果。
可是,如果直接通过控制Alpha来调整透明度,如果后续我们需要在该场景转换效果中添加一些文本或者图片,那么就要单独设置这些新添加的组件的透明度,这样就会很麻烦。因此,我们可以像Mask_Img中添加一个Canvas Group组件,之后把需要添加的组件作为Mask_Img的子节点,那么我们就可以避免做一些多余的工作了。
为Mask_Img添加一个Text子组件,然后直接控制Canvas Group,就可以看到效果了。如下图:
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui

扩展:
Canvas Group可集中控制整组 UI 元素的某些方面,而无需单独处理每个元素。画布组的属性会影响所在的游戏对象以及所有子对象。
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui

回到正文,在添加完Mask_Img后,我们就可以通过Animator控制其Canvas Group来制作动画了,在Hierarchy选中Crossfade对象,按下Ctrl+6打开Animation
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
之后将其命名为Crossfade_End,即创建了一个Animator Clip,同时Unity会自动为我们创建一个名为Crossfade的Animator Controller,并将添加到Crossfade自动添加的Animator组件中。
单击 Animation Record按钮进入动画录制模式,当然也可单击Preview按钮进入预览模式。之后在时间轴中选中1:00的位置,这串数字第一个代表秒,第二个代表帧,1:00即是1秒和60帧。
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
之后将Mask_Img的Canvas Group中的Alpha值由1变成0,即完成了淡入场景转换的动画效果。
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
之后我们可以先单击选中0:00处的关键帧,按住Shift再单击1:00处的关键帧,按Ctrl+C进行复制。之后创建一个新的Animation Clip,命名为Crossfade_Start。
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
再将两个关键帧的位置调转,这样我们就完成了Crossfade_Start的制作。
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
打开Crossfade Animator Controller进入Animator界面,在这里我们就要设置由动画转换状态了,添加一个’Trigger’参数,命名为Start,用来控制在转换场景时通知Animator播放Crossfade_Start效果。
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
之后从Crossfade_End右键单击Make Transition指向Crossfade_Start,同时对Transition进行以下设置
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
之后我们将Crossfade_End和Crossfade_Start的Loop Time取消勾选,因为我们只需要它们播放一次即可。
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
好了,这样我们就完成了淡入淡出的动画转场特效。当然现在还无法在场景中真正的应用,因为还缺少控制脚本,我们会在第三部分讲到同步与异步加载场景的控制脚本。

2.圆形擦除效果

首先我们用Photoshop制作一张如下的png图片。
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
之后,同上述步骤一样,创建一个名为CircleWipe的Canvas,之后将椭圆形图片加入其中,并使其能完全覆盖住CircleWipe。
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
之后将其拖到右侧,使其无法显示在CircleWipe中。
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
我们创建一个Aniamtor Override Controller,其作用是扩展Animator Controller,从而可以使我们使用新的动画替换掉原Animator Controller中使用的动画,但保留其原始结构,参数与逻辑。
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
之后将其添加到CircleWipe的Animator中
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
下面我们制作一个椭圆形由Canvas中间向左侧移动的动画名为CircleWipe_End。

alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
接着我们复制CircleWipe_End的关键帧,同时进行反转,注意这里要将0:00关键帧Position取反,使其从右侧移动到中心。
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
之后,我们进行CircleWipeAnimator Override Controller的设置,将CrossfadeAnimator Controller作为原控制器,之后使用我们新制作的两个动画进行替换即可。
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
这样我们就完成了圆形擦除场景转换效果的制作。

3.Logo旋转效果

对于Logo旋转场景转换的效果步骤大体与圆形擦除一致,以下是LogoRotate_End与LogoRotate_Start的Animation Clip
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui


三、编写控制场景转换效果脚本

1.同步加载场景

(1)将控制脚本添加进LevelLoader中。
public class LoadLevelsManager : MonoBehaviour
{
    Animator animator;

    private void Awake()
    {
        animator = GameObject.Find("Crossfade").GetComponent<Animator>();
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            LoadNextLevel();
        }
    }

    public void LoadNextLevel()
    {
        StartCoroutine(LoadLvel(SceneManager.GetActiveScene().buildIndex + 1));
    }

    IEnumerator LoadLvel(int levelBuildIndex)
    {
        animator.SetTrigger("Start");   //播放淡出特效

        yield return new WaitForSeconds(1);   //等待1秒,因为单个场景转换特效的时长是1秒

        SceneManager.LoadScene(levelBuildIndex);   //加载Scenes In Build 中下一场景
    }
}
(2)创建一个新场景,并将LevelLoader添加进其中。

alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui

(3)将场景添加进Build Settings。

alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui

(4)最终淡入淡出效果。

alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui

(5)最终圆形擦除效果。

alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui

(6)最终Logo旋转效果。

alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui

2.异步加载场景

(1)分析需求。

这部分我们会在异步加载场景的过程中添加场景转换效果。
首先,我们将Crossfade的Animator设置如下
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui
其中Crossfade_Idle是一个什么都不发生的动画。

因为每次新创建一个场景,我们都需要将LevelLoader预制体添加到场景中会比较麻烦,因此我考虑使用单例模式加上DontDestroyOnLoad方法,这样在第一次加载后,LevelLoader就不会被销毁,在后续新添加的场景中自然也不用添加LevelLoader了。之后,我们还希望使用一个LevelLoader就可以使用不同的场景转换动画,这样可以方便我们进行后续新的场景转换动画的添加与使用。于是我们需要添加一个用于控制不同场景转换动画的脚本。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum Effect  //三种场景转换特效
{
    Crossfade = 0,  //淡入淡出
    CircleWipe = 1, //圆形擦除
    LogoRotate = 2, //Logo旋转
}

public class TransitionEffect : MonoBehaviour
{
    private static TransitionEffect _instance;
    public static TransitionEffect Instance { get { return _instance; } }

    Animator m_CrossfadeAnim;   //淡入淡出
    Animator m_CircleWipeAnim;  //圆形擦除
    Animator m_LogoRotateAnim;  //Logo旋转

    private void Awake()
    {
        if (_instance == null)
        {
            DontDestroyOnLoad(this);
            _instance = this;
        }
        else
        {
            Destroy(this);
        }

        m_CrossfadeAnim = GameObject.Find("Crossfade").GetComponent<Animator>();
        m_CircleWipeAnim = GameObject.Find("CircleWipe").GetComponent<Animator>();
        m_LogoRotateAnim = GameObject.Find("LogoRotate").GetComponent<Animator>();
    }

    /// <summary>
    /// 播放指定类型场景转换结束动画
    /// </summary>
    /// <param name="effect">场景转换特效类型</param>
    public void HandleAllAnimationEnd(Effect effect)
    {
        switch (effect)
        {
            case Effect.Crossfade:
                SetTransitionEffectEnd(m_CrossfadeAnim);
                break;
            case Effect.CircleWipe:
                SetTransitionEffectEnd(m_CircleWipeAnim);
                break;
            case Effect.LogoRotate:
                SetTransitionEffectEnd(m_LogoRotateAnim);
                break;
            default:
                break;
        }
    }

    private void SetTransitionEffectEnd(Animator animator)
    {
        animator.SetTrigger("End");
        Debug.Log("AnimationClip_End is Start!");
    }

    /// <summary>
    /// 播放指定类型场景转换开始动画
    /// </summary>
    /// <param name="effect">场景转换特效类型</param>
    public void HandleAllAnimationStart(Effect effect)
    {
        switch (effect)
        {
            case Effect.Crossfade:
                SetTransitionEffectStart(m_CrossfadeAnim);
                break;
            case Effect.CircleWipe:
                SetTransitionEffectStart(m_CircleWipeAnim);
                break;
            case Effect.LogoRotate:
                SetTransitionEffectStart(m_LogoRotateAnim);
                break;
            default:
                break;
        }
    }

    private void SetTransitionEffectStart(Animator animator)
    {
        animator.SetTrigger("Start");
        Debug.Log("AnimationClip_Start is Start!");
    }

    /// <summary>
    /// 判断当前动画是否完成播放
    /// </summary>
    /// <param name="effect">场景转换特效类型</param>
    /// <returns></returns>
    public bool HandleAllAnimationDone(Effect effect)
    {
        switch (effect)
        {
            case Effect.Crossfade:
                return IsAnimationClipDone(m_CrossfadeAnim);
            case Effect.CircleWipe:
                return IsAnimationClipDone(m_CircleWipeAnim);
            case Effect.LogoRotate:
                return IsAnimationClipDone(m_LogoRotateAnim);
            default:
                break;
        }
        return false;
    }

    private bool IsAnimationClipDone(Animator animator)
    {
        //normalizedTime:整数部分为状态已循环的次数。小数部分为当前循环的进度百分比 (0-1)
        if (animator.GetCurrentAnimatorStateInfo(0).normalizedTime < 1)
        {
            return false;
        }
        Debug.Log("AnimationClip is Over!");
        return true;
    }
}

代码比较简单并且都加上了注释,就不进行详细讲解了。TransitionEffect 主要用到了单例模式,配合上DontDestroyOnLoad它就可以在运行期间一致存在,我们就不用向同步加载场景那样需要不断往新创建的场景中加入LoadLevelManager。
下一部分是控制异步加载场景及选择使用的场景转换特效。
LoadNextLevel(string levelName, Effect effect)方法有两个参数,一个是下一需要加载场景的名称,一个用于控制场景转换效果类型(淡入淡出、圆形擦除、Logo旋转等)。
LoadLevel(string levelName, Effect effect)则是具体实现异步加载的一个协程。我们需要在开始异步加载后,将allowSceneActivation设置为false,这样asyncOperation.progre会停在0.9并且asyncOperation.isDone也会一直为false。将LoadAble设置为false,这样除非当前协程执行完毕,否则无法调用加载另一个场景的方法。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class AsyncLoadLevelManager : MonoBehaviour
{
    private static AsyncLoadLevelManager _instance;
    public static AsyncLoadLevelManager Instance { get { return _instance; } }

    public bool LoadAble { get; private set; }  //当前是否可以场景转换

    private void Awake()
    {
        if (_instance == null)
        {
            DontDestroyOnLoad(this);
            _instance = this;
        }
        else
        {
            Destroy(this);
        }
    }

    private void Start()
    {
        LoadAble = true;    //初始允许场景转换
    }

    /// <summary>
    /// 使用指定场景转换特效异步加载下一场景
    /// </summary>
    /// <param name="levelName">下一场景名称</param>
    /// <param name="effect">场景转换特效类型</param>
    public void LoadNextLevel(string levelName, Effect effect)
    {
        if (!LoadAble)
        {
            return;
        }

        StartCoroutine(LoadLevel(levelName, effect));
    }

    IEnumerator LoadLevel(string levelName, Effect effect)
    {
        AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(levelName); //异步加载下一场景
        asyncOperation.allowSceneActivation = false;
        //当allowSceneActivation为false时,asyncOperation.progre会停在0.9并且asyncOperation.isDone也会一直为false
        LoadAble = false;   //当前不允许转换场景

        TransitionEffect.Instance.HandleAllAnimationStart(effect);  //播放场景转换开始动画

        yield return null;

        while (asyncOperation.progress < 0.9f)  //检查是否已完成异步加载
        {
            yield return null;
        }

        while (!TransitionEffect.Instance.HandleAllAnimationDone(effect))   //检查当前动画是否完成播放
        {
            yield return null;
        }

        asyncOperation.allowSceneActivation = true; //允许场景准备就绪后立即激活场景

        while (!asyncOperation.isDone)  //检查是否已经激活场景
        {
            yield return null;

            TransitionEffect.Instance.HandleAllAnimationEnd(effect);    //播放场景转换结束动画
        }

        while (!TransitionEffect.Instance.HandleAllAnimationDone(effect))   //检查当前动画是否完成播放
        {
            yield return null;
        }

        LoadAble = true;    //可以继续转换场景
    }
}

之后,我们用一个测试脚本进行方法的调用。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))    //点击鼠标左键
        {
            AsyncLoadLevelManager.Instance.LoadNextLevel("SceneB", Effect.Crossfade);
        }
        else if (Input.GetMouseButtonDown(1))   //点击鼠标右键
        {
            AsyncLoadLevelManager.Instance.LoadNextLevel("SceneC", Effect.CircleWipe);
        }
        else if (Input.GetMouseButtonDown(2))   //点击鼠标中键
        {
            AsyncLoadLevelManager.Instance.LoadNextLevel("SceneA", Effect.LogoRotate);
        }
    }
}

最终效果如下:
alphaclip 动态场景切换,UGUI,Unity,unity,游戏引擎,ui

扩展
背景图片移动

using UnityEngine;
using UnityEngine.UI;

public class BackgroundMove : MonoBehaviour
{
   public float speed = 0; //移动速度
   float pos = 0;  //当前位置
   private RawImage image;

   void Start()
   {
       image = GetComponent<RawImage>();
   }

   void Update()
   {
       pos += speed;

       if (pos > 1.0F)

           pos -= 1.0F;

       image.uvRect = new Rect(pos, 0, 1, 1);
   }
}

四、完毕

好啦,以上就是我今天想要分享的内容啦~
我是FEZ98:https://blog.csdn.net/weixin_43057990
原创不易,若转载请注明出处,感谢大家~
喜欢我的可以点赞、关注、收藏,最后希望能够对大家有所帮助!文章来源地址https://www.toymoban.com/news/detail-778611.html

到了这里,关于【Unity】Unity使用动画实现场景转换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • unity场景转换(实现开始游戏和返回游戏)

    1、新建两个场景,一个命名为start,另一个命名为game,如下图 2、打开start,创建一个平面和一个按钮(右键,UI,Button),平面绕X轴旋转-90度,按钮的text设置为开始游戏,把按钮拖到场景中合适的位置,如下图 3、编写代码start,把它赋给Canvas,注意是赋给Canvas,不是给按钮,代

    2024年02月11日
    浏览(24)
  • Unity切换场景保存上一个场景的数据,Unity切换场景的案例,Unity切换场景再返回数据丢失的解决方案

    Unity在切换场景之后在再次返回上不会保存上一个场景的数据的。 但是大多数时候我们是需要这些数据的,这应该如何解决呢? 文件链接:我将解决方案打包了,点我下载,免费,或者私信我发你 首先将需要存储到一个class中,这里以学生为例子 然后我们再创建一个脚本,

    2024年02月02日
    浏览(38)
  • Unity中动画切换

    在unity中,3D模型的切换可以使用animator状态机或者代码切换 Animator.CrossFade 切换函数 使用状态机切换 需要连接各个动画的逻辑关系,并且添加切换参数,设置退出时间,调整切换持续时间等。然后直接使用切换参数SetTrigger等切换。 优点就是直观,方便编辑。缺点就是连线太

    2024年02月05日
    浏览(23)
  • Unity基于PICO4设备实现VR下的多场景切换(巨详细,案例全csdn仅此一家)

    打开unity Hub,先点击左侧项目一栏,再点击右上角的新项目,弹出创建窗口后,选择URP模板,自定义项目名称和位置,取消勾选版本管理,最后点击创建项目即可(注意:我这里的unity版本为2020.3.37f1c1 LTS)。 点击创建项目后,第一次创建项目时,需等待一段时间加载,项目初

    2024年02月10日
    浏览(45)
  • unity人物基础动画应用。行走、待机之类的简单动画切换。

    @[TOC]unity人物基础动画应用 直接将项目拖入资源层级就好。这里推荐一个网站,可以给导入网站的模型自动绑骨,并且可挑选动画下载。网站自身也带有很多模型可以直接下载。免费又好用,就是可能网有点慢。 链接: link 1)在项目管理器中右键-创建-动画控制器。双击新建的

    2024年02月08日
    浏览(43)
  • Unity UI动效 - Toggle切换动画

    如下图所示,当 Toggle 的 OnValueChanged 事件执行时,会播放相应的切换动画,该功能可以通过 Animation Editor 编辑帧动画来实现,而本文介绍如何通过代码实现。 为Toggle添加值变更事件: 动画的切换过程在协程中实现,当值变更时,判断当前若正在运行协程,将其终止,然后开

    2024年02月04日
    浏览(38)
  • Unity基础 场景概念以及场景切换

    在Unity中,场景可以理解为一种游戏关卡。它是一个包含了游戏中各种元素的环境,如游戏物体、光照、相机、音频等等。每个场景都可以通过Unity提供的一系列方法和变量进行操作和管理。 在Unity中,场景有以下特点: 可以包含多个游戏物体。 可以包含多个光源和相机。

    2024年02月06日
    浏览(31)
  • Unity 切换场景后场景变暗

    Unity版本:2019.4.34f1c1 主场景只有UI,没有灯光,天空盒;其他场景有灯光和天空盒 所有场景不烘焙 主场景作为启动场景运行,切换到其他场景,场景变暗 某一个场景作为启动场景运行,光影效果正常, 切换到其他场景,场景变暗; 切换到启动场景,光影正常 方法1:烘焙场

    2024年02月06日
    浏览(32)
  • 【Unity2D】角色动画的切换

    第一种方法是设置一个中间状态,从中间状态向其余各种状态切换,且各状态向其他状态需要设置参数 实现动作转移时右键点击Make Transition即可  实现动画转移需要设置条件 点击一种动画到另一种动画的线 ,然后点击加号添加Condition 比如机器人从向左走切换到向右走的条件

    2024年02月15日
    浏览(41)
  • Unity简单操作:设置触发条件 切换Animator动画控制器 里面播放的Animation动画

    确保animator里面有多个animation动画剪辑,点击Animator里面[Parameters]添加触发条件   添加连线箭头并且 给箭头连线绑定触发事件  添加连线箭头并且 给箭头连线绑定触发事件  

    2024年02月04日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包