Unity Timeline封装,方便动态设置Timeline控制对象和参数

最近下载了Unity2017,有一个Timeline的新功能,编辑起来还是比较好上手的,不过如果是要进行动态绑定,就必须使用API,而API用起来步骤有点多,所以自己封装了一下。

我把Timeline和它的属性进行了包装,封成一个TimelineUnit,然后再封装一个挂Timeline的接口。

TimelineUnit.cs

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Timeline;
using UnityEngine.Playables;

public class TimelineUnit
{
    public string name;
    public PlayableDirector director;
    public PlayableAsset asset;
    public Dictionary<string, PlayableBinding> bindings;
    public Dictionary<string, Dictionary<string, PlayableAsset>> clips;

    public void Init(string name, PlayableDirector director, PlayableAsset asset)
    {
        director.playableAsset = asset;
        this.name = name;
        this.director = director;
        this.asset = asset;

        bindings = new Dictionary<string, PlayableBinding>();
        clips = new Dictionary<string, Dictionary<string, PlayableAsset>>();
        foreach (var o in asset.outputs)
        {
            var trackName = o.streamName;
            bindings.Add(trackName, o);

            var track = o.sourceObject as TrackAsset;
            var clipList = track.GetClips();
            foreach (var c in clipList)
            {
                if (!clips.ContainsKey(trackName))
                {
                    clips[trackName] = new Dictionary<string, PlayableAsset>();
                }
                var name2Clips = clips[trackName];
                if (!name2Clips.ContainsKey(c.displayName))
                {
                    name2Clips.Add(c.displayName, c.asset as PlayableAsset);
                }
            }
        }
    }

    public void SetBinding(string trackName, Object o)
    {
        director.SetGenericBinding(bindings[trackName].sourceObject, o);
    }

    public T GetTrack<T>(string trackName) where T : TrackAsset
    {
        return bindings[trackName].sourceObject as T;
    }

    public T GetClip<T>(string trackName, string clipName) where T : PlayableAsset
    {
        if (clips.ContainsKey(trackName))
        {
            var track = clips[trackName];
            if (track.ContainsKey(clipName))
            {
                return track[clipName] as T;
            }
            else
            {
                Debug.LogError("GetClip Error, Track does not contain clip, trackName: " + trackName + ", clipName: " + clipName);
            }
        }
        else
        {
            Debug.LogError("GetClip Error, Track does not contain clip, trackName: " + trackName + ", clipName: " + clipName);
        }
        return null;
    }

    public void Play()
    {
        director.Play();
    }
}


TimelineHelper.cs

using UnityEngine;
using UnityEngine.Playables;

public class TimelineHelper
{
    public static TimelineUnit AddTimeline(GameObject go, string timelineName)
    {
        var unit = new TimelineUnit();
        var director = go.GetComponent<PlayableDirector>();
        if (null == director)
            director = go.AddComponent<PlayableDirector>();
        var asset = Resources.Load<PlayableAsset>("TimelineRes/" + timelineName);
        unit.Init(timelineName, director, asset);
        return unit;
    }
}


现在做一个Timeline,然后进行测试

一个AnimationTrack,一个PlayableTrack,动画轨道不多讲,难点是PlayableTrack,这个是可以自定义逻辑的轨道

需要写两个类,一个继承PlayableAsset,一个继承PlayableBehaviour

using UnityEngine;
using UnityEngine.Playables;

public class MoveObjPlayableAsset : PlayableAsset
{
    public GameObject go;
    public Vector3 pos;

    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    {
        var bhv = new MoveObjPlayableBehaviour();
        bhv.go = go;
        bhv.pos = pos;
        return ScriptPlayable<MoveObjPlayableBehaviour>.Create(graph, bhv);
    }
}

 

using UnityEngine;
using UnityEngine.Playables;

public class MoveObjPlayableBehaviour : PlayableBehaviour
{
    public GameObject go;
    public Vector3 pos;

    public override void OnGraphStart(Playable playable)
    {
        base.OnGraphStart(playable);

        Debug.Log("OnGraphStart=======================");
    }

    public override void OnGraphStop(Playable playable)
    {
        base.OnGraphStop(playable);
        Debug.Log("OnGraphStop=======================");
    }

    public override void OnBehaviourPlay(Playable playable, FrameData info)
    {
        base.OnBehaviourPlay(playable, info);
        Debug.Log("OnBehaviourPlay=======================");
        if (null != go)
        {
            go.transform.position = pos;
        }
    }

    public override void OnBehaviourPause(Playable playable, FrameData info)
    {
        base.OnBehaviourPause(playable, info);
        Debug.Log("OnBehaviourPause=======================");
        if (null != go)
        {
            go.transform.position = Vector3.zero;
        }
    }

    public override void OnBehaviourDelay(Playable playable, FrameData info)
    {
        base.OnBehaviourDelay(playable, info);
        Debug.Log("OnBehaviourDelay=======================");
    }
}


这样,就可以将MoveObjPlayableAsset脚本直接拖动到PlayableTrack轨道上,具体的脚本逻辑在MoveObjPlayableBehaviour中写,我这里的逻辑是改变物体的坐标,具体逻辑就看具体需求了,这里只是举个例子

程序入口我放在一个runner的脚本里,挂在场景中的一个物体上

using UnityEngine;

public class Runner : MonoBehaviour
{
    void Start()
    {
        var go = new GameObject("TimelineGo");
        var unit = TimelineHelper.AddTimeline(go, "myTimeline");
        unit.director.extrapolationMode = UnityEngine.Playables.DirectorWrapMode.Loop;
        unit.SetBinding("at", go);
        
        var p = unit.GetClip<MoveObjPlayableAsset>("myPlayable", "b");
        p.go = gameObject;
        unit.Play();
    }
}

 

 

 

运行就可以看到有一个TimelineGo物体挂了Timeline运行了

 

  • 6
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: Unity Timeline 可以通过代码来控制,比如您可以在代码中访问、播放、暂停或停止 Timeline,更改其中的参数等。下面是一个示例代码,演示如何播放一个名为 "MyTimeline" 的 Timeline: ``` using UnityEngine; using UnityEngine.Playables; public class MyTimelineController : MonoBehaviour { public PlayableDirector timeline; void Start() { timeline = GetComponent<PlayableDirector>(); timeline.Play("MyTimeline"); } } ``` 请注意,上面的代码仅作为示例,您可能需要根据实际需求进行调整。 ### 回答2: ### 回答3: Unity TimelineUnity中用于制作时间轴动画的工具,它可以控制游戏中声音、动画、材质、粒子系统等多种元素的时间和触发方式。我们可以使用Unity Timeline来制作复杂的动画序列、交互式场景和游戏事件,而且不需要编写编程代码,仅仅通过图形界面就可以完成整个操作过程。 但是在某些需要更加精细的控制上,我们需要通过代码来实现对Timeline控制。这里讲解几种常用的代码控制方法: 1. 控制时间轴的播放和停止: 我们可以通过代码访问TimeLine控制它的播放和停止,在播放过程中我们还可以控制它的播放速度。 //获取Timeline组件 Timeline timeline = GetComponent<Timeline>(); //播放Timeline timeline.Play(); //停止Timeline timeline.Stop(); //设置Timeline速度 timeline.playbackSpeed = 1.5f; 2. 控制轨道的启用和禁用: 在一个Timeline中存在多个轨道,我们可以通过代码来控制这些轨道的启用和禁用。 //获取轨道,然后停用轨道 TrackAsset track = timeline.GetTrack(trackID); track.enabled = false; 3. 控制轨道上某一元素的播放和停止: 在一个轨道上可能存在多个元素,我们可以通过代码来控制这些元素的播放和停止。 //获取轨道上的元素,并停用该元素 PlayableAsset playable = track.GetClips()[clipIndex].asset; playable.enabled = false; 4. 控制轨道元素的属性变化: 在一个轨道上,我们可以通过代码来控制该轨道中元素的属性变化,例如动画的位置,角度,大小等。 //获取动画轨道 AnimationTrack animationTrack = timeline.GetTrack(trackID) as AnimationTrack; //获取轨道上的动画片段 TimelineClip clip = animationTrack.GetClips()[clipIndex]; //获取动画片段中的绑定对象 GameObject animationTarget = clip.GetBinding<GameObject>(); //设置对象的Transform中position的值 animationTarget.transform.position = newPosition; Unity Timeline的代码控制可以让我们精细地控制游戏中的各种元素,让动画更加流畅、交互更加自然,同时也更好地满足了游戏开发中的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林新发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值