基于TimeLine编辑角色动画(二)
如何在Clip范围内执行相应的操作
有两种方法:
官方的方法(一)、通过playable.GetInputWeight(i),获得Weight,在播放到Clip范围内如果没有过渡的话Weight=1,如果没有Clip范围内,Weight=0;
并在ProcessFrame 每帧判断Weight。
(二)、PlayableBehaviour 有两个重载方法
OnBehaviourPlay()在Clip开始播放到范围时执行,OnBehaviourPause()在离开Clip播放范围时执行
可以设置个bool变量控制。
如果需要混合的动画最终的逻辑写在MixerBehaviour 的ProcessFrame(),否则写在Playabehavior的OnBehaviourPlay()。在Playabehavior中想拿到外部引用,可以在PlayableClip中 ExposedReference<>,在外部绑定。
自动绑定代码
[Button("重新绑定")] void BuilderPlayableDirector() { if (playableDirector==null) playableDirector = GetComponent<PlayableDirector>(); if(animator==null) animator = GetComponent<Animator>(); if(playerController==null) playerController = GetComponent<PlayerController>(); if(audioSource==null) audioSource = Camera.main.GetComponent<AudioSource>(); if (playableAssets.Values.Count==0) { LoadPlayableAssets(PlayerCareer.Warrior); } foreach (var pa in playableAssets.Values) { TimelineAsset timeline = pa as TimelineAsset; foreach (TrackAsset item in timeline.GetOutputTracks()) { BindTrack(item); BindClip(item); } } }
void BindClip(TrackAsset item) { foreach (TimelineClip i in item.GetClips()) { object clipAsset= i.asset; if (clipAsset is CameraShakeTrackClip) { CameraShakeTrackClip p = clipAsset as CameraShakeTrackClip; playableDirector.SetReferenceValue(p.playerController.exposedName, playerController); } } } void BindTrack(TrackAsset item) { IEnumerable<PlayableBinding> bind = item.outputs; foreach (PlayableBinding b in bind) { if (b.outputTargetType != null) { switch (b.outputTargetType.Name) { case "Animator": playableDirector.SetGenericBinding(b.sourceObject, animator); break; case "AudioSource": playableDirector.SetGenericBinding(b.sourceObject, audioSource); break; case "PlayerController": playableDirector.SetGenericBinding(b.sourceObject, playerController); break; default: break; } } } }
另外说一个测试结果 当Animator和PlayableDirector同时存在时,只播放PlayableDirector,可以将角色的Idle,Run,Walk等没有太多动画事件的动画使用Animator播放,需要大量编辑的复杂动画使用PlayableDirector播放。