https://blogs.unity3d.com/cn/2018/09/05/extending-timeline-a-practical-guide/
https://blog.csdn.net/u011643463/article/details/82585846
引言
Timeline已经很常用了,但是项目往往需要自定义timeline来实现一些可选的功能,如自定义景深,如果需要动态直观的的改变,就需要用到自定义timeline。这里是配合postproces v2来做的,unity版本2019.4.4 timeline是v1.2.14
创建两个文件
unity提供了一个模板
直接填就好了很方便
\
设置PlayableAsset
// DofPlayableBehaviour.cs
[System.Serializable]
public class DofPlayableAsset : PlayableAsset
{
public PostProcessProfile VolumeProfile;
public float FocusDistance;
// Factory method that generates a playable based on this asset
public override Playable CreatePlayable(PlayableGraph graph, GameObject go)
{
var playable = ScriptPlayable<DofPlayableBehaviour>.Create(graph);
var dofBehaviour = playable.GetBehaviour();
//dofBehaviour.VolumeProfile = VolumeProfile.Resolve(graph.GetResolver());
dofBehaviour.VolumeProfile = VolumeProfile;
dofBehaviour.Distance = FocusDistance;
return playable;
}
}
设置PlayableBehaivour
这个脚本会挂到对应的Asset上
所以在Asset里去关联就好了
// DofPlayableBehaviour.cs
public class DofPlayableBehaviour : PlayableBehaviour
{
public float Distance;
public PostProcessProfile VolumeProfile;
private DepthOfField m_DepthOfField;
// Called when the owning graph starts playing
public override void OnGraphStart(Playable playable)
{
VolumeProfile.TryGetSettings(out m_DepthOfField);
}
// Called when the owning graph stops playing
public override void OnGraphStop(Playable playable)
{
}
// Called when the state of the playable is set to Play
public override void OnBehaviourPlay(Playable playable, FrameData info)
{
}
// Called when the state of the playable is set to Paused
public override void OnBehaviourPause(Playable playable, FrameData info)
{
}
// Called each frame while the state is set to Play
public override void PrepareFrame(Playable playable, FrameData info)
{
SetFoucusDistance();
}
public void SetFoucusDistance()
{
m_DepthOfField.focusDistance.value = Distance;
Debug.Log($"SetFoucusDistance {Distance}");
}
}
- 然后添加playabletrack
- 右键添加asset,或者直接拖拽
接下来是混合
要用到4个代码 (可见 不混合的方式还是比较简单的😉)
这里我们把 volume给整合起来,不然每次都要拖拽到clip上
[TrackClipType(typeof(DofPlayableAsset))]
[TrackBindingType(typeof(PostProcessProfile))] // 指定暴露的参数 如上图
public class DofTrack : TrackAsset
{
public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
{
return ScriptPlayable<DofPlayableMixerBehaviour>.Create(graph, inputCount);
}
}
[System.Serializable]
public class DofPlayableAsset : PlayableAsset
{
[Range(0, 8)]
public float FocusDistance;
// Factory method that generates a playable based on this asset
public override Playable CreatePlayable(PlayableGraph graph, GameObject go)
{
var playable = ScriptPlayable<DofPlayableBehaviour>.Create(graph);
var dofBehaviour = playable.GetBehaviour();
dofBehaviour.Distance = FocusDistance;
return playable;
}
}
public class DofPlayableBehaviour : PlayableBehaviour
{
public float Distance;
}
public class DofPlayableMixerBehaviour : PlayableBehaviour
{
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{
var profile = playerData as PostProcessProfile;
DepthOfField dof;
profile.TryGetSettings<DepthOfField>(out dof);
float finalDistance = 0f;
if (!dof)
return;
int inputCount = playable.GetInputCount(); //get the number of all clips on this track
//Debug.Log("======= mix");
for (int i = 0; i < inputCount; i++)
{
float inputWeight = playable.GetInputWeight(i);
ScriptPlayable<DofPlayableBehaviour> inputPlayable = (ScriptPlayable<DofPlayableBehaviour>)playable.GetInput(i);
DofPlayableBehaviour input = inputPlayable.GetBehaviour();
// Use the above variables to process each frame of this playable.
finalDistance += input.Distance * inputWeight;
}
//assign the result to the bound object
dof.focusDistance.value = finalDistance;
}
}