当前位置:   article > 正文

游戏开发技术--Timeline封装(Unity)_unity playablebehaviour

unity playablebehaviour

一、设计意图

使用Unity中的Timeline功能进行技能效果或者过场剧情开发的都知道,对于Timeline功能的扩展,通常要扩展以下几个类:

  1. TrackAsset:轨道资源,用来创建片段和Playable混合器,提供序列化数据与Binding。
  2. PlayableAsset:片段资源,用来创建Playable以及提供序列化数据。
  3. PlayableBehaviour:逻辑行为,用来实现Playable具体的业务逻辑。

然而,在扩展过程中,会发现一些不便利的情况,最明显的就是PlayableBehaviour的回调函数,对于不熟悉Playable的开发者来说,需要一定的理解成本。为此,我对Timeline的结构进行了进一步的封装。

二、设计思路

对于TrackAsset和PlayableAsset来说,设计上希望它们只是提供具体序列化数据,而屏蔽掉对于Playable的创建过程。而对于PlayableBehaviour来说,希望它仅用于实现业务逻辑,同时提炼回调函数使其友好于普通的Unity游戏开发者,而不需要过多了解Playable的机制。

三、实现方式

1、PlayableBehaviour封装

先来对PlayableBehaviour进行封装,定义BaseBehaviour类,对原有的回调函数使用修饰符sealed,定义通用的回调函数(OnCreate,OnDestroy,OnStart,OnUpdate,OnStop),同时提供一些获取数据的接口(GetData,Time,Duration,Percent)。

全部代码如下:

  1. namespace TimelineKit
  2. {
  3. using UnityEngine.Playables;
  4. public abstract class BaseBehaviour : PlayableBehaviour
  5. {
  6. private bool _started;
  7. private bool _played;
  8. private object _playerData;
  9. private Playable _playable = Playable.Null;
  10. private PlayableAsset _asset;
  11. public static Playable CreatePlayable<T>(PlayableGraph graph, PlayableAsset data) where T : BaseBehaviour, new()
  12. {
  13. var playable = ScriptPlayable<T>.Create(graph);
  14. T behaviour = playable.GetBehaviour();
  15. behaviour._asset = data;
  16. behaviour._playable = playable;
  17. return playable;
  18. }
  19. #region protected
  20. protected T GetData<T>() where T : PlayableAsset => _asset as T;
  21. protected float Time => (float)_playable.GetTime();
  22. protected float Duration => (float) _playable.GetDuration();
  23. protected float Percent => (float) (_playable.GetDuration().Equals(0) ? 0 : _playable.GetTime() / _playable.GetDuration());
  24. #endregion protected
  25. #region base
  26. protected virtual void OnCreate() { }
  27. protected virtual void OnDestroy() { }
  28. protected virtual void OnStart(object binding) { }
  29. protected virtual void OnUpdate(object binding, float deltaTime) { }
  30. protected virtual void OnStop(object binding) { }
  31. #endregion base
  32. #region sealed
  33. public sealed override void OnBehaviourPlay(Playable playable, FrameData info)
  34. {
  35. if (_played)
  36. return;
  37. _started = false;
  38. _played = true;
  39. }
  40. public sealed override void OnBehaviourPause(Playable playable, FrameData info)
  41. {
  42. if (!_played)
  43. return;
  44. OnStop(_playerData);
  45. _played = false;
  46. }
  47. public sealed override void OnPlayableCreate(Playable playable)
  48. {
  49. OnCreate();
  50. }
  51. public sealed override void OnPlayableDestroy(Playable playable)
  52. {
  53. OnDestroy();
  54. }
  55. public sealed override void OnGraphStart(Playable playable) { }
  56. public sealed override void OnGraphStop(Playable playable) { }
  57. public sealed override void PrepareData(Playable playable, FrameData info) { }
  58. public sealed override void PrepareFrame(Playable playable, FrameData info) { }
  59. public sealed override void ProcessFrame(Playable playable, FrameData info, object playerData)
  60. {
  61. if (!_played)
  62. return;
  63. if (!_started)
  64. {
  65. _started = true;
  66. _playerData = playerData;
  67. OnStart(_playerData);
  68. }
  69. OnUpdate(_playerData, info.deltaTime);
  70. }
  71. #endregion sealed
  72. }
  73. }

2、PlayableAsset封装

为了和对应的PlayableBehaviour进行绑定,这里使用泛型对PlayableAsset进行封装,定义类型BaseClipAsset<T>,并实现了CreatePlayable的方法。因此继承此类型的子类只需要提供序列化数据即可。

全部代码如下:

  1. namespace TimelineKit
  2. {
  3. using UnityEngine;
  4. using UnityEngine.Playables;
  5. public class BaseClipAsset<T> : PlayableAsset where T : BaseBehaviour, new()
  6. {
  7. public sealed override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
  8. {
  9. return BaseBehaviour.CreatePlayable<T>(graph, this);
  10. }
  11. }
  12. }

3、TrackAsset封装

TrackAsset的封装和PlayableAsset的封装思路类似,也是对Create方法进行重载权限设置,定义了BaceTrackAsset和BaceTrackAsset<T>两种类型,其中使用泛型的类型可以用来创建Mixer混合器。

全部代码如下:

  1. namespace TimelineKit
  2. {
  3. using UnityEngine;
  4. using UnityEngine.Playables;
  5. using UnityEngine.Timeline;
  6. public class BaseTrackAsset : TrackAsset
  7. {
  8. protected sealed override Playable CreatePlayable(PlayableGraph graph, GameObject gameObject, TimelineClip clip)
  9. {
  10. return base.CreatePlayable(graph, gameObject, clip);
  11. }
  12. public sealed override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
  13. {
  14. return base.CreateTrackMixer(graph, go, inputCount);
  15. }
  16. }
  17. public class BaseTrackAsset<T> : TrackAsset where T : BaseBehaviour, new()
  18. {
  19. protected sealed override Playable CreatePlayable(PlayableGraph graph, GameObject gameObject, TimelineClip clip)
  20. {
  21. return base.CreatePlayable(graph, gameObject, clip);
  22. }
  23. public sealed override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
  24. {
  25. var mixer = BaseBehaviour.CreatePlayable<T>(graph, this);
  26. mixer.SetInputCount(inputCount);
  27. return mixer;
  28. }
  29. }
  30. }

四、使用案例

使用上面包装好的Timeline组件,可以很容易的对Timeline功能进行扩展,例如我们要实现一个Timeline控制光强的功能。

TrackAsset:

  1. namespace TimelineKit
  2. {
  3. using UnityEngine;
  4. using UnityEngine.Timeline;
  5. [TrackColor(1f,1f,0f)]
  6. [TrackClipType(typeof(LightClipAsset))]
  7. [TrackBindingType(typeof(Light))]
  8. public class LightTrackAsset : BaseTrackAsset { }
  9. }

BaseClipAsset实现:

  1. namespace TimelineKit
  2. {
  3. public class LightClipAsset : BaseClipAsset<LightBehaviour>
  4. {
  5. public float StartIntensity;
  6. public float EndIntensity;
  7. }
  8. }

BaseBehaviour实现:

  1. namespace TimelineKit
  2. {
  3. using UnityEngine;
  4. public class LightBehaviour : BaseBehaviour
  5. {
  6. protected override void OnUpdate(object binding, float deltaTime)
  7. {
  8. if (binding is Light light)
  9. {
  10. var data = GetData<LightClipAsset>();
  11. light.intensity = Mathf.Lerp(data.StartIntensity,data.EndIntensity, Percent);
  12. }
  13. }
  14. }
  15. }

做了个简易的场景,最终效果如下:

Demo

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/95491
推荐阅读
相关标签
  

闽ICP备14008679号