赞
踩
Timeline中,可以通过脚本扩展自定义的剪辑,轨道,混合轨道,Inspector属性显示器。
我这里参考了官方的 Default Playables的一个节点扩展方式,它也提供了一个辅助工具,非常方便,基本上我们只管处理轨道、混合轨道处理的逻辑就好了,其他的只需要鼠标点点点就可以创建好你想要的效果。
当然,如果辅助工具某些功能不满足你想要的,你也可以自己编辑脚本来扩展。
那下面我们就用这个辅助工具来创建自定义内容吧。
首先打开辅助工具的向导面板
首先是我们的剪辑名字
如:TestingTRS_Scale
那么工具会帮助我们自动创建以下几个类:
这些类虽然是工具帮我们生成的。
但是我们也是可以自己手写的,只是用工具会更快而已,不用写太多的代码。
是否创建标准的可混合的Playable
选没选中,区别在于:
UnityEngine.Component
的所有类。UnityEngine.Component
的所有类外,还可以选中GameObject,与null,的额外两种。从代码中可以看出来:
if (isStandardBlendPlayable) // 选中 Standard Blend Playable { oldIndex = m_ComponentBindingTypeIndex; m_ComponentBindingTypeIndex = EditorGUILayout.Popup (m_TrackBindingTypeContent, m_ComponentBindingTypeIndex, UsableType.GetGUIContentWithSortingArray (s_ComponentTypes)); // 使用的是集合:s_ComponentTypes trackBinding = s_ComponentTypes[m_ComponentBindingTypeIndex]; EditorGUILayout.Space (); defaultValuesComponent = EditorGUILayout.ObjectField (m_DefaultValuesComponentContent, defaultValuesComponent, trackBinding.type, true) as Component; } else // 没选 { m_TrackBindingTypeIndex = EditorGUILayout.Popup(m_TrackBindingTypeContent, m_TrackBindingTypeIndex, UsableType.GetGUIContentWithSortingArray(s_TrackBindingTypes)); // 使用的是集合:s_TrackBindingTypes trackBinding = s_TrackBindingTypes[m_TrackBindingTypeIndex]; }
可以看到分别使用了不一样的TrackBindingType的集合而已,那再去看看这两个集合的收集区别
Type[] componentTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where(t => typeof(Component).IsAssignableFrom(t)).Where (t => t.IsPublic).ToArray(); List<UsableType> componentUsableTypesList = UsableType.GetUsableTypeArray(componentTypes).ToList(); componentUsableTypesList.Sort(); s_ComponentTypes = componentUsableTypesList.ToArray (); // Starndard Blend Playable == true是使用的TrackBindingType的集合 UsableType gameObjectUsableType = new UsableType(typeof(GameObject)); UsableType[] defaultUsableTypes = UsableType.GetUsableTypeArray(componentTypes, gameObjectUsableType); List<UsableType> exposedRefTypeList = defaultUsableTypes.ToList (); exposedRefTypeList.Sort(); s_ExposedReferenceTypes = exposedRefTypeList.ToArray(); UsableType noneType = new UsableType((Type)null); s_TrackBindingTypes = UsableType.AmalgamateUsableTypes(s_ExposedReferenceTypes, noneType); // Starndard Blend Playable == false是使用的TrackBindingType的集合 // 所以我们可以看到,仅仅比s_ComponentTypes ,多了个:GameObject,与null类。
当你选中了 Standard Blend Playable后,你会发现界面精简了很多。
就是Track之接受处理的数据对象是什么类型的
因为Timeline中的变量不能直接暴露应用的类型变量。
所以专门独立出来一项,添加引用类型的变量,以与值类型的分开。
如果Standard Blend Playable选中的话,Exposed References不显示,就是不提供设置。
点击’Add按钮’,出现新的一个变量栏,然后你可以对变量默认的名字:newBehaviourVariable,重命名成你想要的,右边还有变量的类型选择。
点击’Remove按钮’,可删除对应的变量。
行为逻辑类的变量
如果Standard Blend Playable选中的话,就叫:Standard Blend Playable Properties,叫法不一致而已。
点击’Add按钮’,出现新的一个变量栏,然后你可以对变量默认的名字:newBehaviourVariable,重命名成你想要的,右边还有变量的类型选择。
点击’Remove按钮’,可删除对应的变量。
可理解为:剪辑的内置功能开始选项。
开启的功能,在Inspector中会显示一些该剪辑通用的属性项。
再脚本中定义如下:
public enum ClipCaps
{
All = -1,
None = 0,
Looping = 1,
Extrapolation = 2,
ClipIn = 4,
SpeedMultiplier = 8,
Blending = 16
}
轨道的颜色
如果调整为红色,那么Timeline中的轨道左侧红色条,与剪辑下面的红色条,就是Track Color。
是否创建剪辑的Inspector属性绘制器
如下图的红色框中的,就是选中 Create Drawer后的结果。
using UnityEditor; using UnityEngine; [CustomPropertyDrawer(typeof(TestingTRS_ScaleBehaviour))] public class TestingTRS_ScaleDrawer : PropertyDrawer { public override float GetPropertyHeight (SerializedProperty property, GUIContent label) { int fieldCount = 3; return fieldCount * EditorGUIUtility.singleLineHeight; } public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) { SerializedProperty scaleXProp = property.FindPropertyRelative("scaleX"); SerializedProperty scaleYProp = property.FindPropertyRelative("scaleY"); SerializedProperty scaleZProp = property.FindPropertyRelative("scaleZ"); Rect singleFieldRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight); EditorGUI.PropertyField(singleFieldRect, scaleXProp); singleFieldRect.y += EditorGUIUtility.singleLineHeight; EditorGUI.PropertyField(singleFieldRect, scaleYProp); singleFieldRect.y += EditorGUIUtility.singleLineHeight; EditorGUI.PropertyField(singleFieldRect, scaleZProp); } }
using UnityEditor; using UnityEngine; using UnityEngine.Playables; using UnityEngine.UI; [CustomPropertyDrawer(typeof(TestingTRS_ScaleDrawer))] public class TestingTRS_ScaleDrawer : PropertyDrawer { public override float GetPropertyHeight (SerializedProperty property, GUIContent label) { int fieldCount = 0; return fieldCount * EditorGUIUtility.singleLineHeight; } public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) { Rect singleFieldRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight); } }
面板里的基本介绍得差不多了
下面说说,主要扩展混合剪辑的代码
介绍说明我都写注释里吧
主要看:// === add start ===
与// === add end ===
之间的内容,其他都是生成的代码。
using System; using UnityEngine; using UnityEngine.Playables; using UnityEngine.Timeline; public class TestingTRS_ScaleMixerBehaviour : PlayableBehaviour { // === add start === // 一些辅助变量 private bool firstFrae = false; // 是否处理过第一帧的逻辑 private Vector3 srcScale = Vector3.one; // 轨道处理前的原始缩放值 private Transform trackBinding; // 这个就是我嗯Track Binding Type指定的类型变量 // === add end === // NOTE: This function is called at runtime and edit time. Keep that in mind when setting the values of properties. public override void ProcessFrame(Playable playable, FrameData info, object playerData) { trackBinding = playerData as Transform; if (!trackBinding) return; // === add start === if (!firstFrae) // 没有处理过第一帧 { firstFrae = true; // 处理过了,将标识打上 srcScale = trackBinding.localScale; // 记录轨道处理前的数据 } // === add end === int inputCount = playable.GetInputCount (); // === add start === float totalWeight = 0; // 总的混合权重 float blendX = 0; // scaleX的混合值 float blendY = 0; // scaleY的混合值 float blendZ = 0; // scaleZ的混合值 // === add end === for (int i = 0; i < inputCount; i++) { float inputWeight = playable.GetInputWeight(i); ScriptPlayable<TestingTRS_ScaleBehaviour> inputPlayable = (ScriptPlayable<TestingTRS_ScaleBehaviour>)playable.GetInput(i); TestingTRS_ScaleBehaviour input = inputPlayable.GetBehaviour (); // Use the above variables to process each frame of this playable. // === add start === totalWeight += inputWeight; // 累加混合权重 blendX += inputWeight * input.scaleX; // 根据权重值,将每一个剪辑的值都以混合权重值来做插值 blendY += inputWeight * input.scaleY; blendZ += inputWeight * input.scaleZ; // === add end === } // === add start === trackBinding.localScale = new Vector3(blendX, blendY, blendZ); // 将混合后的权重设置到binding数据中 // === add end === } // === add start === public override void OnPlayableDestroy(Playable playable) // 在剪辑销毁时恢复之前的缩放值 { if (trackBinding != null && firstFrae) { firstFrae = false; trackBinding.localScale = srcScale; } } // === add end === }
选中TestTL对象,点击Timeline窗口中的Create按钮
先看看运行效果,很生硬的设置缩放值,后面添加混合会平滑很多
混合的说明我之前翻译过一篇官方手册教程,可以看看:Unity - Timeline 之 Blending clips(混合剪辑)
再运行看看混合效果
using System;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
[Serializable]
public class TestingTRS_ScaleBehaviour : PlayableBehaviour
{
public float scaleX;
public float scaleY;
public float scaleZ;
}
using System; using UnityEngine; using UnityEngine.Playables; using UnityEngine.Timeline; [Serializable] public class TestingTRS_ScaleClip : PlayableAsset, ITimelineClipAsset { public TestingTRS_ScaleBehaviour template = new TestingTRS_ScaleBehaviour (); public ClipCaps clipCaps { get { return ClipCaps.Blending; } } public override Playable CreatePlayable (PlayableGraph graph, GameObject owner) { return ScriptPlayable<TestingTRS_ScaleBehaviour>.Create (graph, template); } }
using System; using UnityEngine; using UnityEngine.Playables; using UnityEngine.Timeline; public class TestingTRS_ScaleMixerBehaviour : PlayableBehaviour { // === add start === // 一些辅助变量 private bool firstFrae = false; // 是否处理过第一帧的逻辑 private Vector3 srcScale = Vector3.one; // 轨道处理前的原始缩放值 private Transform trackBinding; // 这个就是我嗯Track Binding Type指定的类型变量 // === add end === // NOTE: This function is called at runtime and edit time. Keep that in mind when setting the values of properties. public override void ProcessFrame(Playable playable, FrameData info, object playerData) { trackBinding = playerData as Transform; if (!trackBinding) return; // === add start === if (!firstFrae) // 没有处理过第一帧 { firstFrae = true; // 处理过了,将标识打上 srcScale = trackBinding.localScale; // 记录轨道处理前的数据 } // === add end === int inputCount = playable.GetInputCount (); // === add start === float totalWeight = 0; // 总的混合权重 float blendX = 0; // scaleX的混合值 float blendY = 0; // scaleY的混合值 float blendZ = 0; // scaleZ的混合值 // === add end === for (int i = 0; i < inputCount; i++) { float inputWeight = playable.GetInputWeight(i); ScriptPlayable<TestingTRS_ScaleBehaviour> inputPlayable = (ScriptPlayable<TestingTRS_ScaleBehaviour>)playable.GetInput(i); TestingTRS_ScaleBehaviour input = inputPlayable.GetBehaviour (); // Use the above variables to process each frame of this playable. // === add start === totalWeight += inputWeight; // 累加混合权重 blendX += inputWeight * input.scaleX; // 根据权重值,将每一个剪辑的值都以混合权重值来做插值 blendY += inputWeight * input.scaleY; blendZ += inputWeight * input.scaleZ; // === add end === } // === add start === trackBinding.localScale = new Vector3(blendX, blendY, blendZ); // 将混合后的权重设置到binding数据中 // === add end === } // === add start === public override void OnPlayableDestroy(Playable playable) // 在剪辑销毁时恢复之前的缩放值 { if (trackBinding != null && firstFrae) { firstFrae = false; trackBinding.localScale = srcScale; } } // === add end === }
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
[TrackColor(1f, 0f, 0.2057924f)]
[TrackClipType(typeof(TestingTRS_ScaleClip))]
[TrackBindingType(typeof(Transform))]
public class TestingTRS_ScaleTrack : TrackAsset
{
public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
{
return ScriptPlayable<TestingTRS_ScaleMixerBehaviour>.Create (graph, inputCount);
}
}
using UnityEditor; using UnityEngine; [CustomPropertyDrawer(typeof(TestingTRS_ScaleBehaviour))] public class TestingTRS_ScaleDrawer : PropertyDrawer { public override float GetPropertyHeight (SerializedProperty property, GUIContent label) { int fieldCount = 3; return fieldCount * EditorGUIUtility.singleLineHeight; } public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) { SerializedProperty scaleXProp = property.FindPropertyRelative("scaleX"); SerializedProperty scaleYProp = property.FindPropertyRelative("scaleY"); SerializedProperty scaleZProp = property.FindPropertyRelative("scaleZ"); Rect singleFieldRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight); EditorGUI.PropertyField(singleFieldRect, scaleXProp); singleFieldRect.y += EditorGUIUtility.singleLineHeight; EditorGUI.PropertyField(singleFieldRect, scaleYProp); singleFieldRect.y += EditorGUIUtility.singleLineHeight; EditorGUI.PropertyField(singleFieldRect, scaleZProp); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。