Skip to content

Instantly share code, notes, and snippets.

@iwashihead
Created January 21, 2017 07:37
Show Gist options
  • Save iwashihead/9204fd3d5d51adff5dfc61b84f019a86 to your computer and use it in GitHub Desktop.
Save iwashihead/9204fd3d5d51adff5dfc61b84f019a86 to your computer and use it in GitHub Desktop.
汎用シェイク処理
using System;
using UnityEngine;
using Random = UnityEngine.Random;
namespace hoge
{
/// <summary>
/// シェイク処理
/// </summary>
public class Shaker : IDisposable
{
/// <summary>
/// シェイク構造体
/// </summary>
private struct ShakeParam
{
/// <summary>シェイク中かどうか</summary>
public bool IsShake;
/// <summary>減衰率</summary>
public EasingUtility.EasingType DecayType;
/// <summary>シェイクの開始時間</summary>
public float StartTime;
/// <summary>シェイクにかける時間</summary>
public float Duration;
/// <summary>シェイク量</summary>
public float RandomAmount;
}
/// <summary>
/// 2D用のシェイクかどうか.
/// Trueの場合、Zは変化せずXYのみ変化します.
/// </summary>
public bool Is2D { get; set; }
/// <summary>
/// ローカルポジションかどうか
/// </summary>
public bool IsLocal { get; set; }
/// <summary>
/// シェイクのターゲット
/// </summary>
public Transform Target { get; set; }
/// <summary>
/// シェイクパラメーター
/// </summary>
private ShakeParam _shakeParam = default(ShakeParam);
/// <summary>
/// ターゲットの初期位置
/// IsLocalがTrueならlocalPositionが、FalseならPositionが代入されます
/// </summary>
private Vector3 _initializePos = Vector3.zero;
#region Constractor
/// <summary>
/// 2D用コンストラクタ
/// </summary>
/// <param name="target"></param>
public Shaker(RectTransform target)
{
Is2D = true;
IsLocal = true;
Target = target;
_initializePos = IsLocal ? Target.localPosition : Target.position;
}
/// <summary>
/// 3D用コンストラクタ
/// </summary>
/// <param name="target"></param>
public Shaker(Transform target)
{
Is2D = false;
IsLocal = true;
Target = target;
_initializePos = IsLocal ? Target.localPosition : Target.position;
}
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="is2D"></param>
/// <param name="isLocal"></param>
/// <param name="target"></param>
public Shaker(bool is2D, bool isLocal, Transform target)
{
Is2D = is2D;
IsLocal = isLocal;
Target = target;
_initializePos = IsLocal ? Target.localPosition : Target.position;
}
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="is2D"></param>
/// <param name="isLocal"></param>
/// <param name="target"></param>
/// <param name="initialPos"></param>
public Shaker(bool is2D, bool isLocal, Transform target, Vector3 initialPos)
{
Is2D = is2D;
IsLocal = isLocal;
Target = target;
_initializePos = initialPos;
}
#endregion
#region IDisposable
/// <summary>
/// 破棄処理
/// </summary>
public void Dispose()
{
Memory.Delete(ref _shakeParam);
Memory.Delete(ref _initializePos);
Memory.Delete(Target);
}
#endregion
#region Public Method
/// <summary>
/// シェイクを開始します
/// </summary>
/// <param name="duration">シェイクさせる時間</param>
/// <param name="amount">シェイク量(この値からランダムにシェイクします)</param>
/// <param name="decayType">シェイク量の減衰タイプ</param>
public void SetShake(float duration, float amount, EasingUtility.EasingType decayType = EasingUtility.EasingType.Linear)
{
_shakeParam = new ShakeParam()
{
IsShake = true, //Shake開始
StartTime = Time.time,
Duration = duration,
RandomAmount = amount
};
}
/// <summary>
/// シェイクを中止します
/// </summary>
public void CancelShake()
{
_shakeParam.IsShake = false;
if (IsLocal)
{
Target.localPosition = _initializePos;
}
else
{
Target.position = _initializePos;
}
}
/// <summary>
/// シェイクの更新を行います
/// MonoのUpdate、もしくはLateUpdateでよびだしてください
/// </summary>
public void UpdateShake()
{
if (Target == null) return;
if (_shakeParam.IsShake == false) return;
var elapsedTime = Time.time - _shakeParam.StartTime;
if (elapsedTime >= _shakeParam.Duration)
{
// Shake終了.
_shakeParam.IsShake = false;
if (IsLocal)
{
Target.localPosition = _initializePos;
}
else
{
Target.position = _initializePos;
}
}
else
{
/* Shake量の計算 */
// 経過時間から進捗率を0~1で計算.
var progress = Mathf.Clamp01(elapsedTime / _shakeParam.Duration);
// 進捗率にイージングを加味したシェイクの減衰率を計算.
var decayRate = EasingUtility.GetEasingFunc(EasingUtility.EasingType.EaseInCubic)(1f, 0f, progress);
// 減衰率を加味したシェイク量をランダムで取得.
Vector3 shakeAmount;
if (Is2D)
{
shakeAmount = Random.insideUnitCircle * _shakeParam.RandomAmount * decayRate;
}
else
{
shakeAmount = Random.insideUnitSphere * _shakeParam.RandomAmount * decayRate;
}
// シェイクの実行
if (IsLocal)
{
Target.localPosition = _initializePos + shakeAmount;
}
else
{
Target.position = _initializePos + shakeAmount;
}
}
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment