【Unity博客节选】Timeline 的 Traversal mode参数

注:软件版本Unity 6.0 + Timeline 1.8.7

作者:CSDN @ RingleaderWang
原文:《Unity第25期——Timeline结构及其源码浅析》
文章首发Github👍《Timeline结构及其源码浅析》

Bilibili 视频版👍👍《Timeline结构及其源码解析》https://www.bilibili.com/video/BV1bHjYzNE35

TraversalModeMix/Passthrough,表示遍历节点input的方式,Mix就是将各输入进行加权;passthrough就是匹配input与output,第几个output来请求数据,就从第几个input获取数据。Passthrough目前只用于TimelinePlayable,使之成为graph的统一入口

⭐Traversal mode 验证

对Traversal mode这个参数的理解非常重要,不明白它的话,你会误以为每个PlayableOutput都会接收所有叶子节点的数据。

我们来创建个graph案例:

[Tooltip("false则mode是passthrough,true则mode是mix")]  
public bool changeTraversalMode = false;  
[Tooltip("false则PlayableOutput的source为playable1,true则为playable2")]  
public bool changeSourcePlayable = false;

//newInput system绑定空格键触发
public void BackspaceDown(InputAction.CallbackContext ctx)  
{  
    if (ctx.performed)  
    {   
        ValidateTraversalMode2(changeTraversalMode,changeSourcePlayable);  
    }
}

private void ValidateTraversalMode2(bool _changeTraversalMode,bool _changeSourcePlayable)  
{  
    DestoryGraph(graph);  
    graph = PlayableGraph.Create();  
    var playable1 = Playable.Create(graph,1);  
    var playable2 = Playable.Create(graph,2);  
    var playable3 = Playable.Create(graph);  
    playable3.SetTraversalMode(!_changeTraversalMode?PlayableTraversalMode.Passthrough:PlayableTraversalMode.Mix);  
    var playable4 = Playable.Create(graph,4);  
    var playable5 = Playable.Create(graph,5);  
	playable3.SetInputCount(10);  
    playable3.SetOutputCount(10);  
    graph.Connect(playable3, 0, playable1, 0);  
    graph.Connect(playable3, 1, playable2, 0);  
    graph.Connect(playable4, 0, playable3, 0);  
    graph.Connect(playable5, 0, playable3, 1);  
    ScriptPlayableOutput output = ScriptPlayableOutput.Create(graph, "customOutput");  
    output.SetSourcePlayable(!_changeSourcePlayable?playable1:playable2,100);
    graph.Play();  
}

当前中间Playable的 traversalMode是passthrough,可以看到只有port 0 这条线有数据传输。

mode为passthrough数据流向

改变PlayableOutput连在port 1 这端,数据又只接受input 1 这个port输入了。

mode为passthrough的数据流向(改变sourcePlayable)

而当 MODE 设为 MIX ,input 0 和 input 1 都接收数据。

MODE=MIX的数据流向

通过这个例子,能大概理解 TraversalMode 遍历模式到底是什么意思。

不过要注意,按照Passthrough源码注释的本意:

应该是sourceOutputPortPlayableOutput跟对应input位置的节点进行直通,但实测sourceOutputPort没起作用,实际上是由PlayableOutput在graph中的顺序决定,也就是下图中PlayableOutput前面的#0 #1 #2 标号(其实就是PlayableOutput数组的index)。

passthrough mode下input port匹配的其实是PlayableOutput数组标号

测试代码你可以发现SetSourcePlayable的port你设50设100都不影响。

void ValidateTraversalMode()  
{  
    DestoryGraph(graph);  
    graph = PlayableGraph.Create("TraversalModeGraph");  
    ScriptPlayableOutput output = ScriptPlayableOutput.Create(graph, "customOutput");  
    ScriptPlayableOutput output2 = ScriptPlayableOutput.Create(graph, "customOutput2");  
    ScriptPlayableOutput output3 = ScriptPlayableOutput.Create(graph, "customOutput3");  
    var playable = ScriptPlayable<CustomClipBehaviour>.Create(graph);  
    var playable2 = ScriptPlayable<CustomClipBehaviour>.Create(graph);  
    var playable3 = ScriptPlayable<CustomClipBehaviour>.Create(graph);  
    var playable4 = ScriptPlayable<CustomClipBehaviour>.Create(graph);  
    var playable5 = ScriptPlayable<CustomClipBehaviour>.Create(graph);  
    var mixer = ScriptPlayable<CustomMixerBehaviour>.Create(graph);  
    mixer.SetTraversalMode(PlayableTraversalMode.Passthrough);//默认mode为mix,这里改为passthrough  
    mixer.SetInputCount(10);// 很重要,否则连接报错:Connecting invalid input  
    mixer.ConnectInput(4,playable,0,1);  
    mixer.ConnectInput(6,playable2,0,1);  
    mixer.ConnectInput(2,playable3,0,1);  
    mixer.ConnectInput(8,playable4,0,1);  
    mixer.ConnectInput(1,playable5,0,1);  
    output.SetSourcePlayable(mixer,30);// 这个SetSourcePlayable的port根本没用,完全根据PlayableOutput顺序获取的  
    output2.SetSourcePlayable(mixer,50);  
    output3.SetSourcePlayable(mixer,100);  
    graph.Play();  
}

但从Animation计算权重的过程也能看出,SourceOutputPort本意就是playable的output port。但实测中Playableout获取数据时并没有使用这个参数,更没有校验,你设多少都可以(只校验了不能重复绑定,但没校验port是否存在)。

如果是bug的话,官方可能需要做下面两个步骤进行修复:

  • 每connect一个节点到TimelinePlayable,TimelinePlayable的outputCount加一(这样直通才有意义)
  • 对每个Playableout从根节点TimelinePlayable开始遍历时,严格按照TimelinePlayable.getInput(PlayableOutput.GetSourceOutputport())获取绑定的Playable,而不是用PlaybleGraph中类似PlayableOytput[]数组的index来get input playable。(注:Timeline生成的graph中PlayableOutput.GetSourcePlayable()得到的就是TimelinePlayable
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值