ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Unity Timeline自定义轨道 DefaultPlayables源码剖析

2021-12-11 09:58:57  阅读:586  来源: 互联网

标签:TrackBinding 自定义 inputWeight Timeline float 剪辑 源码 Playable public


DefaultPlayables源码

DefaultPlayables在Unity原生的轨道支持下额外提供了7种轨道。

  • LightControl
  • NavMeshAgentControl
  • ScreenFader
  • Video
  • TransformTween
  • TimeDilation
  • TextSwitcher

我们以LightControl为例,主要有以下4个脚本:

LightControlBehaviour、LightControlClip、LightControlMixerBehaviour、LightControlTrack

Editor下的绘制有一个脚本:

LightControlDrawer

结合我之前的文章:

Unity Timeline自定义轨道_漫漫无期的博客-CSDN博客

Timeline上的轨道由LightControlTrack进行管理。

在进行混合时创建出LightControlMixerBehaviour,Editor下获取绑定物体的灯光属性基础信息。

[TrackColor(0.9454092f, 0.9779412f, 0.3883002f)]
[TrackClipType(typeof(LightControlClip))]
[TrackBindingType(typeof(Light))]
public class LightControlTrack : TrackAsset
{
    public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
    {
        return ScriptPlayable<LightControlMixerBehaviour>.Create (graph, inputCount);
    }

    public override void GatherProperties(PlayableDirector director, IPropertyCollector driver)
    {
#if UNITY_EDITOR
       Light trackBinding = director.GetGenericBinding(this) as Light;
       if (trackBinding == null)
           return;
       driver.AddFromName<Light>(trackBinding.gameObject, "m_Color");
       driver.AddFromName<Light>(trackBinding.gameObject, "m_Intensity");
       driver.AddFromName<Light>(trackBinding.gameObject, "m_Range");
       driver.AddFromName<Light>(trackBinding.gameObject, "m_BounceIntensity");
#endif
        base.GatherProperties(director, driver);
    }
}

LightControlMixerBehaviour 完成具体行为上的控制,可以看到,它首先在第一帧时记录下默认的灯光属性,然后通过playable.GetInput系列方法获取输入的各个Input并由他们的权重进行混合计算,得出结果后再赋值给绑定的物体Light m_TrackBinding。

最后在OnPlayableDestroy 还原其基本灯光属性。

public class LightControlMixerBehaviour : PlayableBehaviour
{
    Color m_DefaultColor;
    float m_DefaultIntensity;
    float m_DefaultBounceIntensity;
    float m_DefaultRange;

    Light m_TrackBinding;
    bool m_FirstFrameHappened;

    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        m_TrackBinding = playerData as Light;

        if (m_TrackBinding == null)
            return;

        if (!m_FirstFrameHappened)
        {
            m_DefaultColor = m_TrackBinding.color;
            m_DefaultIntensity = m_TrackBinding.intensity;
            m_DefaultBounceIntensity = m_TrackBinding.bounceIntensity;
            m_DefaultRange = m_TrackBinding.range;
            m_FirstFrameHappened = true;
        }

        int inputCount = playable.GetInputCount ();

        Color blendedColor = Color.clear;
        float blendedIntensity = 0f;
        float blendedBounceIntensity = 0f;
        float blendedRange = 0f;
        float totalWeight = 0f;
        float greatestWeight = 0f;
        int currentInputs = 0;

        for (int i = 0; i < inputCount; i++)
        {
            float inputWeight = playable.GetInputWeight(i);
            ScriptPlayable<LightControlBehaviour> inputPlayable = (ScriptPlayable<LightControlBehaviour>)playable.GetInput(i);
            LightControlBehaviour input = inputPlayable.GetBehaviour ();
            
            blendedColor += input.color * inputWeight;
            blendedIntensity += input.intensity * inputWeight;
            blendedBounceIntensity += input.bounceIntensity * inputWeight;
            blendedRange += input.range * inputWeight;
            totalWeight += inputWeight;

            if (inputWeight > greatestWeight)
            {
                greatestWeight = inputWeight;
            }

            if (!Mathf.Approximately (inputWeight, 0f))
                currentInputs++;
        }

        m_TrackBinding.color = blendedColor + m_DefaultColor * (1f - totalWeight);
        m_TrackBinding.intensity = blendedIntensity + m_DefaultIntensity * (1f - totalWeight);
        m_TrackBinding.bounceIntensity = blendedBounceIntensity + m_DefaultBounceIntensity * (1f - totalWeight);
        m_TrackBinding.range = blendedRange + m_DefaultRange * (1f - totalWeight);
    }

    public override void OnPlayableDestroy (Playable playable)
    {
        m_FirstFrameHappened = false;

        if(m_TrackBinding == null)
            return;

        m_TrackBinding.color = m_DefaultColor;
        m_TrackBinding.intensity = m_DefaultIntensity;
        m_TrackBinding.bounceIntensity = m_DefaultBounceIntensity;
        m_TrackBinding.range = m_DefaultRange;
    }
}

LightControlClip、LightControlBehaviour 数据来源。在LightControlClip的CreatePlayable方法中完成将template数据传递过去的责任。

[Serializable]
public class LightControlClip : PlayableAsset, ITimelineClipAsset
{
    public LightControlBehaviour template = new LightControlBehaviour ();

    public ClipCaps clipCaps
    {
        get { return ClipCaps.Blending; }
    }

    public override Playable CreatePlayable (PlayableGraph graph, GameObject owner)
    {
        var playable = ScriptPlayable<LightControlBehaviour>.Create (graph, template);
        return playable;    }
}
[Serializable]
public class LightControlBehaviour : PlayableBehaviour
{
    public Color color = Color.white;
    public float intensity = 1f;
    public float bounceIntensity = 1f;
    public float range = 10f;
}

LightControlDrawer负责Editor下的检视面板的自定义绘制。

[CustomPropertyDrawer(typeof(LightControlBehaviour))]
public class LightControlDrawer : PropertyDrawer
{
    public override float GetPropertyHeight (SerializedProperty property, GUIContent label)
    {
        int fieldCount = 4;
        return fieldCount * EditorGUIUtility.singleLineHeight;
    }

    public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
    {
        SerializedProperty colorProp = property.FindPropertyRelative("color");
        SerializedProperty intensityProp = property.FindPropertyRelative("intensity");
        SerializedProperty bounceIntensityProp = property.FindPropertyRelative("bounceIntensity");
        SerializedProperty rangeProp = property.FindPropertyRelative("range");

        Rect singleFieldRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
        EditorGUI.PropertyField(singleFieldRect, colorProp);
        
        singleFieldRect.y += EditorGUIUtility.singleLineHeight;
        EditorGUI.PropertyField(singleFieldRect, intensityProp);
        
        singleFieldRect.y += EditorGUIUtility.singleLineHeight;
        EditorGUI.PropertyField(singleFieldRect, bounceIntensityProp);
        
        singleFieldRect.y += EditorGUIUtility.singleLineHeight;
        EditorGUI.PropertyField(singleFieldRect, rangeProp);
    }
}

其他6种轨道结构也与此类似,不一一展开。

Default Playables辅助工具

可以看下这篇文章更详细的介绍:

Unity - Timeline 自定义剪辑,轨道,混合轨道,Inspector属性显示(使用Default Playables辅助工具)_Jave.Lin 的学习笔记-CSDN博客

打开辅助工具的向导面板。

Playable Name

首先是我们的剪辑名字。如:TestScale。

那么工具会帮助我们自动创建以下几个类:

XXXXBehaviour : PlayableBehaviour - 普通剪辑逻辑要处理的内容,逻辑也可以写到混合剪辑逻辑。
XXXXClip : PlayableAsset, ITimelineClipAsset - 剪辑资源要保存的数据内容。
XXXXMixerBehaviour : PlayableBehaviour - 混合剪辑逻辑要处理的内容,对混合数据的收集,或是处理,其实也可以只在这里收集数据,然后传到 普通剪辑逻辑 里处理混合也是可以的。
XXXXTrack : TrackAsset - 轨道资源要处理的内容,主要让轨道在处理混合时,应该用哪些逻辑类来处理混合。
XXXXDrawer : PropertyDraw - 剪辑属性绘制器,主要处理在Timeline 的 Clips view中选中的剪辑,然后在Inspector窗口中显示的绘制内容。

Standard Blend Playable

是否创建标准的可混合的Playable。
选没选中,区别在于:

选中,Track Binding Type 可以选择: 可实例化,并继承自 UnityEngine.Component 的所有类。
没选,Track Binding Type 可以选择:继承自 UnityEngine.Component 的所有类外,还可以选中GameObject,与null,的额外两种。

Track Binding Type

就是Track接受处理的数据对象是什么类型的。


Exposed References

因为Timeline中的变量不能直接暴露应用的类型变量。
所以专门独立出来一项,添加引用类型的变量,以与值类型的分开。
如果Standard Blend Playable选中的话,Exposed References不显示,就是不提供设置。
点击’Add按钮’,出现新的一个变量栏,然后你可以对变量默认的名字:newBehaviourVariable,重命名成你想要的,右边还有变量的类型选择。
点击’Remove按钮’,可删除对应的变量。


Behaviour Variables

行为逻辑类的变量。

如果Standard Blend Playable选中的话,就叫:Standard Blend Playable Properties,叫法不一致而已。
点击’Add按钮’,出现新的一个变量栏,然后你可以对变量默认的名字:newBehaviourVariable,重命名成你想要的,右边还有变量的类型选择。
点击’Remove按钮’,可删除对应的变量。


Clip Caps

可理解为:剪辑的内置功能开始选项。

开启的功能,在Inspector中会显示一些该剪辑通用的属性项。

再脚本中定义如下:

public enum ClipCaps
{
	All = -1,
	None = 0,
	Looping = 1,
	Extrapolation = 2,
	ClipIn = 4,
	SpeedMultiplier = 8,
	Blending = 16
}

ClipCaps的枚举简介

  • All 就是开始所有内置的剪辑功能。
  • None 啥都不开启,只有 Clip Timing属性的Start,End,Duration可调整。
  • Looping 可以对剪辑内的可以循环播放,只要剪辑还处于播放中的话。
  • Extrapolation 开启,并显示对剪辑编辑Clip Extrapolation的设置,可以对空白内容的外插模拟数据。
  • Clip In 开启,并提供可对剪辑的裁剪设置,一般Animation Clip才有用。
  • SpeedMultiplier 开启,对剪辑的内容加速播放。一般Animation Clip才有用。
  • Blending 开启后,可以对空白内容与剪辑内容的混合过渡处理。

Track Color

轨道的颜色。

Create Drawer

是否创建剪辑的Inspector属性绘制器。

标签:TrackBinding,自定义,inputWeight,Timeline,float,剪辑,源码,Playable,public
来源: https://blog.csdn.net/dmk17771552304/article/details/121764437

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有