Timeline中,可以通过脚本扩展自定义的剪辑,轨道,混合轨道,Inspector属性显示器。
我这里参考了官方的 Default Playables的一个节点扩展方式,它也提供了一个辅助工具,非常方便,基本上我们只管处理轨道、混合轨道处理的逻辑就好了,其他的只需要鼠标点点点就可以创建好你想要的效果。
当然,如果辅助工具某些功能不满足你想要的,你也可以自己编辑脚本来扩展。
那下面我们就用这个辅助工具来创建自定义内容吧。
工具面板首先打开辅助工具的向导面板
首先是我们的剪辑名字
如:TestingTRS_Scale
那么工具会帮助我们自动创建以下几个类:
- 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,的额外两种。
从代码中可以看出来:
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 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 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
}
ClipCaps的枚举简介
- All 就是开始所有内置的剪辑功能。
- None 啥都不开启,只有 Clip Timing属性的Start,End,Duration可调整
- Looping 描述说的是,可以对剪辑内的可以循环播放,只要剪辑还处于播放中的话(目前这个没看到有什么用)
- Extrapolation 开启,并显示对剪辑编辑Clip Extrapolation的设置,可以对空白内容的外插模拟数据
- Clip In 开启,并提供可对剪辑的裁剪设置,一般Animation Clip才有用。自定义脚本我决定没啥用。
- SpeedMultiplier 开启,对剪辑的内容加速播放。一般Animation Clip才有用。
- Blending 开启后,可以对空白内容与剪辑内容的混合过渡处理。
轨道的颜色
如果调整为红色,那么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);
}
}
没选 Create Drawer,对应编辑器代码:
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
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?