Skip to content

Instantly share code, notes, and snippets.

@iwashihead
Created October 20, 2017 01:23
Show Gist options
  • Save iwashihead/83c881a6aff35ca5dbcbdb2af6a6e324 to your computer and use it in GitHub Desktop.
Save iwashihead/83c881a6aff35ca5dbcbdb2af6a6e324 to your computer and use it in GitHub Desktop.
UnityEngine.UI.Textにアタッチして文字を個別に動かすアニメーションのサンプル。
//-------------------------------------------------------
// @file CommonTextAnimation.cs
// @brief IMeshModifierを利用したテキストアニメーション.
//
// @author haruki.tachihara
//-------------------------------------------------------
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
//これは別UnityEngine名前空間を使ってはいるが自前のTweenライブラリ
using Method = UnityEngine.UI.TweenMain.Method;
namespace UnityEngine.UI
{
[RequireComponent(typeof(Text))]
[DisallowMultipleComponent]
public class CommonTextAnimation : BaseMeshEffect
{
// 1文字は6頂点.
const int CHAR_VERT_CNT = 6;
#region Animation Parameter
// OnEnableで自動開始するか.
public bool autoStartOnEnable = true;
// アニメーションにかける所用時間 [秒]
public float duration = 0.5f;
// X軸の動きの大きさ.
public float moveAmountX = 0f;
// Y軸の動きの大きさ.
public float moveAmountY = 0f;
// シェイクは有効か.
public bool enableShake = true;
// シェイク量.
public float shakeAmount = 1f;
#endregion
private bool isFinished;
private float time;
public void StartEffect()
{
time = 0;
isFinished = false;
}
protected override void OnEnable()
{
base.OnEnable();
if (autoStartOnEnable)
{
StartEffect();
}
}
protected virtual void Update()
{
if (isFinished)
return;
time += Time.deltaTime;
if (graphic != null)
{
graphic.SetVerticesDirty();
}
}
public override void ModifyMesh(VertexHelper vh)
{
var vList = new List<UIVertex>();
vh.GetUIVertexStream(vList);
Modify(ref vList);
vh.Clear();
vh.AddUIVertexTriangleStream(vList);
}
void Modify(ref List<UIVertex> vList)
{
if (isFinished || duration <= 0f || vList.Count < CHAR_VERT_CNT)
{
return;
}
if (time >= duration && !enableShake)
{
isFinished = true;
}
var vertexCount = vList.Count;
var charCount = vertexCount / CHAR_VERT_CNT;
var deltaTimeParChar = duration / charCount;
Vector3 shake = Vector3.zero;
if (enableShake)
{
shake = Random.insideUnitCircle * shakeAmount;
}
for (int i = 0; i < vertexCount; i += CHAR_VERT_CNT)
{
// 現在の文字のnormalizeTime[0-1]を計算.
var startTime = i / CHAR_VERT_CNT * deltaTimeParChar;
var elapsedTime = time - startTime;
var normalizeTime = Mathf.Clamp01(elapsedTime / deltaTimeParChar);
if (normalizeTime <= 0f)
{
// 見えないように設定.
for (int vertexIndex = 0; vertexIndex < CHAR_VERT_CNT; vertexIndex++)
{
var v = vList[i + vertexIndex];
v.color = Color.clear;
vList[i + vertexIndex] = v;
}
}
else if (normalizeTime >= 1f)
{
if (enableShake)
{
for (int vertexIndex = 0; vertexIndex < CHAR_VERT_CNT; vertexIndex++)
{
var v = vList[i + vertexIndex];
v.position += shake;
vList[i + vertexIndex] = v;
}
}
}
else
{
// アニメーションさせる.
var center = Vector2.Lerp(vList[i].position, vList[i + 3].position, 0.5f);
for (int vertexIndex = 0; vertexIndex < CHAR_VERT_CNT; vertexIndex++)
{
var v = vList[i + vertexIndex];
var sampled = Tweening.Sample(Method.EaseOut, normalizeTime);
// 移動量
var moveX = moveAmountX * Tweening.Sample(Method.EaseIn, 1f - normalizeTime);
var moveY = moveAmountY * Mathf.Sin((1f - normalizeTime) * Mathf.PI);//上下にサインカーブ移動.
// スケール
var posX = Mathf.Lerp(center.x, v.position.x, sampled) + moveX;
var posY = Mathf.Lerp(center.y, v.position.y, sampled) + moveY;
v.position = new Vector2(posX + shake.x, posY + shake.y);
vList[i + vertexIndex] = v;
}
}
}
}
}
public static class Tweening
{
public static float Sample(Method method, float normalizeTime)
{
float val = Mathf.Clamp01(normalizeTime);
switch (method)
{
case Method.Linear:
val = Easing.Linear(val);
break;
case Method.EaseIn:
val = Easing.Sinusoidal.In(val);
break;
case Method.EaseOut:
val = Easing.Sinusoidal.Out(val);
break;
case Method.EaseInOut:
val = Easing.Sinusoidal.InOut(val);
break;
case Method.BounceIn:
val = Easing.Bounce.In(val);
break;
case Method.BounceOut:
val = Easing.Bounce.Out(val);
break;
case Method.BounceInOut:
val = Easing.Bounce.InOut(val);
break;
}
return val;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment