0 支持
468 閲覧
(160 ポイント) Q&A

SS6P for Unityの機能について質問させてください。


現在SpriteStudioを使用したゲームを作成しておりその中で、
アニメーションの途中(例・剣を振るアニメーションの場合、剣を振り下ろす直前等)
を会得し攻撃時のダメージ等のいくつかの処理を条件分岐で追加したいのですが、アニメーション中にフレーム等でどこまでアニメーションが進んだかを会得することは可能でしょうか。
また、フレーム数以外にもアニメーション中のキャラクターに対し特定のタイミングを会得する手段はありますでしょうか。初歩的な質問で申し訳ありませんが、よろしくお願いいたします。【バージョン】
・SpriteStudio 6 Player for Unity 1.1.32
・Unity2020.1.4f

このページをシェアする

回答 1

+1 支持
(4.9k ポイント)
編集

お世話になっております。SS6Player for Unity(SS6PU) 開発担当です。

基本的に、Unityでは動作機種や環境によってアプリケーションの動作速度が安定していないため、フレームスキップが起きてしまいます(常に同じ時間周期でゲームの処理が呼び出される保証がありません)。

そのため、「フレーム数」で処理を分岐するのではなく、「経過時間」などで処理を分岐するような仕組を推奨します。

単純に「アニメーションが、特定のフレームを通過したか?」を知る代表的な方法としては、2つ存在しています。

  1. 「ユーザーデータ」を使用して、コールバックを受け取る
  2. 「アニメーションの現在の再生時間位置」を取得する

1は、SpriteStudio上で特定のパーツに「ユーザーデータ」を設置しておくことで、そのデータをインポート後にSS6PUで再生した時に、「ユーザーデータを検知した」というコールバックを受け取ることができるものです。

具体的には、SpriteStudio6のアニメーションを再生管理しているScript_SpriteStudio6_Rootクラスのインスタンスに「FunctionUserData」というデリゲート関数を設定する変数があります。

ここに「呼び出される関数」を設定しておくことで、直前のMonoBehaviourのUpdateから今回のUpdateの間の時間経過内に、ユーザーデータが検知された時に設定した関数が呼ばれます。

詳細の解説は下記になります(SS6PUを公開しているGitHubのWikiにあるスクリプトのマニュアル内です)。

https://github.com/SpriteStudio/SS6PlayerForUnity/wiki/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9%EF%BC%88%5BRoot%5D%E3%82%B3%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%EF%BC%89#Variable-FunctionUserData

この方法の利点としては、下記になります。

  • 毎ループ経過時間を監視しなくても良い(経過した時間での判定とその処理だけを関数化して記載することができる)
  • フレームスキップ(前回から今回の処理がUnityに設定している処理フレーム数に間に合わなかった場合など)が起きても、その複数フレームにわたっている経過時間の間に検知したユーザーデータ全てに対して、個別にコールバックがかかる。
  • ユーザーデータに付属している様々なデータがあるので、付属情報を乗せやすい。
  • アニメーション合成(複数のアニメーションを同時に再生して、パーツ毎に適用するアニメーションを指定して、アニメーションを合成する方法)や、トランジション再生(いわゆるモーションブレンドです)を行った場合でも、再生区間中にあるユーザーデータを検知してくれる。

一方、欠点としては下記になります。

  • ユーザーデータの検知処理が若干処理が複雑なこともあり、設置したユーザーデータの個数や仕掛けるパーツ数が多くなると、CPU側の実行速度に負荷がかかる場合がある。(基本的にユーザーデータを仕掛ける場合、できるだけ特定のパーツ……例えばrootパーツなど……に集中して設置することを推奨します)。
  • コールバックを受け取る関数の中でアニメーションの切り替えなどの「アニメーションの再生状態に影響を与える処理」を行うと誤動作する場合がある(ユーザーデータのコールバックは、アニメーションの更新処理中で呼び出されるために、その最中にアニメーションの再生状態に影響を与える処理を行うことは危険です)

2は、Script_SpriteStudio6_Rootクラスの実体の「CursorGet」関数を使用して、「現在再生している時間位置」を取得する方法です。

この「時間位置」は、厳密には「経過時間ではない」ことに注意してください(経過時間ではあるのですが、アニメーションがループ再生している場合などは、ループした時には0秒の位置に戻ります。つまり、アニメーションの現在の再生「位置」を取得する関数です)。

こちらは、現在GitHubのスクリプトマニュアルには記載がない旨、申し訳ありません(本関数を追加した時に、解説の追記を失念しておりました)。

Unityのアセット内のSpriteStudio6/Script/Root/FunctionTrack.cs内の本関数宣言の直上に注釈で英語での解説があります。

  • public float CursorGet(int indexTrack)

返ってくる値は「1.0f=1秒」を単位とした再生位置です。

こちらのメリットは、

  • ユーザーデータと違い、現在のアニメーション再生の時間位置だけを取得するため「単に経過している時間」を知りたいだけの場合、高速です。

一方デメリットは、

  • フレームスキップを考慮していないので、直前のUpdateから今回のUpdateの間の区間中に複数の条件成立がある場合を考慮してコードを記述する必要がある。
  • アニメーション合成やトランジション再生などを行っている場合に、複数のトラック(アニメーションの時間経過を管理するための機構です)のそれぞれの経過時間位置を自分(コード)で調停する必要がある

となります。


少々長くなってしまい申し訳ありませんが、上記のどちらかの方法で、ご希望の実装が行えることを願っております。

※「シーケンス」などを使った複雑な状態遷移なども可能ではありますが、その詳細については(若干複雑になることもあり)、ここでは割愛させていただいております。

何卒今後ともよろしくお願いいたします。

...