Unity3D RPG Core | 35 场景转换的渐入渐出
这节我们使用 Unity Timeline 制作游戏开始时的开场动画。同时,之前的场景传送功能在视觉效果上有点突兀。我们增加一个场景切换的渐入渐出功能。
1. Timeline 创建动画
我们点击 Window - Sequencing - Timeline,打开如图 1 所示的 Timeline 窗体。
Timeline 窗体中我们可以看到 "To start creating a timeline, select a GameObject"。为此我们新建一个空对象,用于承载 Timeline 组件。接着点击 Timeline 窗体上的 Create 按钮,创建并保存 Timeline。
记得先要选中想要的对象,再在其下创建 Timeline。
1.1 为相机创建动画
我们首先为相机创建动画,让相机位置逐渐靠近传送门。在 Timeline 窗体左侧右击选择新建 Animation Track。
接着如图 2 所示,我们把相机组件拖拽到动画轨道组件上。并且右上角选择 Timecode 模式。
注意要切换到 Timecode 模式。此处视频中没有说。
设置好后点击录制按钮。选择相机组件下的 Position 位置,右击选择 Add Key 添加开始关键帧。
我们想要动画为 3 秒,因此如图 4 所示,将拖拽进度条到 3 秒的位置。接着修改相机的终点位置,这时会自动添加关键帧。
注意添加第一帧关键帧之后,如果位置信息变化了会自动添加关键帧。所以需要先移动进度条到结尾。
至此相机的动画就制作好了,我们再次点击录制按钮结束录制。可以点击播放按钮,预览一下效果。
1.2 为角色人物创建动画
如图 5 所示,我们同样为人物角色创建一条 Animation Track。因为人物组件上已经有了动画控制器,所以我们可以将奔跑的动画拖拽到时间条上。
但是默认奔跑动画只能播放一遍,为此我们如图 6 所示,将 Post-Extrapolate 设置为 Loop。同时将动画条放置最左端,然后拉到 3 秒处(即覆盖整个动画周期)。
添加了动画,角色人物的坐标会变到零的默认值。为此我们点击图 5 箭头处位置,选择 Add Override Track。我们就在这条新的轨道上设置角色位置变化动画,设置的方式和设置相机时一样。
如果想要首帧的位置和原先显示的一样,记得记录一下角色人物的起始位置。
1.3 禁用 EventSystem
在播放动画期间,我们还是可以和 UI 进行交互(比如键盘选择、按 Enter 键等)。这会影响到程序逻辑,因此我们新建一条 Activation Track,并拖拽指定 EventSystem。
默认 EventSystem 是处于 Active 状态的,我们需要在 Timeline 时间轴上将其删除。
2. 控制动画播放
动画默认情况下在程序运行的时候就会执行。我们需要在点击新游戏的时候再进行播放,所以如图 7 所示,我们取消勾选 Play On Awake,在代码中控制播放时机。
如代码清单 1 所示,我们改变之前主界面控制器的逻辑。首先通过 FindObjectOfType() 获取到动画播放器(第 11 行)。之前的新游戏点击事件 OnNewGameClick() 改为播放动画,即点击新游戏会播放动画。
最后需要考虑的是,我们何时运行之前的场景切换功能:我们为动画播放器设置播放完成的 stopped 事件(第 12 行),即在动画播放完后进行场景切换。
3. 实现渐入渐出
首先我们创建一个新的画布,并在其下添加 Image UI 组件。如图 8 所示,我们按 Alt + Shift 键,再点击矩阵框出的按钮,以平铺 Image。
接着我们在 Canvas 下添加 Canvas Group 组件,如图 9 所示,我们就是控制其 Alpha 值来实现渐入渐出。
3.1 代码控制
我们新建 C# 脚本,并命名为 FadeController。如代码清单 2 所示,我们首先获取到 CanvasGroup 组件(第 7 行);因为渐入渐出涉及不同场景,所以我们设置其场景切换时不销毁(第 8 行);定义渐入 FadeIn() 和渐出 FadeOut() 这两个协程格式的函数,因为需要外部指定调用,我们需要将其定义为公有方法。
我们实现渐入渐出的方式是,在场景切换前通过预制体创建出新的 FadeController 实例,然后通过协程调用其中的渐入渐出函数。因此我们先将 FadeController 脚本拖拽到之前的画布组件上,并将其指定为预制体,然后原先场景中的画布组件就可以删除了。
因为渐入渐出画布是预制体实例化出来的,所以务必记得销毁。在代码清单 2 的第 28 行,当渐入到新场景完成后,就可以销毁组件了。
实现完 FadeController 并制作好预制体之后,我们就可以在 SceneController 中调用了。如代码清单 3 所示,我们首先指定预制体(第 3 行);接着在原先不同场景传送的协程前后,增加渐出(第 8 行)和渐入(第 28 行)。
返回主界面的不同场景加载接口函数有所不同。如代码清单 4 所示,加上渐入渐出也是同样的操作。
4. 角色死亡逻辑完善
以上已经完成了渐入渐出的功能了。在此基础上,注意到人物角色死亡时也可以回到主界面,以完善角色死亡这块的逻辑。
实现的方式之前也已经有过了,如代码清单 5 所示,继承 IEndGameObserver,实现其中的响应接口,响应的措施为返回主界面。同时需要在 Start 函数中注册观察者。
我们还需要更改一下之前的通知机制。因为死亡是一个状态更改,只需要通知一次就可以了,每帧通知会造成负载过大,且影响以上的场景加载逻辑。如代码清单 6 所示,我们新增一个变量,指示是否通知过,以确保只通知过一次。
5. 测试
如果测试的时候,想要修改动画逻辑,比如想要人物先跑一段时间,相机再跟上。我们不需要重新制作动画,可以直接在现有 Timeline 上修改:如图 10 所示,我们双击相机时间轴上的动画。进入编辑界面后,可以拖拽移动第一帧关键帧的位置,让它延后一点。
图 11 所示的是进入新游戏时的渐入渐出效果。
图 12 所示的是角色死亡时返回主界面的渐入渐出效果。