2017年03月26日

【Unity5】キャラモーションをリミテッドアニメにする  〜 再生フレーム指定編 〜

unity_コマ落とし_クリップフレーム00.gif
前回のボーントレース編に続き、今回はアニメーションクリップの再生位置を指定する方法でリミテッドアニメ化してみます。

使う素材は前回と同じく、プロ生ちゃんの【PronamaChan_Ver3.unitypackage】 と、スタンダードアセット【Characters】 に入っているアニメーションクリップ【HumanoidRun】 です。インポート方法は前回記事を参照してください。
※Unity 5.5.2f1 (64-bit)を使用しています。


キャラクターを準備


【PronamaChan】 > 【Prefabs】 > 【Normal】 > 【Standard】
にある、【PronamaChan_dynamic】を【Hierarchy】に配置。

【Standard Assets】 > 【Characters】 > 【ThirdPersonCharacter】 > 【HumanoidRun】にある
【HumanoidRun】を【Hierarchy】の【Pronamachan_Dynamic】にドラッグ&ドロップ。
Image2.png

プロ生ちゃんが走り去ってしまわないように
【PronamaChan_dynamic】の【Inspector】 > 【Animator】の【Apply Root Motion】のチェックを外しましょう。
Image3.png



今回のスクリプト【LimitedAnimationByPlayClipFrame.cs】


【project】に【C# Script】を新規追加し、「LimitedAnimationByPlayClipFrame 」という名前に変更、ダブルクリックしてファイルを開き、下記の内容に書き換えて保存。

【LimitedAnimationByPlayClipFrame.cs】
using UnityEngine;
using System.Collections;
public class LimitedAnimationByPlayClipFrame : MonoBehaviour
{
       //各要素1フレームとして、-1は更新しないフレーム、それ以外の数字は描画するフレーム位置を指定
       public int[] timesheet = new int[] { 0, -1, -1, -1, -1, 5, -1, -1, -1, -1, 10, -1, -1, -1, -1, 15, -1, -1 };
       private Animator m_animator;
       private AnimationClip clip;
       private int animationHash;
       void Awake()
       {
              //アニメーションクリップの情報をゲット
              m_animator = GetComponent<Animator>();
              clip = m_animator.GetCurrentAnimatorClipInfo(0)[0].clip;
              animationHash = m_animator.GetCurrentAnimatorStateInfo(0).shortNameHash;
              m_animator.speed = 0;
       }

       void LateUpdate()
       {
              if (IsDrawFrame(Time.frameCount))
              {
                     DrawAnimationFrame(timesheet[Time.frameCount % timesheet.Length]);
              }
       }
       //アニメーションクリップの指定時間のフレームを静止再生
       void DrawAnimationFrame(int drawFrame)
       {
              //アニメーションクリップの長さを1とした時のフレームの位置
              float normalizedtime = ((float)drawFrame / clip.frameRate / clip.length);
              m_animator.Play(animationHash, 0, normalizedtime);
       }
       //ポーズを更新するフレームかどうかチェック
       bool IsDrawFrame(int checkFrame)
       {
              if (timesheet[checkFrame % timesheet.Length] >= 0)
              {
                     return true;
              }
              return false;
       }
}
実際、アニメーションクリップは複数あったりするものですが、今回は実験なのでアニメーションクリップは一つだけの想定のスクリプトになってます。
結果、あまり汎用性がないのでご注意ください。

このスクリプトを【Hierarchy】の【Pronamachan_Dynamic】にアタッチし、
【Inspectr】の【Timesheet】に使用するフレームの情報を入力します。
【Size】はループするフレーム数と思ってください。以下【Element】が各フレームで、値がアニメーションクリップのフレームナンバーです。

Image.png
【-1】はポーズの更新なし、つまり前の絵のままのフレームです。
【0】以上の値はフレームナンバーで、元のクリップのフレーム数より大きい値も入ります。
10フレームしかないアニメーションクリップで15と入れたら、5フレーム目が使われます。
ちなみに今回使ったアニメーションクリップ【HumanoidRun】は【clip.framerate】が「30」で長さ【clip.length】は「0.593」なので、フレーム数換算で19程度です。

もちろん数字を順番に入れる必要はないので、唐突に違うフレームを差し込んだりできます。

これで再生してみると、スカートなどの揺れ物以外はコマ落ちして再生できます。
unity_コマ落とし_クリップフレーム00.gif
この方法とボーントレースを組み合わせて、両者の欠点を補えれば・・・。
posted by 神威光司 at 14:10| インフォメーション