一直没有用过NGUI动画的功能,之前的理解就是:设置始末两个“位置”,然后就是从起始位置移到结束位置。至于中间是怎么变化的,就感觉很神奇了,变化率怎么设置才不会看起来很“傻”,这里不是看“郭靖”,动画一定要有惊奇,摸不着猜不透的感觉。对NGUI主要的几个脚本都已经有点掌握了(猛点查看),一直都没有去”膜拜“Tweening文件夹的各个大神,可能以前会觉得不就是一个动画组件,自己都可以实现。但是看过里面的代码就后悔了,因为至少结合TweenFOV和TweenOrhoSize这两个脚本就可以实现很多效果,竟然轻而易举的集成了,看来人还是不要太看得起自己的好,这样才会走的更快更远。
每次都觉得前面吹水很写,也写不好(一直都有感觉自己的写作水平太差了),那就来看下Tweening文件夹下到底卖的是什么药——UITweener和它的“孩子”:
UITweener的Fields
看着很复杂,其实只要把UITweener琢磨透了,其它都只是重写UITweener的OnUpdate方法和封装了Begin方法。还是先看下主要的Field(作用看注释):
bool mStarted = false; //是否开始动画 float mStartTime = 0f; //动画开始播放的时间, mStarted =true;mStartTime = time + delay; float mDuration = 0f; //动画长度(时间) float mAmountPerDelta = 1000f; //单位时间动画播放的长度,有点帧率的感觉 float mFactor = 0f; //当前动画播放的进度 /// <summary> /// Amount advanced per delta time. /// </summary> public float amountPerDelta { get { if (mDuration != duration) { mDuration = duration; mAmountPerDelta = Mathf.Abs((duration > 0f) ? 1f / duration : 1000f); } return mAmountPerDelta; } }
通过Begin设置需要的参数:
static public T Begin<T> (GameObject go, float duration) where T : UITweener { T comp = go.GetComponent<T>(); #if UNITY_FLASH if ((object)comp == null) comp = (T)go.AddComponent<T>(); #else if (comp == null) comp = go.AddComponent<T>(); #endif comp.mStarted = false; comp.duration = duration; comp.mFactor = 0f; comp.mAmountPerDelta = Mathf.Abs(comp.mAmountPerDelta); comp.style = Style.Once; comp.animationCurve = new AnimationCurve(new Keyframe(0f, 0f, 0f, 1f), new Keyframe(1f, 1f, 1f, 0f)); comp.eventReceiver = null; comp.callWhenFinished = null; comp.enabled = true; return comp; }
Update函数
然后再Update函数先计算出时间delta,进一步计算出当前动画播放的mFactor,然后进行Sample采用,执行OnUpdate:
void Update () { float delta = ignoreTimeScale ? RealTime.deltaTime : Time.deltaTime; float time = ignoreTimeScale ? RealTime.time : Time.time; if (!mStarted) { mStarted = true; mStartTime = time + delay; } if (time < mStartTime) return; // Advance the sampling factor mFactor += amountPerDelta * delta; // Loop style simply resets the play factor after it exceeds 1. if (style == Style.Loop) { if (mFactor > 1f) { mFactor -= Mathf.Floor(mFactor); } } else if (style == Style.PingPong) { // Ping-pong style reverses the direction if (mFactor > 1f) { mFactor = 1f - (mFactor - Mathf.Floor(mFactor)); mAmountPerDelta = -mAmountPerDelta; } else if (mFactor < 0f) { mFactor = -mFactor; mFactor -= Mathf.Floor(mFactor); mAmountPerDelta = -mAmountPerDelta; } } // If the factor goes out of range and this is a one-time tweening operation, disable the script if ((style == Style.Once) && (mFactor > 1f || mFactor < 0f)) { mFactor = Mathf.Clamp01(mFactor); Sample(mFactor, true); current = this; // Notify the listener delegates EventDelegate.Execute(onFinished); // Deprecated legacy functionality support if (eventReceiver != null && !string.IsNullOrEmpty(callWhenFinished)) eventReceiver.SendMessage(callWhenFinished, this, SendMessageOptions.DontRequireReceiver); current = null; // Disable this script unless the function calls above changed something if (mFactor == 1f && mAmountPerDelta > 0f || mFactor == 0f && mAmountPerDelta < 0f) enabled = false; } else Sample(mFactor, false); }
Sample采样函数
前面说的动画要有摸不着猜不透的感觉,就是要考Sample的采样函数来实现的,UITweener支持5种动画曲线:
public enum Method { Linear, EaseIn, EaseOut, EaseInOut, BounceIn, BounceOut, }
采样的函数,原理很简单:根据当前播放的进度mFactor,计算出实际的动画播放刻度,然后执行OnUpdate操作:
public void Sample (float factor, bool isFinished) { // Calculate the sampling value float val = Mathf.Clamp01(factor); if (method == Method.EaseIn) { val = 1f - Mathf.Sin(0.5f * Mathf.PI * (1f - val)); if (steeperCurves) val *= val; } else if (method == Method.EaseOut) { val = Mathf.Sin(0.5f * Mathf.PI * val); if (steeperCurves) { val = 1f - val; val = 1f - val * val; } } else if (method == Method.EaseInOut) { const float pi2 = Mathf.PI * 2f; val = val - Mathf.Sin(val * pi2) / pi2; if (steeperCurves) { val = val * 2f - 1f; float sign = Mathf.Sign(val); val = 1f - Mathf.Abs(val); val = 1f - val * val; val = sign * val * 0.5f + 0.5f; } } else if (method == Method.BounceIn) { val = BounceLogic(val); } else if (method == Method.BounceOut) { val = 1f - BounceLogic(1f - val); } // Call the virtual update OnUpdate((animationCurve != null) ? animationCurve.Evaluate(val) : val, isFinished); }
缓动函数(easing fuction)
上面说的动画曲线,中文叫缓动函数(曲线):
通过上面这张图可以很感性的认识不同函数的具体的效果,也可以自己尝试推导一边加深理解,不过D.S.Qiu已经有点“廉颇老矣”,凭着记忆“奇变偶不变,符号看象限”,慢的只能到easeInSine,要想详细了解可以参考②和③。
妙用mAmountPerDelta
mAmountPerDelta就是动画播放速度,只对mAmountPerData就可以有更多控制:Toggle,PlayForward,PlayResverse:
/// <summary> /// Manually activate the tweening process, reversing it if necessary. /// </summary> public void Play (bool forward) { mAmountPerDelta = Mathf.Abs(amountPerDelta); if (!forward) mAmountPerDelta = -mAmountPerDelta; enabled = true; Update(); } /// <summary> /// Manually start the tweening process, reversing its direction. /// </summary> public void Toggle () { if (mFactor > 0f) { mAmountPerDelta = -amountPerDelta; } else { mAmountPerDelta = Mathf.Abs(amountPerDelta); } enabled = true; }
『Bug修复和吐槽
之前用TweenRotation这个脚本,做游戏等待转圈等待界面,发现总是不能旋转360度,总是一个小于180的角度,无论from和to如何设置:
public Vector3 from; public Vector3 to;
后来无奈之下,只好去看下TweenRotation的OnUpdate函数,发现使用的是 Quaternion.Slerp这个函数,发现确实是这样,所以就做了下面的修改:
protected override void OnUpdate (float factor, bool isFinished) { //cachedTransform.localRotation = Quaternion.Slerp(Quaternion.Euler(from), Quaternion.Euler(to), factor); //NGUI的实现是上一行,有Bug,不能达到要求 cachedTransform.localEulerAngles = Vector3.Lerp(from, to, factor); }
NGUI提供了UIPlayTween,这个脚本管理一组Tween脚本的Play,提供了不同的Tirgger,然后在不同的事件函数中触发Play(true):
void OnClick () { if (enabled && trigger == Trigger.OnClick) { Play(true); } }
虽然UIPlayTween提供了很多参数都是没有满足要其交替地进行PlayForward和PlayReverse,因为其都是执行Play(true),开始的时候我想到了给其中一个UITween添加OnFinished委托,在播放结束的时候改变playDiretion的方向:
public Direction playDirection = Direction.Forward;
但是这个控制因为动画是有时间的,会有问题。所以我只能添加一个Trigger的类型:Trigger.None,然后自己去调用,就是自己管理动画的播放,而不是在OnClick中触发。』
增补于 2013,12,23 21:50
小结:
确实很简单,主要是对缓动函数的理解,有了这些基础可以做的事情(特效和动画)就很多了——屏幕抖动和刀光剑影(下次自己动手尝试下,哈哈),NGUI的ButtonScale等脚本也是通过UITweener来完成的。但是收获蛮多的,又一点多了,晚安!
如果您对D.S.Qiu有任何建议或意见可以在文章后面评论,或者发邮件(gd.s.qiu@gmail.com)交流,您的鼓励和支持是我前进的动力,希望能有更多更好的分享。
转载请在文首注明出处:http://dsqiu.iteye.com/blog/1974528
更多精彩请关注D.S.Qiu的博客和微博(ID:静水逐风)
参考:
①NGUI: Next-Gen UI kit 3.0.0:http://www.tasharen.com/ngui/docs/class_u_i_tweener.html
② 缓动函数:http://easings.net/zh-cn
③Easing Equations by Robbert Penner: http://www.gizma.com/easing/#sin2
④Unity3dPack: http://www.unity3dpack.com/?p=300
相关推荐
在场景视图中看到的就是在游戏视图中得到的(所见即所得)。 基于组件的、模块化的特性:要让你的界面控件做什么,只需为其附加相应的行为,而不需要编码。 全面支持iOS/Android和Flash。 灵活的事件系统。 可以让...
在场景视图中看到的就是在游戏视图中得到的(所见即所得)。 基于组件的、模块化的特性:要让你的界面控件做什么,只需为其附加相应的行为,而不需要编码。 全面支持iOS/Android和Flash。 灵活的事件系统。 可以让...
在场景视图中看到的就是在游戏视图中得到的(所见即所得)。 基于组件的、模块化的特性:要让你的界面控件做什么,只需为其附加相应的行为,而不需要编码。 全面支持iOS/Android和Flash。 灵活的事件系统。 可以让...
开发者可以在Unity编辑器中直接设计和调整UI元素,实现所见即所得的效果。这种设计方式极大地提高了开发效率,使得UI设计和游戏逻辑的开发可以同步进行,减少了开发者在不同工具间切换的时间成本。 二、本地化与...
使用unity原生GUI封装,来达到UGUI,NGUI所见即所得的效果和部分功能,目的是由此来了解高级UI的原理。
- 编辑器集成,所见即所得 - 本地化、数据绑定、委托、事件 - 支持所有平台 - 制作进行 1 次绘制调用的 UI - 随附完整的 C# 源代码 - 已广泛优化 - 专门团队支持 2020.1.5 - NEW: You can now specify per-symbol ...
在场景视图中看到的就是在游戏视图中得到的(所见即所得)。 基于组件的、模块化的特性:要让你的界面控件做什么,只需为其附加相应的行为,而不需要编码。 全面支持iOS/Android和Flash。 灵活的事件系统。 可以让...
《NGUI 3.6.4:打造高效Unity3D移动界面的利器》 NGUI,全称为Next-Gen UI,是Unity3D游戏引擎中的一款广泛应用的界面系统插件,尤其在移动游戏开发领域备受青睐。其3.6.4版本作为官方发布的最新版,不仅集成了之前...
在场景视图中看到的就是在游戏视图中得到的(所见即所得)。 基于组件的、模块化的特性:要让你的界面控件做什么,只需为其附加相应的行为,而不需要编码。 全面支持iOS/Android和Flash。 灵活的事件系统。...
NGUI Next-Gen UI是一款功能强大、灵活性高的UI插件,是当前最新版本的NGUI插件。它可以覆盖Unity的多个版本,包括Unity 5、Unity 2017和Unity 2018等。与其他UI插件相比,NGUI Next-Gen UI具有高效的性能和优秀的...
NGUI3.7.3unitypackage 是 NGUI 的一个特定版本,即3.7.3版的资源包。这个版本包含了对 NGUI 系统的更新和改进,旨在提升性能、优化用户体验以及增加新的功能。 NGUI 的核心特性包括: 1. **Widget 系统**:NGUI ...
NGUI 是一款非常强大的 UI 系统和事件通知框架。...- 编辑器集成,所见即所得 - 本地化、数据绑定、委托、事件 - 支持所有平台 - 制作进行 1 次绘制调用的 UI - 随附完整的 C# 源代码 - 已广泛优化 - 专门团队支持
在场景视图中看到的就是在游戏视图中得到的(所见即所得)。 基于组件的、模块化的特性:要让你的界面控件做什么,只需为其附加相应的行为,而不需要编码。 全面支持iOS/Android和Flash。 灵活的事件系统。...
《NGUI v3.12.1:2018年Unity UI系统深度解析》 NGUI,全称为Next-Gen UI,是一款专为Unity引擎设计的用户界面系统。在2018年,它发布了v3.12.1的最新版本,此更新旨在优化用户体验,提升性能,并增加新功能。作为...
NGUI 是一个针对 Unity 游戏引擎的用户界面(UI)系统,专为游戏开发者设计,提供了一套高效、易用且功能丰富的UI组件。在3.11.2版本中,NGUI 进一步提升了性能和用户体验,遵循了“Keep It Simple, Stupid”(KISS...
《NGUI 3.7.0:Unity开发插件的深度解析与应用指南》 NGUI,全称为Next-Gen User Interface,是一款专为Unity3D游戏引擎设计的UI开发插件,它提供了丰富的界面元素和强大的交互功能,极大地简化了开发者在创建用户...
本包中共有六个版本的NGUI,大家可以自己选择版本。 NGUI Next-Gen UI 3.6.0.unitypackage NGUI Next-Gen UI 3.12.1(u5.6.5).unitypackage NGUI Next-Gen UI 2019.3.0.unitypackage NGUI Next-Gen UI v2018.3.0....
NGUI离线文档是针对Unity游戏开发中NGUI框架的一个详细参考资料,主要基于3.7.5版本。NGUI是一个用户界面系统,专为Unity3D设计,它提供了丰富的UI组件和工具,使得开发者能够在2D和3D环境中创建出交互性强、视觉...
《NGUI在Unity中的应用详解》 Unity,作为全球领先的实时3D内容创作和运营平台,深受游戏开发者和视觉效果创作者的喜爱。而NGUI(Next Generation User Interface)是Unity早期流行的一款用户界面(UI)系统插件,...