筆者覺得一個好緩動效果的使用墨缘,往往會讓人覺得這個游戲對象瞬間活潑起來就像有了生命一般星虹,Easing 就是這般神奇。在本文镊讼,筆者帶大家寫一個具有緩動效果的 PingPong 動效宽涌。
EasingCore
巧婦難為無米之炊,我們要先整理一些 Ease 算法先蝶棋,沒想人家早早的就整理了一份放到 GitHub 上咯~(其實 Itween里面也有一套 Ease 算法哈)
EasingCore-GitHub
怎么用 EasingCore:
怎么用EasingCore卸亮,超簡單:
float value = EasingFunction.Get(easetype).Invoke(progress);
這樣獲得的值就是被算法修正的值啦。
PingPong
用上了這個EasingCore 的 PingPong動效模塊玩裙,:
using EasingCore;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using zFrame.Extend;
using Ease = EasingCore.Ease;
public class PingPong : MonoBehaviour
{
#region SelfField
float progress = 0;
bool addition = true;
private CoroutineHandler coroutine;
#endregion
#region Configration Parameter
private event Action<float> action;
private Ease ease = Ease.Linear;
private float delay = 0;
#endregion
#region 單例
static PingPong driver;
static PingPong Driver
{
get
{
if (null == driver)
{
GameObject go = new GameObject("[PingPongDriver]");
driver = go.AddComponent<PingPong>();
GameObject.DontDestroyOnLoad(go);
go.hideFlags = HideFlags.HideAndDontSave;
}
return driver;
}
}
private void Awake()
{
driver = this;
}
#endregion
#region PingPongBehaviours
public static PingPong OnUpdate(Action<float> action)
{
if (null == Driver.action)
{
Driver.action = action;
}
else
{
List<Delegate> list = new List<Delegate>(Driver.action.GetInvocationList());
if (!list.Contains(action))
{
Driver.action += action;
}
}
return Driver;
}
public PingPong SetEase(Ease ease)
{
this.ease = ease;
return Driver;
}
public PingPong SetDelay(float delay)
{
this.delay = delay;
return Driver;
}
public void Play()
{
if (null == coroutine)
{
coroutine = Handler().Start();
}
}
private void Finish()
{
coroutine.Stop();
coroutine = null;
action = null;
}
public static void Stop()
{
Driver.Finish();
}
#endregion
IEnumerator Handler()
{
yield return new WaitForSeconds(delay);
while (true)
{
progress += (addition ? 1 : -1) * Time.deltaTime ;
progress = Mathf.Clamp01(progress);
addition = progress == 1 ? false : progress == 0 ? true : addition;
float value = EasingFunction.Get(ease).Invoke(progress);
action?.Invoke(value);
yield return 0;
}
}
}
這個實現(xiàn)比較無聊嫡良,僅僅是做的好玩,所以居然使用了單例献酗,哈哈寝受。
然后,使用了鏈式編程風格以配置參數(shù):
怎么使用:
演示代碼罕偎,應該沒有什么復雜需要特別注解的地方了
using UnityEngine;
public class TestBreath : MonoBehaviour
{
public EasingCore.Ease ease = EasingCore.Ease.InExpo;
public Transform endPoint;
public float delay = 2;
public float factor = 0.5f;
Vector3 v3; //緩存起點
Vector3 ve; //終點
void Start()
{
v3 = transform.position;
Play();
}
[EditorButton]
public void Restart()
{
PingPong.Stop();
transform.position = v3;
Play();
}
private void Play()
{
ve = endPoint.position;
Vector3 dr = ve - v3; //獲得起點指向終點的向量
float dis = Vector3.Distance(v3, ve); //獲得向量距離很澄,
PingPong.OnUpdate(v =>
{
Vector3? pos = v3 + dr.normalized * dis * v; // 使用可空值接這個數(shù)據(jù)
transform.position = pos.HasValue ? pos.Value : transform.position;
}).SetEase(ease) //設置 Ease 模式
.SetDelay(delay) //設置延時多久后播放動畫
.SetFactor(factor) //等效于設置動畫時長
.Play();
}
}
動畫演示:
Pingpong + EasingCore
總共有30個緩動,動畫中幾個動效為隨機測試颜及。
擴展閱讀:
Unity EditorButton - GitHub
[Unity3D] 協(xié)程管理CoroutineManager - 簡書
[Unity 3d] 如何優(yōu)雅的寫一個PingPong效果 - 簡書