自定义TimeLine

自定义TimeLine

什么是TimeLine

在 Unity 中,TimeLine(时间轴)是一种用于创建和管理动画序列的工具。它是 Unity 的一个可视化编辑器窗口,用于创建复杂的、时间驱动的动画、剧情和交互式体验。
Timeline 提供了一系列功能和资源,例如轨道(Track)、片段(Clip)、混合器(Mixer),数据(Data)等,用于组织和控制动画序列。你可以在 Timeline 上创建不同类型的轨道,如动画轨道、音频轨道、事件轨道等,然后将相应的片段添加到轨道上,并在时间轴上安排它们的播放顺序和属性变化。简单的可以理解为timeline就是这四个基本组成的。
了解了上述关于TimeLine的基本介绍之后就到了本篇的重点了,如下。我们只要实现这四个部分就是能自定以TImeLine了。

  • Data : 数据

  • Clip : 片段(放在轨道上的一段动画数据或片段)

  • Mixer:混合(将两个片段按照一定的规则进行融合)

  • Track :轨道(clip和Mixer的载体负责管理和组织)

Data(数据)

继承PlayableBehaviour

在这个类中一般我们只放数据,需要注意的是,这个类中存放的仅仅只是一个模板,真正的数据会在Clip中创建。

csharp 复制代码
using UnityEngine.Playables;

public class DataBehaviour : PlayableBehaviour
{
    public Transform exampleValue;
}

Clip(片段)

继承PlayableAsset 并实现ITimelineClipAsset。

注意:我们上面说了data中的是模板而Clip中才是我么珍重要用到的数据。下面的代码有点不好理解。现在把我们的Timeline比作一场演出,Data是存在Clip中的一些变量,我们把Clip当作一个剧本,但是我们要的是一场演出,光有剧本显然是不行的,我们需要把我们的剧本装换位我们想要的演出这个转换就是CreatePlayable。

csharp 复制代码
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;

public class TextDataClip : PlayableAsset,ITimelineClipAsset
{
    private DataBehaviour template;
   
    // 是否需要混合 Clip.None 不需要混合,blending 需要融合
    public ClipCaps clipCaps => ClipCaps.Blending;
    //需要把你想要展示的数据暴露出来,不然无法进行引用。
    public ExposedReference<Transform> exampleValue;
    // 在这个脚本中 需要理解为什么我们已经有了clip还需要 playable
    // 因为clip相当于戏的剧本而我们给观众是戏不是剧本,这个时候据需要Create 创建一个playable 作为戏来来演出。
    // graph 一个可播放图用于管理播放的行为。owner 表示拥有这个可播放对象的游戏对象。
    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    {
        // 我们需要一个playable 所以用工厂模式创建一个,graph代表我们是给谁创建,template 是我们的data实例表示把这个template创建为playable,但是我们知道这个Template是一个模板里面是没有数据的所以有了下一步
        var playable = ScriptPlayable<DataBehaviour>.Create(graph, template);
        // 我们需要从这个playable上面把clone的data取出来
        DataBehaviour clone = playable.GetBehaviour();
        // 因为mono behaviour 可以引用 mono behaviour 也可以引用 assets 但是反过来  assets 不能随意引用monobehaviour 但是可以通过反过来引用那个引用了assets的monobehaviour来引用其他的monobehaviour。
        // 之后在进行赋值
		clone.exampleValue = exampleValue.Resolve(graph.GetResolover());
        return playable;
    }
}

Track(轨道)

用于组织动画和音频剪辑的容器

继承 TrackAsset 并加上特性。

csharp 复制代码
[TrackColor(0/255f,255/255f,255/255f)] // 轨道的颜色
[TrackBindingType(typeof(GameObject))] // 要绑定的物品的类型是什么,需要给什么物体播放Timeline,可以是一个物体,也可以是一个脚本,或者是一个Aanimator等等
[TrackClipType(typeof(TextDataClip))] // 可以放到这个轨道上的clip是什么类型
csharp 复制代码
using UnityEngine.Timeline;

[TrackColor(0/255f,255/255f,255/255f)]
[TrackBindingType(typeof(Transform))]
[TrackClipType(typeof(DataClip))]
public class TextTrack : TrackAsset
{
	public override Playable CreateTrackMixer(PlayableGraph graph,GameObject go,int inputCount)
    {
       // var mixerPlayable = ScriptPlayable<CustomMixer>.Create(graph);//这个是被CustomMixer驱动的Playable,mixerPlayable.GetBehaviour() as CustomMixer;就可以获得CustomMixer了
        //mixerPlayable.SetInputCount(inputCount);
        //return mixerPlayable;
        //返回mixer
        return ScriptPlayable<CustomMixer>.Create(graph,inputCount);
    }
}

Mixer(混合)

Mixer会铺满整条轨道,他并不会知道现在在播放哪一个clip,他会询问在他上面的每一个clip的权重,当播放到某一个clip的时候这个clip的权重就会变成1但是当两个混合的时候 权重的大小就会变成一条斜线

csharp 复制代码
public class CustomMixer:PlayableBehaviour
{
    public override void OnPlayableCreate(Playable playable)
    {
        ...
    }
    public override void OnPlayableDestroy(Playable playable)
    {
        ...
    }

    public override void PrepareFrame(Playable playable, FrameData info)
    {
        ...
    }
    // 相当于update 会一直更新的
    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        //得到绑定的东西(就是你需要修改的东西)
        Transform transform =  playerData as Transform;
        
        for(int i = 0 ; i < playable.GetInputCount(); i++)//获取轨道上所有的片段
        {
            float weight  = playable.GetInputWeight(i);//获取片段在当前帧的片段的权重
            var clipPlayable = (ScriptPlayable<CustomPlayableBehaviour>)playable.GetInput(i);// 获取当前的 
            CustomPlayableBehaviour behaviour = clipPlayable.GetBehaviour();//获取CustomPlayableBehaviour
            ...//接下来你可以根据Clip的权重写相应的逻辑(如果你没有在ClipCaps里设置blend的话,应该只有一个片段的权重是1,其他为0)
        }
    }

    //上面4个虚方法是最常用的,OnBehaviourPause不建议使用,不太好掌控(会因为各种原因暂停)。直接根据time值得变化判断是否暂停也挺好得
}

这里自定义TimeiLine就完成了,后面会做一个例子的。

相关推荐
牙膏上的小苏打23331 小时前
Unity Surround开关后导致获取主显示器分辨率错误
unity·主屏幕
Unity大海3 小时前
诠视科技Unity SDK开发环境配置、项目设置、apk打包。
科技·unity·游戏引擎
浅陌sss9 小时前
Unity中 粒子系统使用整理(一)
unity·游戏引擎
维度攻城狮13 小时前
实现在Unity3D中仿真汽车,而且还能使用ros2控制
python·unity·docker·汽车·ros2·rviz2
为你写首诗ge16 小时前
【Unity网络编程知识】FTP学习
网络·unity
神码编程18 小时前
【Unity】 HTFramework框架(六十四)SaveDataRuntime运行时保存组件参数、预制体
unity·编辑器·游戏引擎
菲fay20 小时前
Unity 单例模式写法
unity·单例模式
火一线21 小时前
【Framework-Client系列】UIGenerate介绍
游戏·unity
ZKY_241 天前
【工具】Json在线解析工具
unity·json
ZKY_241 天前
【Unity】处理文字显示不全的问题
unity·游戏引擎