5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

HeliScriptで出来る!"演出で一気に垢ぬける方法"

Last updated at Posted at 2025-12-08

イージングとは

イージングは“動きの緩急”を制御するための仕組みです。
プログラムでありがちな「線形で固い動き」を、自然で気持ちよい動きへと変えてくれます。

ゲーム開発ではもちろん、動画・UI・Webアニメーションなど、幅広い分野で利用されています。
Unityだと DoTween が有名ですね。

開発でイージングと言えばこのサイト!

長年愛用しているサイトはこちら:

イージングがグラフとプレビュー付きで30種類用意されている上に、
CSS / TypeScript のサンプルコード付きなので、そのまま開発に転用できる超優秀サイト。

スクリーンショット 2025-12-05 154249.png


百聞は一見に如かず。

上記チートシートに掲載されているすべてのイージング関数を
HeliScript に移植して確認できるようにしました!
ぜひワールドに入って色んなイージングを試してみてください。

明日から使える!HeliScriptイージングアニメーションワールド

!!!全イージング移植したHeliScriptコードはコチラ!!!
// 参考サイト https://easings.net/ja#
class Easing
{
   public float easeInSine(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return 1 - hsMathCos((_time * PI) / 2);
   }

   public float easeInCubic(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return _time * _time * _time;
   }

   public float easeInQuint(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return _time * _time * _time * _time * _time;
   }

   public float easeInCirc(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return 1 - hsMathSqrt(1 - MathPow(_time, 2));
   }

   public float easeInElastic(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float c4 = (2 * PI) / 3;
       float val = 0;

       if(_time == 0 ){
           val = 0;
       }
       else if(_time == 1 ){
           val = 1;
       }
       else {
           val = -MathPow(2, 10 * _time - 10) * hsMathSin((_time * 10 - 10.75) * c4);
       }

       return val;
   }

   public float easeOutSine(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return hsMathSin((_time * PI) / 2);
   }

   public float easeOutCubic(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return 1 - MathPow(1 - _time, 3);
   }

   public float easeOutQuint(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return 1 - MathPow(1 - _time, 5);
   }

   public float easeOutCirc(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return hsMathSqrt(1 - MathPow(_time - 1, 2));
   }

   public float easeOutElastic(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float c4 = (2 * PI) / 3;
       float val = 0;

       if(_time == 0 ){
           val = 0;
       }
       else if(_time == 1 ){
           val = 1;
       }
       else {
           val = MathPow(2, -10 * _time) * hsMathSin((_time * 10 - 0.75) * c4) + 1;
       }

       return val;
   }

   public float easeInOutSine(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return -( hsMathCos(PI * _time) - 1) / 2;
   }

   public float easeInOutCubic(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float val = 0;

       if(_time < 0.5 ){
            val = 4 * _time * _time * _time;
       }
       else {
           val = 1 - MathPow(-2 * _time + 2, 3) / 2;
       }

       return val;
   }

   public float easeInOutQuint(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float val = 0;

       if(_time < 0.5 ){
            val = 16 * _time * _time * _time * _time * _time;
       }
       else {
           val =  1 - MathPow(-2 * _time + 2, 5) / 2;
       }

       return val;
   }

   public float easeInOutCirc(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float val = 0;

       if(_time < 0.5 ){
           val = (1 -hsMathSqrt(1 - MathPow(2 * _time, 2))) / 2;
       }
       else {
           val = (hsMathSqrt(1 - MathPow(-2 * _time + 2, 2)) + 1) / 2;
       }

       return val;
   }

   public float easeInOutElastic(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float c5 = (2 * PI) / 4.5;
       float val = 0;

       val = (MathPow(2, -20 * _time + 10) * hsMathSin((20 * _time - 11.125) * c5)) / 2 + 1;

       if(_time < 0.5 ){
            val = -(MathPow(2, 20 * _time - 10) * hsMathSin((20 * _time - 11.125) * c5)) / 2;
       }
       if(_time == 0 ){ val = 0; }
       if(_time == 1 ){ val = 1; }

       return val;
   }

   public float easeInQuad(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return _time * _time;
   }

   public float easeInQuart(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return _time * _time * _time * _time;
   }

   public float easeInExpo(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float val = 0;

       if(_time == 0 ){
           val = 0;
       }
       else {
           val = MathPow(2, 10 * _time - 10);
       }

       return val;
   }

   public float easeInBack(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float c1 = 1.70158;
       float c3 = c1 + 1;

       return c3 * _time * _time * _time - c1 * _time * _time;
   }


   public float easeInBounce(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return 1 - easeOutBounce(1 - _time);
   }

   public float easeOutQuad(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return 1 - (1 - _time) * (1 - _time);
   }

   public float easeOutQuart(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       return 1 - MathPow(1 - _time, 4);
   }

   public float easeOutExpo(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float val = 0;

       if(_time == 1 ){
           val = 1;
       }
       else {
           val = 1 - MathPow(2, -10 * _time);
       }

       return val;
   }

   public float easeOutBack(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float c1 = 1.70158;
       float c3 = c1 + 1;

       return 1 + c3 * MathPow(_time - 1, 3) + c1 * MathPow(_time - 1, 2);
   }

   public float easeOutBounce(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       
       float n1 = 7.5625;
       float d1 = 2.75;
       float val = 0;

       if (_time < 1 / d1) {
           val = n1 * _time * _time;
       }
       else if (_time < 2 / d1) {
           val = n1 * (_time -= 1.5 / d1) * _time + 0.75;
       }
       else if(_time < 2.5 / d1){
           val = n1 * (_time -= 2.25 / d1) * _time + 0.9375;
       }
       else {
           val = n1 * (_time -= 2.625 / d1) * _time + 0.984375;
       }

       return val;
   }

   public float easeInOutQuad(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float val = 0;

       if(_time < 0.5){
           val = 2 * _time * _time;
       }
       else {
           val = 1 - MathPow(-2 * _time + 2, 2) / 2;
       }

       return val;
   }

   public float easeInOutQuart(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float val = 0;

       if(_time < 0.5){
           val = 8 * _time * _time * _time * _time;
       }
       else {
           val = 1 - MathPow(-2 * _time + 2, 4) / 2;
       }

       return val;
   }

   public float easeInOutExpo(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float val = 0;

       if(_time == 0 ){
           val = 0;
       }
       else if(_time == 1 ){
           val = 1;
       }
       else if(_time < 0.5){
           val = MathPow(2, 20 * _time - 10) / 2;
       }
       else {
           val = (2 - MathPow(2, -20 * _time + 10)) / 2;
       }

       return val;
   }


   public float easeInOutBack(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float c1 = 1.70158;
       float c2 = c1 * 1.525;

       float val = (MathPow(2 * _time - 2, 2) * ((c2 + 1) * (_time * 2 - 2) + c2) + 2) / 2;

       if(_time < 0.5){
           val = (MathPow(2 * _time, 2) * ((c2 + 1) * 2 * _time - c2)) / 2;
       }

       return val;
   }

   public float easeInOutBounce(float _time){
       _time = hsMathMax(0, hsMathMin(1, _time));
       float val = (1 + easeOutBounce(2 * _time - 1)) / 2;

       if(_time < 0.5){
           val = (1 - easeOutBounce(1 - 2 * _time)) / 2;
       }

       return val;
   }

   private float MathPow(float _base, int _exponent){
       // 指数が0の場合
       if(_exponent == 0){
           return 1;
       }

       // 負の指数の場合 (例: 2^-2 = 1/(2^2))
       if(_exponent < 0){
           return 1.0 / MathPow(_base, -_exponent);
       }

       // 正の整数指数の場合
       float result = 1;
       int i;
       for(i = 0; i < _exponent; i++){
           result *= _base;
       }

       return result;
   }
}

(プレビュー)
image.png


コピペで動く! シンプルなイージングアニメーション

HeliScript でイージングを適用する最も基本的な例として、
「オブジェクトがスケールしながら出現するアニメーション」を実装したクラスです。

// シンプルなイージングアニメーションクラス
component SampleEase
{
    // アニメの進行スピードを調整する値
    // 値が大きいほど速くアニメーションが終了します
    const float EASE_SPEED = 2;
    
    Item selfObj;
    float timeCounter;
    bool isFinished;
    
    // 初期化
    public SampleEase(){
        this.selfObj = hsItemGetSelf();
        this.timeCounter = 0;
        this.isFinished = false;
        
        // 開始位置とサイズを設定
        this.selfObj.SetPos(new Vector3(-14, 1, 8));
        this.selfObj.SetScale(new Vector3(0, 0, 0));  // 最初は見えないサイズ
    }
    
    // 毎フレーム呼ぶ更新処理
    public void Update(){
        if(this.isFinished){
            return;  // 終了済みなら何もしない
        }
        
        if(this.timeCounter >= 1.0){
            this.timeCounter = 1.0;
            this.isFinished = true;  // アニメーション完了
        }
        
        // イージングを適用
        float easedValue = this.Ease(this.timeCounter);
        
        // スケールアニメーション実行
        Vector3 scale = new Vector3(1.5, 1.5, 1.5);
        scale.x *= easedValue;
        scale.y *= easedValue;
        scale.z *= easedValue;
        this.selfObj.SetScale(scale);
        
        // 時間を進める
        this.timeCounter += hsSystemGetDeltaTime() * EASE_SPEED;
    }
    
    // イージング関数: easeOutBack (勢いよく出て、少し戻る)
    // UI・オブジェクト演出のどちらにも適応しやすい万能タイプです。
    private float Ease(float time){
        // 0~1の範囲に制限
        time = hsMathMax(0, hsMathMin(1, time));
        // easeOutBack
        float c1 = 1.70158;
        float c3 = c1 + 1;

        return 1 + c3 * MathPow(time - 1, 3) + c1 * MathPow(time - 1, 2);
    }

    private float MathPow(float baseNum, int exponent){
        float result = 1;
        for(int i = 0; i < exponent; i++){
            result *= baseNum;
        }
        return result;
    }
}

イージングの利点

● 印象をコントロールできる

やわらかいなら「ぽよぽよ」、弾性があるなら「バウンド」など、
“動きだけで質感を説明できる” のがイージングの強みです。

ユーザーがひと目見ただけで、「これは柔らかい物だな」「重そうだな」と直感的に理解できます。


● 視認性・誘導性の向上

表示/非表示を即時で切り替えると、ユーザーに気づかれないことがあります。
「いつの間にか表示されていた」「気づかないうちに消えていた」などが起こりがちです。

そこで、登場時にイージングを付けることで
“ここを見てほしい” という意図を自然に伝えやすくなります。


● 体感的な“快さ”が生まれる

UIやオブジェクトの動きが「ただ動くだけ」なのと、
“気持ちのいいスピード感” を持つのとでは、操作感が大きく変わります。

スッと動く →「軽快」
一瞬溜めてから動く →「重厚」
滑らかに加速する →「自然」

こうした“体験の質”が高まることで、ユーザーに没入感を提供できます。


おわりに

イージングを実装できると、手触りは爆上がりするのでぜひ試してみてください。
また、様々なゲームや映像で使われているので、ぜひ遊びながら研究して自分のものにしてください。

執筆者:HIKKY 伊東(ふれふれ)
投稿:2025/12/9

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?