需要实现一些 UI 动画效果(比如动态弹出),可以利用多态来完成。
下面定义一个基类 Actions,继承自 MonoBehaviour,封装了动画的生命周期:进入(OnEnter)、每帧更新(UpdateMS)和退出(OnExit)。动画在 MAX_TIME 秒后自动销毁,并触发回调 OnComptele。
/*
* Author: caoshanshan
* Email: me@dreamyouxi.com
*/
using UnityEngine;
using System.Collections;
public class Actions : MonoBehaviour
{
public virtual void UpdateMS()
{
}
public virtual void OnExit()
{
}
public virtual void OnEnter()
{
}
void Start()
{
this.OnEnter();
}
void Update()
{
current_time += Time.deltaTime;
this.UpdateMS();
if (current_time > MAX_TIME)
{
this.Dispose();
}
}
public void Dispose()
{
this.OnExit();
if (OnComptele != null) OnComptele();
GameObject.Destroy(this as Component);
}
public float current_time = 0.0f;
public float MAX_TIME = 1.0f;
public VoidFuncVoid OnComptele = null;
}
public class ScaleTo : Actions
{
public float start_x = 0.0f;
public float end_x = 0.0f;
public float current_x = 0.0f;
public float start_y = 0.0f;
public float end_y = 0.0f;
public float current_y = 0.0f;
public override void UpdateMS()
{
current_x = (end_x - start_x) * (current_time) / MAX_TIME + start_x;
current_y = (end_y - start_y) * (current_time) / MAX_TIME + start_y;
this.transform.localScale = (new Vector3(current_x, current_y, 1.0f));
}
public static Actions Create(GameObject target, float time, float x, float y)
{
ScaleTo action = target.AddComponent<ScaleTo>();
action.MAX_TIME = time;
action.end_x = x;
action.end_y = y;
return action;
}
public static Actions Create(GameObject target, float time, float xy)
{
return Create(target, time, xy, xy);
}
public override void OnExit()
{
//修正
this.transform.localScale = (new Vector3(end_x, end_y, 1.0f));
}
public override void OnEnter()
{
start_x = this.transform.localScale.x;
start_y = this.transform.localScale.y;
}
}
public class ScaleBy : ScaleTo
{
public static Actions Create(GameObject target, float time, float x, float y)
{
ScaleBy action = target.AddComponent<ScaleBy>();
action.MAX_TIME = time;
action.end_x = x; action.end_y = y;
return action;
}
public static Actions Create(GameObject target, float time, float xy)
{
return Create(target, time, xy, xy);
}
public override void OnEnter()
{
base.OnEnter();
end_x += start_x;
end_y += start_y;
}
}
使用示例
以弹出式对话框为例,通过链式调用 ScaleTo.Create 实现带回弹感的弹出动画:先缩小到 0.7,再依次经过 0.9、1.2,最终收敛到 1.0。
protected void PopIn()
{
this.panel.SetActive(true);
ScaleTo.Create(this.panel, 0.05f, 0.7f, 0.7f).OnComptele = () =>
{
ScaleTo.Create(this.panel, 0.01f, 0.9f, 0.9f).OnComptele = () =>
{
ScaleTo.Create(this.panel, 0.01f, 1.2f, 1.2f).OnComptele = () =>
{
ScaleTo.Create(this.panel, 0.03f, 1f, 1f).OnComptele = () =>
{
};
};
};
};
}