链接:https://blog.csdn.net/beihuanlihe130/article/details/79233320
Timeline是Unity2017版本中新加入的功能,可以非常方便的进行场景动画的创建和修改,包括物体、声音、粒子、动画、特效、自定义Playable以及子Timeline等多种资源进行整合,从而能够较方便的生成效果很棒的场景动画,同时可以通过Unity的Recorder资源包录制较为完整的视频并导出。
1.Timeline界面简单介绍
在Unity2017中,点击Window->Timeline即可调出Timeline面板。如下图所示:
- Activation Track(控制物体的显示和隐藏)
- Animation Track(为物体加入动画,可以在场景中方便地录制动画,也可以是已经制作好的Animation Clip)
- Audio Track(为动画添加音效,并可对音效进行简单的裁剪和操作)
- Control Track(在该轨道上可以添加粒子效果,同时也可以添加子Timeline进行嵌套)
- Playable Track(在该轨道中用户可以添加自定义的播放功能)
- Track Group(将不同的轨道进行分类,相当于文件夹功能)
当我们创建了TimeLine后,会在指定位置生成TimeLine的文件*.playable,当选中该文件后,会在Inspector面板中看到其相应的属性,如下图所示:
2.Timeline轨道简单介绍
@H_404_52@2.1 Activation Track该轨道首先需要为其赋值一个GameObject,表示该轨道控制该物体的显示与隐藏,当在Timeline播放过程中,如果处于片段内部,则该物体显示,否则该物体隐藏。
当我们点击该轨道时,会在Inspector面板中看到可以设置的属性,如下所示:
- Active(当Timeline播放结束时,将该物体激活,设置为显示状态)
- Inactive(当Timeline播放结束时,该物体取消激活,设置为隐藏状态)
- Revert(当Timeline播放结束时,该物体还原Timeline在第1帧时的激活状态)
- Leave As Is(当Timeline播放结束时,该物体保持在Timeline最后一帧的激活状态)
Animation Track主要控制动画的播放,包括动画片段、帧动画等。当我们点击Animation Track时,可以设置其属性,如下图所示:
- Apply Avatar Mask(启用“阿凡达遮罩”,当启用后将根据选择的遮罩应用在整个轨道中)
- Avatar Mask(选择需要的遮罩,并将其应用在当前Animation轨道中)
最终效果如下: - Apply Track Offsets(启用轨道偏移效果,将所有动画的起始位置都设置为指定的偏移角度和位置上,与动画片段中的Clip Root Motion Offsets功能类似)
- Clip Offset Match Fields(该选项可以设置不同动画之间偏移可匹配的变换)
1.添加Animation Clip
右击Animation Clip的空白处,选择Add From Animation Clip即可从已有的动画片段中选择。
可以拖拽动画片段调整播放的时间,同时也可以将多个动画片段进行叠加来完成动画过渡效果。
2.录制动画
可以在Animation Clip中点击红色按钮进行录制,通过设置不同的属性来为物体设置关键帧,从而完成不同类型的动画制作。
3.设置曲线
录制的动画可以在动画窗口中打开,在动画窗口中可以通过关键帧点的方式进行控制,也可以通过曲线的方式进行控制。
2.4 Control Track
Control Track主要控制与时间有关的元素,如粒子效果、嵌套子Timeline等。
该轨道可以在指定的父物体下实例化一个Prefab,并对该Prefab中与时间有关的元素进行播放操作。
Playable Track允许用户自定义相关动画效果,在Default Playables资源包中包含了一部分自定义的功能轨道,包括文字、时间、灯光、位置、寻路、淡入淡出等效果,用户也可以根据自己的需要进行定制化开发,以实现更加复杂的效果。
用户可以在代码中继承PlayableBehavIoUr和PlayableAsset两个类,在其中完成自定义的动画功能。
/// <summary>
///该类主要实现在TimeLine的PlayableTrack中显示我们定义的功能,并完成赋值
/// </summary>
public class PlayableBehavIoUrSample : PlayableAsset
{
//使用ExposedReference进行赋值操作
public ExposedReference<GameObject> ShowNumberText;
private Text text;
public int startNum;
public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
{
var scriptPlayable = ScriptPlayable<PlayableTest>.Create(graph);
//从ExposedReference中获取我们需要的控件
text = ShowNumberText.Resolve(graph.GetResolver()).GetComponent<Text>();
//对指定的PlayableBehavIoUr中的属性进行赋值
scriptPlayable.GetBehavIoUr().ShowNumberText = text;
scriptPlayable.GetBehavIoUr().StartNum = startNum;
return scriptPlayable;
}
}
/// <summary>
/// 读秒功能
/// </summary>
public class PlayableTest : PlayableBehavIoUr
{
//显示文字的控件
public Text ShowNumberText;
public int StartNum;
float time;
int currentNum;
/// <summary>
/// 当该PlayableBehavIoUr的PlayableGraph启动时调用
/// </summary>
/// <param name="playable"></param>
public override void OnGraphStart(Playable playable)
{
base.OnGraphStart(playable);
Debug.Log("OnGraphStart Called");
currentNum = StartNum;
ShowNumberText.text = "Start Number Is " + StartNum;
Debug.Log(ShowNumberText.text);
}
/// <summary>
/// 当该PlayableBehavIoUr的PlayState转换为PlayState.Play时调用
/// </summary>
/// <param name="playable"></param>
/// <param name="info"></param>
public override void OnBehavIoUrPlay(Playable playable, FrameData info)
{
base.OnBehavIoUrPlay(playable, info);
Debug.Log("OnBehavIoUrPlay Called");
}
/// <summary>
/// 该函数与ProcessFrame函数功能相同,都是在该PlayableBehavIoUr播放的每一帧中调用,相当于Update函数的功能
/// </summary>
/// <param name="playable"></param>
/// <param name="info"></param>
public override void PrepareFrame(Playable playable, FrameData info)
{
base.PrepareFrame(playable, info);
Debug.Log("PrepareFrame Called");
time += Time.deltaTime;
if (time > 1.0f)
{
currentNum++;
ShowNumberText.text = "Current Number Is " + currentNum;
Debug.Log(ShowNumberText.text);
time -= 1.0f;
}
}
/// <summary>
/// 该函数与PrepareFrame函数功能相同,都是在该PlayableBehavIoUr播放的每一帧中调用,相当于Update函数的功能
/// </summary>
/// <param name="playable"></param>
/// <param name="info"></param>
/// <param name="playerData"></param>
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{
base.ProcessFrame(playable, info, playerData);
Debug.Log("ProcessFrame Called");
}
/// <summary>
/// 该函数在PlayableBehavIoUr片段的PlayState转换为Delay时调用
/// </summary>
/// <param name="playable"></param>
/// <param name="info"></param>
public override void OnBehavIoUrDelay(Playable playable, FrameData info)
{
base.OnBehavIoUrDelay(playable, info);
Debug.Log("OnBehavIoUrDelay Called");
}
/// <summary>
/// 该函数在PlayableBehavIoUr片段的PlayState转换为Pause时调用
/// </summary>
/// <param name="playable"></param>
/// <param name="info"></param>
public override void OnBehavIoUrPause(Playable playable, FrameData info)
{
base.OnBehavIoUrPause(playable, info);
Debug.Log("OnBehavIoUrPause Called");
ShowNumberText.text = "End Number Is " + currentNum;
Debug.Log(ShowNumberText.text);
}
/// <summary>
/// 该函数在PlayableBehavIoUr片段停止播放时调用
/// </summary>
/// <param name="playable"></param>
public override void OnGraphStop(Playable playable)
{
base.OnGraphStop(playable);
Debug.Log("OnGraphStop Called");
}
/// <summary>
/// 该函数在PlayableBehavIoUr片段创建时调用
/// </summary>
/// <param name="playable"></param>
public override void OnPlayableCreate(Playable playable)
{
base.OnPlayableCreate(playable);
Debug.Log("OnPlayableCreate Called");
}
/// <summary>
/// 该函数在PlayableBehavIoUr片段销毁时调用
/// </summary>
/// <param name="playable"></param>
public override void OnPlayableDestroy(Playable playable)
{
base.OnPlayableDestroy(playable);
Debug.Log("OnPlayableDestroy Called");
}
/// <summary>
/// 该函数在PlayableGraph的PrepareData阶段被调用
/// </summary>
/// <param name="playable"></param>
/// <param name="info"></param>
public override void PrepareData(Playable playable, FrameData info)
{
base.PrepareData(playable, info);
Debug.Log("PrepareData Called");
}
}
以下为运行后的调用顺序
以下为该Timeline设置的状态,主要部分为PlayableTrack。
最终运行效果如下:
该方法也可通过继承BasicPlayableBehavIoUr类完成,但是在未来的版本中该类可能会被PlayableBehavIoUr和PlayableAsset类取代(已经弃用)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。