(1)
bing PlayableDirector SetReferenceValue
(2)
Unity--如何将Timeline用于网络游戏的剧情系统中
https://blog.csdn.net/qq826364410/article/details/80501824
网络游戏中的角色都是动态生成的,所以如果要结合Timeline编辑剧情,就需要将动态生成的角色放入到“剧本”中。以下提供一个解决方案。
外部触发只需要提供timelineSn用于索引timeline,timelineDataSn用于索引剧情中的数据
TimelineData类用于timeline中的数据保存,通过Scriptable 序列化数据。数据主要分为演员数据和相机数据。
演员数据
-
public struct ActorData
-
{
-
public string actorModelSn;//演员模型
-
public string acotrName;//演员名字,剧情中演员的唯一标识
-
public Vector3 actorPos;//由于演员出生位置、转角
-
public Vector3 actorRotation;
-
}
摄像机数据
-
public struct VCamData
-
{
-
public string vCamPrefabSn;//索引保存非场景数据的prefab
-
public string lookAtPart;//lookAtPart可以瞄准指定演员的指定部位
-
public string followActorOrPostion;//跟随演员名字或出生位置
-
}
- CreateAsset.cs 扩展Editor生成数据空壳。
- TimelineController类负责具体的timeline剧情细节,外部通过它来管理timeline剧情,而无需管具体细节。其最主要的职责之将 剧情数据与剧情相结合,而AssemblyTimeline方法主要执行这项工作。调用的Unity给出的接口有PlayableAsset 的outputs数据,这里获取剧情的binding数据,然后通过binding的sourceObj获取Track的类型,然后根据Track类型分别处理。
binding列表
- 对于AnimationTrack:通过SetGenericBinding来设置动作的执行演员(要求有Animator)
- 对于CinemachineTrack:通过GetClips获取镜头列表,然后通过Director的 SetReferenceValue将场景中的虚拟相机传入Timeline 中
- 对于自定义的PlayableBehaviour,也是通过类似的方法来传数据。但是另外有一点需要注意的是通过GetClips获取的是PlayableAsset对象,我认为他是一个对PlayableBehaviour对象的代理,如何对接两者的具体写法可以参照我自写的ConversationPlayable类。
- ScenarioObjController类用于管理剧情中的演员。
- ScenarioMod类模式类来管理剧情数据,以及执行主要逻辑。
- 剧情的演员列表存在ScenarioMod中的一个Dictionary中,Key是Name,Value是演员的ScenarioObjController
代码工程地址:
https://pan.baidu.com/s/1eSs3jAq
主场景在TimelineAction下的scene,按”K”键开始剧情。
(3)
Unity--Timeline自定义PlayableTrack
https://blog.csdn.net/qq826364410/article/details/80511057
今天尝试使用Unity timeline来做段动画, 发现BasicPlayableBehaviour已弃用, 而新的PlayableBehaviour不能直接往Playable Track拖。
翻了下文档使用PlayableAsset来新建PlayableBehaviour,然后使用ExposedReference,具体实现如下:
C# PlayableTest代码实现,功能就是当timeline开始播放时,设置Text为true,并把m_DialogStr字符串赋值给Text:
using UnityEngine.Playables;
using UnityEngine.UI;
// A behaviour that is attached to a playable
public class PlayableTest : PlayableBehaviour
{
public Text m_DialogContainer;
public string m_DialogStr;
// Called when the state of the playable is set to Play
public override void OnBehaviourPlay(Playable playable, FrameData info)
{
if (m_DialogContainer != null)
{
m_DialogContainer.gameObject.SetActive(true);
m_DialogContainer.text = m_DialogStr;
}
}
// Called when the state of the playable is set to Paused
public override void OnBehaviourPause(Playable playable, FrameData info)
{
if (m_DialogContainer != null)
{
m_DialogContainer.gameObject.SetActive(false);
}
}
}
C# PlayableAssetTest 代码实现,真正拖入Timeline的PlayableTrack中的脚本,在Scene中创建一个UI的Text组件,并把Text组件拖到PlayableAssetTest 上的Text上,在m_DialogStr随便填写一段字符串,运行Unity即可看到效果:
注:Timeline的PlayOnAwake,一定要勾选,否则不会自动执行。当然也可以在代码中调用Timeline的Play()方法。
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.UI;
[System.Serializable]
public class PlayableAssetTest : PlayableAsset
{
public ExposedReference<Text> m_DialogContainer;
public string m_DialogStr;
// Factory method that generates a playable based on this asset
public override Playable CreatePlayable(PlayableGraph graph, GameObject go)
{
var playable = ScriptPlayable<PlayableTest>.Create(graph);
playable.GetBehaviour().m_DialogContainer = m_DialogContainer.Resolve(graph.GetResolver());
playable.GetBehaviour().m_DialogStr = m_DialogStr;
return playable;
}
}
下面给出代码控制Timeline执行,把这个脚本挂在Scene中的随便一个GameObject上,不勾选PlayOnAwake,并把之前创建好的Text组件赋值给脚本的Text,把Timeline赋值给脚本的PlayableDirector,OK,现在运行Unity,只有当按下k键时,Timeline才会运行:
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Timeline;
using UnityEngine.UI;
public class DialogDirector : MonoBehaviour
{
public PlayableDirector director;
public Text text;
void Update()
{
if (Input.GetKeyDown(KeyCode.K))
{
foreach (PlayableBinding bind in director.playableAsset.outputs)
{
if (bind.sourceObject.GetType() == typeof(PlayableTrack))
{
PlayableTrack playableTrack = (PlayableTrack)bind.sourceObject;
foreach (var clip in playableTrack.GetClips())
{
object clipAsset = clip.asset;
if (clipAsset is PlayableAssetTest)
{
PlayableAssetTest test = clipAsset as PlayableAssetTest;
director.SetReferenceValue(test.m_DialogContainer.exposedName, text);
}
}
}
}
director.Play();
}
}
}
————————————————
版权声明:本文为CSDN博主「Mr_传奇」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq826364410/article/details/80511057
(4)
tsubaki/Rebind.cs
https://gist.github.com/tsubaki/30416864f4438fe1603ca34d32238c26
(5)
Set PlayableDirector bindings from script
https://forum.unity.com/threads/set-playabledirector-bindings-from-script.487337/
(6)
[专栏作家]探索TimelinePlayableAPI,让Timeline为所欲为
https://www.sohu.com/a/231583446_667928
之前快速地学习了一下Timeline,这里我们做快速的回顾,Timeline主要分为TimelineInstance和TimelineAsset,可以用Timeline PlayableDirector控制播放哪一个TimelineAsset
今天我们再来看看Timeline中的Track,并且动手实现一个老年迪斯科场景。
一图流
Track
Timeline可以添加很多Track来对不同的对象做控制。
- Track 在Clip上控制动画,可以在有Animator组件但是没有AnimatorController的情况下直接播放动画。
- Audio Track 在Clip上控制音频播放。
- Activtion Track 在Clip上控制物体是否在场景中Active,GameObject.SetActive()的作用
- Control Track 在Clip上可以控制和时间相关的元素,可以控制粒子系统,克隆物体,控制另一个timeline等。厉害的是我们放在Control Track上的例子特效,可以随意地拖动Timeline来预览效果,对特效兄弟来说是应该很强大很爽的地方。
- Playable Track 控制继承自BasicPlayableBehaviour的clip (在2017.4.0f1版本里原先的BasicPlayableBehaviour因为性能原因已经被弃用,建议采用PlayableAsset和PlayableBehaviour)
如何有了这篇文章
虽然上面提供的几个track已经有很强大的功能了,但是实际操作中我们会发现这些远远不够,官方的Mannul上也没有更多的介绍,有效的资料是少之又少。那么官方演示的demo里的对话系统是怎么通过Timeline实现的呢?
于是我开始寻找,在Youtube上找到了Unite Europe2017上的演讲视频,Extending Timeline with your own playables(https://www.youtube.com/watch?v=uBPRfcox5hE&t=2331s)。
研究了一番,里面的例子就是LightControl将自己的理解分享给大家。让大家都能在Timeline里为所欲为。
深度理解Timeline
Timeline是建立在Playables API(https://docs.unity3d.com/Manual/Playables.html)上的PlayableGraph系统,在这套系统中Timeline相当于是一个函数的作用,我们从Assset传入InputData,Timeline处理后输出OutputData到对应的Component。
这套系统中有4个关键部分,Data,Clip,Mixer,Track
我希望我的这张图可以帮助大家快速对应和理解这4个部分。
Timeline也一个Templete,可以方便快速地被复用。
- The Data 用来存放数据,需要被序列化。继承自PlayableBehaviour
- The Clip 也就是asset,继承自PlayableAsset。因为是asset,所以不能直接与场景中的物体关联,需要关联场景中的物体时要用ExposedReference来声明, 并且通过Resolve方法赋值。
- The Mixer Mixer控制当前Track中所有的clip的行为,根据每个clip不同的输入权重,计算需要的结果。 Mixer在Timeline中算是最重要的部分了。
- The Track 把Mixer计算的结果输出,可以指定输出到绑定的物体上。继承自TrackAsset。有好几个特性可以绑定,
- TrackColor : 定义在编辑器中Track的标识颜色
- BindingObejctType : 当前Track上的Mixer输出后的数据要传递的对象类型
- TrackClipType : 当前Track上的Clip的类型
实践
通过上面的探究,我们要做老年disco效果,那就来定制一个自己的track,专门用来控制Light,我们叫LightControl
- 创建一个新的场景添加两个角色,一红一蓝
- 新建一个ParticleSytem,烘托一下Disco的气氛
- 创建一个新的Timeline,DiscoTimeline
- 在DiscoTimeline上新建2个AnimationTrack,一个控制蓝角色的动画,一个控制红角色的动画
- 在DiscoTimeline新建一个ControlTrack,控制刚才创建的ParticleSystem
- 在场景中新建一个SpotLight和一个PointLight
- 在DiscoTimeline中新建一个TrackGroup,命名为PlayableLight
- 在DiscoTimeline中新建我们的LightControl Track,将SpotLight与这个Track绑定,命名为SpotLight
- 在DiscoTimeline中新建我们的LightControl Track,将PointLight与这个Track绑定,命名为PointLight
- 将我们自定义的Clip添加2段到SpotLightTrack上,在一个Clip上的LookAtTarget上绑定蓝角色,另一个Clip上的LookAtTarget绑定到红角色
- 将我们自定义的Clip添加2段到PointLightTrack上,设置变换的灯光颜色和强度。 最后的Timeline就是这样
Play and Enjoy It
结尾
关于Playable API比较有趣的是,Playable使用C#结构体而非C++对象来保存对象。使用结构体的目的是避免分配GC所需的内存。这样用起来可能稍微有点复杂,但由于该API承载了未来的很多功能,所以必须注重性能问题。
掌握了Timeline的系统设计理念后,我们基本上就能掌握Timeline,实现自己想要的效果了,希望大家能打开脑洞,用Timeline创造出更多好玩的东西来。
另外视频中提到的PreviewMode我还没有非常明白,就先不写出来了,如果有兄弟知道的话,希望你能不吝赐教。