美文网首页UnityUnity干货Unity技术分享
【Unity3D开发】DOTween 插件仿写

【Unity3D开发】DOTween 插件仿写

作者: DamonTo | 来源:发表于2017-05-17 16:08 被阅读334次

本文同时发布至我的个人博客,点击进入我的个人博客阅读。本博客供技术交流与经验分享,可自由转载。转载请在评论区或私信简单通知,感谢!

项目简介

DOTween是一个用于实现插值动画(补间动画)的 Unity 插件。“插值”这个概念可能一些使用 AE 或 Flash 等动画软件的同学可能有所了解。简单来说,插值动画(补间动画)就是在时间轴上定义两个不同时间的动画关键帧状态后,自动生成两个时间点之间所有帧动画动画制作方法。关于什么是插值动画(补间动画),以及什么是帧动画在这里不做过多的解释,感兴趣的读者可以参考这一篇文章——帧动画和补间动画

​ 这个项目主要是利用C#中的拓展方法来实现一个简单的DOTween插件效果,实现过程涉及到拓展方法、协程等知识点。

设计参考

​ DOTween是一个开源插件,可以在GitHub上找到这个项目:DOTween - GitHub。官方实现的方式较为复杂,我在这里参考了其架构设计,将项目分成:TweenIDOTweenExtension

效果展示

开发过程

(一)Tween.cs:补间动画类

​ 定义一个简单的补间动画类,需要注意的是每个补间动画都包括一个协程。通过使用协程,我们的动画函数就可以实现不在一帧里完成,而是逐帧调用,每帧执行一部分。这符合动画实现的需求。

using UnityEngine;

namespace myTween
{
    public class Tween
    {
        internal string tid;
        internal Vector3 target;
        internal float duration;
        internal bool isPause = false;
        internal bool isAutoKill = true;
        internal Coroutine coroutine = null;
        internal Transform transform = null;
        public delegate void OnComplete();
        internal OnComplete onComplete = null;

        //constructor
        public Tween(string tid, Vector3 target, float duration, Transform transform, Coroutine coroutine)
        {
            this.tid = tid;
            this.target = target;
            this.duration = duration;
            this.transform = transform;
            this.coroutine = coroutine;
            IDOTween.getInstance().Add(this);
        }

        //set the coroutine of tween
        public void setCoroutine(Coroutine coroutine)
        {
            this.coroutine = coroutine;
        }

        public void setAutoKill(bool isAutoKill)
        {
            this.isAutoKill = isAutoKill;
        }

        public void Play()
        {
            isPause = false;
        }

        public void Pause()
        {
            isPause = true;
        }

        public void Kill()
        {
            MonoBehaviour mono = transform.GetComponent<MonoBehaviour>();
            mono.StopCoroutine(coroutine);
            IDOTween.getInstance().Remove(this);
        }

        public void runOnComplete()
        {
            if (onComplete != null)
            {
                onComplete();
            }
            if (isAutoKill)
            {
                Kill();
            }
        }

        public void setOnComplete(OnComplete fun)
        {
            onComplete += fun;
        }
    }
}

(二)IDOTween.cs:动画工厂类

​ 工厂类主要通过一个List来储存和管理所有的补间动画对象,同时也定义了一些基础的增删改查的基础函数。主要是注意控制单实例。

using System.Collections.Generic;
using UnityEngine;

namespace myTween {
    public class IDOTween
    {
        private static List<Tween> dotweenList = new List<Tween>();
        private static IDOTween dotween = null;

        //控制单实例
        public static IDOTween getInstance()
        {
            if (dotween == null)
            {
                dotween = new IDOTween();
            }
            return dotween;
        }

        public void Add(Tween d)
        {
            dotweenList.Add(d);
        }

        public void Remove(Tween d)
        {
            dotweenList.Remove(d);
        }

        public static void Play(string id)
        {
            foreach (Tween t in dotweenList)
            {
                if (t.tid == id)
                {
                    t.Play();
                }
            }
        }

        public static void Play(Transform transform)
        {
            foreach (Tween d in dotweenList)
            {
                if (d.transform == transform)
                {
                    d.Play();
                }
            }
        }

        public static void PlayAll()
        {
            foreach (Tween d in dotweenList)
            {
                d.Play();
            }
        }

        public static void Pause(string id)
        {
            for (int i = dotweenList.Count - 1; i >= 0; i--)
            {
                if (dotweenList[i].tid == id)
                {
                    dotweenList[i].Pause();
                }
            }
        }

        public static void Pause(Transform transform)
        {
            for (int i = dotweenList.Count - 1; i >= 0; i--)
            {
                if (dotweenList[i].transform == transform)
                {
                    dotweenList[i].Pause();
                }
            }
        }

        public static void PauseAll()
        {
            for (int i = dotweenList.Count - 1; i >= 0; i--)
            {
                dotweenList[i].Pause();
            }
        }

        public static void Kill(string id)
        {
            for (int i = dotweenList.Count - 1; i >= 0; i--)
            {
                if (dotweenList[i].tid == id)
                {
                    dotweenList[i].Kill();
                }
            }
        }

        public static void Kill(Transform transform)
        {
            for (int i = dotweenList.Count - 1; i >= 0; i--)
            {
                if (dotweenList[i].transform == transform)
                {
                    dotweenList[i].Pause();
                }
            }
        }

        public static void KillAll()
        {
            for (int i = dotweenList.Count - 1; i >= 0; i--)
            {
                dotweenList[i].Kill();
            }
        }
    }
}

(三)Extension.cs:拓展方法类

​ 拓展方法类主要是通过C#的拓展方法机制,对MonoBehaviourTransform类拓展控制Tween对象的一系列方法。这样用户只需导入已定义的命名空间myTween就可以拓展这些类方法。

using System.Collections;
using UnityEngine;

namespace myTween {
    public static class Extension
    {
        //MonoBehaviour的DoMove方法拓展
        public static IEnumerator DoMove(this MonoBehaviour mono, Tween tween)
        {
            Vector3 speed = (tween.target - tween.transform.position) / tween.duration;
            for (float f = tween.duration; f >= 0.0f; f -= Time.deltaTime)
            {
                tween.transform.Translate(speed * Time.deltaTime);
                yield return null;
                while (tween.isPause == true)
                {
                    yield return null;
                }
            }
            tween.runOnComplete();
        }

        //Transform的DoMove方法拓展
        public static Tween DoMove(this Transform transform, Vector3 target, float duration)
        {
            MonoBehaviour mono = transform.GetComponents<MonoBehaviour>()[0];
            Tween tween = new Tween("DoMove",target, duration, transform,null);
            Coroutine coroutine = mono.StartCoroutine(mono.DoMove(tween));
            tween.setCoroutine(coroutine);
            return tween;
        }

        //MonoBehaviour的DoScale方法拓展
        public static IEnumerator DoScale(this MonoBehaviour mono, Tween tween)
        {
            Vector3 speed = (tween.target - tween.transform.localScale) / tween.duration;
            for (float f = tween.duration; f >= 0.0f; f -= Time.deltaTime)
            {
                tween.transform.localScale = tween.transform.localScale + speed * Time.deltaTime;
                yield return null;
                while (tween.isPause == true)
                {
                    yield return null;
                }
            }
            tween.runOnComplete();
        }

        //Transform的DoScale方法拓展
        public static Tween DoScale(this Transform transform, Vector3 target, float time)
        {
            MonoBehaviour mono = transform.GetComponents<MonoBehaviour>()[0];
            Tween tween = new Tween("DoScale", target, time, transform, null);
            Coroutine coroutine = mono.StartCoroutine(mono.DoScale(tween));
            tween.setCoroutine(coroutine);
            return tween;
        }
    }
}

(四)测试脚本及测试

写一个简单的插件测试脚本(注意导入命名空间),在unity中挂载到一个游戏对象中,就可以测试插件的运行情况了:

using UnityEngine;
using myTween;

public class DOTweenTest : MonoBehaviour {

    Tween tween;

    private void Start()
    {
        transform.DoMove(new Vector3(5f, 5f, 5f), 5f);
        transform.DoScale(new Vector3(5f, 5f, 5f), 5f);
    }
}

相关文章

  • Unity3d DoTween动画插件视频教程

    Unity3D动画插件里面(DOTween,HOTween,LeanTween,iTween)DOTween...

  • 【Unity3D开发】DOTween 插件仿写

    本文同时发布至我的个人博客,点击进入我的个人博客阅读。本博客供技术交流与经验分享,可自由转载。转载请在评论区或私信...

  • Unity3D实用插件

    DoTween当前效率最好的动画插件。http://dotween.demigiant.com/ Advanced...

  • Dotween插件的使用小结

    一.Dotween的使用DOTween插件一般与UGUI结合使用,做一些简单的动画。二.Dotween的核心表达式...

  • cocosCreator中的DOTween

    cocosCreater中的DOTween,之前用过unity中的插件DOTween,感觉真的好用。现在学习coc...

  • [Unity插件] Unity3D插件之DoTween

    官方下载地址:http://dotween.demigiant.com/download.php 1、把下载到压缩...

  • unity plugin

    Unity提高开发效率的插件集合 14个 Vectrosity:Unity3D中可以用Vectrosity插件画直...

  • 插件-DOTween

    简介 实例 写法 通用:DoTween.To(()=>value,x=>value=x,100,1) 简洁:tra...

  • DoTween插件

    1.命名前缀DO: 动作操作前缀。 例如:DoMove(),DoKill()等等。 Set:动画设置操作前缀。例如...

  • DoTween插件

    doteeen(hotween第二个版本) hotween leantween gokit itween(多个相同...

网友评论

  • 一个当年人:对的,有一个空指针的错误,已转载。
  • LoveWaits_9b9a:控制自身是没有问题的,但是要是用脚本控制别的物体,且物体上没有挂载任何继承MonoBehaviour 的组建就会报空,不知道是不是我哪里弄错了

本文标题:【Unity3D开发】DOTween 插件仿写

本文链接:https://www.haomeiwen.com/subject/udbdxxtx.html