关于unity timeline control asset 属性的记录

  记一次尴尬事件,顺便记一下control asset的属性。起因是这样的,美术在timeline的control track上放置了一个例子特效,结果在timeline播完,特效又重新播放了一次。排查完别的地方,并没有控制该特效,那么问题就能只是timeline中的问题。
  看到asset的属性如下:
在这里插入图片描述

  感觉其中可能有问题的也就post-playback这个属性了。去查了下手册:
在这里插入图片描述
  首先注意一下,post playback并不仅仅是只对嵌套的timeline起作用,大家可以测试下。由于我把revert(还原)和reverse(取反)看混了,无巧不成书,我在看完手册以后又看到了这位老哥的文章(如下图所示,试图说明不止我一个人会犯这种错误,没有说这位老哥跟我一样菜的意思,而且老哥已经在别的文章里纠正了)就十分不解,为什么播完以后这个特效又激活了?继续看了一些资料才意识到看错了(难受)。然后告诉美术把post playback改成了inactive,就没再播放了。我推断可能是这样的:Timeline开始播放之前特效是开着的,Timeline一开始播放就控制特效关闭了,等到特效的clip播放时,特效正常播放。Timeline播放完重置特效为激活状态,同时又释放了对特效的控制权,所以特效就又播了一遍
在这里插入图片描述
  还有,关于postplayback的执行时间,有看到不同的说法,这里直接上代码吧。看最后的OnPlayableDestroy()就明白了,当timeline播完,Playable开始销毁的时候才会修改Postplayback

using UnityEngine.Playables;

namespace UnityEngine.Timeline
{
    /// <summary>
    /// Playable that controls the active state of a GameObject.
    /// </summary>
    public class ActivationControlPlayable : PlayableBehaviour
    {
        /// <summary>
        /// The state of a GameObject's activeness when a PlayableGraph stops.
        /// </summary>
        public enum PostPlaybackState
        {
            /// <summary>
            /// Set the GameObject to active when the PlayableGraph stops.
            /// </summary>
            Active,

            /// <summary>
            /// Set the GameObject to inactive when the [[PlayableGraph]] stops.
            /// </summary>
            Inactive,

            /// <summary>
            /// Revert the GameObject to the active state it was before the [[PlayableGraph]] started.
            /// </summary>
            Revert
        }

        enum InitialState
        {
            Unset,
            Active,
            Inactive
        }

        public GameObject gameObject = null;
        public PostPlaybackState postPlayback = PostPlaybackState.Revert;
        InitialState m_InitialState;

        /// <summary>
        /// Creates a ScriptPlayable with an ActivationControlPlayable behaviour attached
        /// </summary>
        /// <param name="graph">PlayableGraph that will own the playable</param>
        /// <param name="gameObject">The GameObject that triggered the graph build</param>
        /// <param name="postPlaybackState">The state to leave the gameObject after the graph is stopped</param>
        /// <returns>Returns a playable that controls activation of a game object</returns>
        public static ScriptPlayable<ActivationControlPlayable> Create(PlayableGraph graph, GameObject gameObject, ActivationControlPlayable.PostPlaybackState postPlaybackState)
        {
            if (gameObject == null)
                return ScriptPlayable<ActivationControlPlayable>.Null;

            var handle = ScriptPlayable<ActivationControlPlayable>.Create(graph);
            var playable = handle.GetBehaviour();
            playable.gameObject = gameObject;
            playable.postPlayback = postPlaybackState;

            return handle;
        }

        /// <summary>
        /// This function is called when the Playable play state is changed to Playables.PlayState.Playing.
        /// </summary>
        /// <param name="playable">The playable this behaviour is attached to.</param>
        /// <param name="info">The information about this frame</param>
        public override void OnBehaviourPlay(Playable playable, FrameData info)
        {
            if (gameObject == null)
                return;

            gameObject.SetActive(true);
        }

        /// <summary>
        /// This function is called when the Playable play state is changed to PlayState.Paused.
        /// </summary>
        /// <param name="playable">The playable this behaviour is attached to.</param>
        /// <param name="info">The information about this frame</param>
        public override void OnBehaviourPause(Playable playable, FrameData info)
        {
            // OnBehaviourPause can be called if the graph is stopped for a variety of reasons
            //  the effectivePlayState will test if the pause is due to the clip being out of bounds
            if (gameObject != null && info.effectivePlayState == PlayState.Paused)
            {
                gameObject.SetActive(false);
            }
        }

        /// <summary>
        /// This function is called during the ProcessFrame phase of the PlayableGraph.
        /// </summary>
        /// <param name="playable">The playable this behaviour is attached to.</param>
        /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
        /// <param name="userData">unused</param>
        public override void ProcessFrame(Playable playable, FrameData info, object userData)
        {
            if (gameObject != null)// && !gameObject.activeSelf)
                gameObject.SetActive(true);
        }

        /// <summary>
        /// This function is called when the PlayableGraph that owns this PlayableBehaviour starts.
        /// </summary>
        /// <param name="playable">The playable this behaviour is attached to.</param>
        public override void OnGraphStart(Playable playable)
        {
            if (gameObject != null)
            {
                if (m_InitialState == InitialState.Unset)
                    m_InitialState = gameObject.activeSelf ? InitialState.Active : InitialState.Inactive;
            }
        }

        /// <summary>
        /// This function is called when the Playable that owns the PlayableBehaviour is destroyed.
        /// </summary>
        /// <param name="playable">The playable this behaviour is attached to.</param>
        public override void OnPlayableDestroy(Playable playable)
        {
            if (gameObject == null || m_InitialState == InitialState.Unset)
                return;

            switch (postPlayback)
            {
                case PostPlaybackState.Active:
                    gameObject.SetActive(true);
                    break;

                case PostPlaybackState.Inactive:
                    gameObject.SetActive(false);
                    break;

                case PostPlaybackState.Revert:
                    gameObject.SetActive(m_InitialState == InitialState.Active);
                    break;
            }
        }
    }
}

  最后稍微提一下ITimeCOntrol。这个是用来自定义在clip开始和结束时要执行的操作。

using UnityEngine.Playables;

namespace UnityEngine.Timeline
{
    /// <summary>
    /// A PlayableBehaviour that manages a component that implements the ITimeControl interface
    /// </summary>
    public class TimeControlPlayable : PlayableBehaviour
    {
        ITimeControl m_timeControl;

        bool m_started;

        /// <summary>
        /// Creates a Playable with a TimeControlPlayable behaviour attached
        /// </summary>
        /// <param name="graph">The PlayableGraph to inject the Playable into.</param>
        /// <param name="timeControl"></param>
        /// <returns></returns>
        public static ScriptPlayable<TimeControlPlayable> Create(PlayableGraph graph, ITimeControl timeControl)
        {
            if (timeControl == null)
                return ScriptPlayable<TimeControlPlayable>.Null;

            var handle = ScriptPlayable<TimeControlPlayable>.Create(graph);
            handle.GetBehaviour().Initialize(timeControl);
            return handle;
        }

        /// <summary>
        /// Initializes the behaviour
        /// </summary>
        /// <param name="timeControl">Component that implements the ITimeControl interface</param>
        public void Initialize(ITimeControl timeControl)
        {
            m_timeControl = timeControl;
        }

        /// <summary>
        /// This function is called during the PrepareFrame phase of the PlayableGraph.
        /// </summary>
        /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
        /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
        public override void PrepareFrame(Playable playable, FrameData info)
        {
            Debug.Assert(m_started, "PrepareFrame has been called without OnControlTimeStart being called first.");
            if (m_timeControl != null)
                m_timeControl.SetTime(playable.GetTime());
        }

        /// <summary>
        /// This function is called when the Playable play state is changed to Playables.PlayState.Playing.
        /// </summary>
        /// <param name="playable">The Playable that owns the current PlayableBehaviour.</param>
        /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
        public override void OnBehaviourPlay(Playable playable, FrameData info)
        {
            if (m_timeControl == null)
                return;

            if (!m_started)
            {
                m_timeControl.OnControlTimeStart();
                m_started = true;
            }
        }

        /// <summary>
        /// This function is called when the Playable play state is changed to PlayState.Paused.
        /// </summary>
        /// <param name="playable">The playable this behaviour is attached to.</param>
        /// <param name="info">A FrameData structure that contains information about the current frame context.</param>
        public override void OnBehaviourPause(Playable playable, FrameData info)
        {
            if (m_timeControl == null)
                return;

            if (m_started)
            {
                m_timeControl.OnControlTimeStop();
                m_started = false;
            }
        }
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值