原カバンは鞄のお店ではありません。

Unityを使ったゲーム制作のあれこれを綴っていきます。

【Unity】Objectを音楽と同期させて動かす時の注意

最初に宣伝から

現在、開発中のゲーム「Dull Things No Life」ですが、ようやく完成の目処が立ってきたので今回の記事からそのゲーム内容について紹介をしていきたいと思います。

 

f:id:Karvan:20190122223555p:plain


「Dull Things No Life」はいわゆるラン系ゲームというやつで、操作キャラクターが自動で走っているところをタップ操作で左右に移動させ、迫り来る障害物をかわしてゴールを目指して進んでいく、といった内容のゲームとなっています。

このゲームの操作キャラクターは赤色のMotorBikeで、画面の左右をタップすることでMotorBikeも左右に移動します。
またMotorBikeの走る経路はトンネルのように壁で囲まれていますが、上下左右どこの壁にも移動することが出来ます。

 

f:id:Karvan:20190122223646g:plain

 

こんな感じ、大きな柱が走路を塞いでいる場合は左右の壁に移動してそれを避ける事ができます。

画面の左右をタップするだけで難しい操作はありません。まぁ、類似のアプリは多々あるので「ああ、よくあるやつね」と思って頂いて結構です。

 

ただ、「Dull Things No Life」ではMotorBikeは左右移動だけでなく特殊な動作で障害物を避けることが出来るのですが、宣伝が長くなるのでこれについてはまた次回紹介したいと思います。

 

で、本題

UnityではObjectを移動させる処理は様々ありますが、よく使われる手法としてUpdate内で移動速度×前フレームからの時間差分=移動量を計算してObjectのtransformに反映する、という方法があります。

 

このとき前フレームからの時間差分にはTime.deltaTimeを使用しますが、このdeltaTimeはTime.timeScaleに影響を受けます。

 

Time.timeScaleはUnity内(ゲーム内)の時間の定義しているので、Time.timeScale = 1であれば現実の時間と同じ時間、この値を小さくすると現実の時間 > ゲーム内の時間となり、例えばtimeScale = 0.5とすると、deltaTimeが1.0(sec)だとしても現実の時間は2.0(sec)経過していることになります。

 

通常、timeScaleを意図的に変更しない限りは(timeScale = 1のままであれば)、現実の時間=ゲーム内の時間となるのでdeltaTimeを使用しても現実の時間と食い違うことはなく特に問題ない、と思っていました。

 

だが、しかし・・・

Mobile端末でゲームを動かす場合、PCと比べると演算性能や描画性能は劣るので、PC上のUnityEditorで確認した動作よりももっさりした(処理に時間が掛かる)動作になるのは仕方ないことだと思います。

 

ただ、どうもUnity内部にて(私の推測だけど)、処理に時間が掛かる分だけゲーム内のtimeScaleを調整しているようで、deltaTimeと現実の時間が一致しない状態になります。
つまり、こちらはtimeScaleを変更していないのに、現実の時間 > ゲーム内の時間、みたいな事象になるということ。

 

まぁ、現実の時間とリンクしない、ゲーム内の時間だけで完結するようなゲームの場合、それでも問題ないのでしょうが、音楽と同期させてObjectを動かしたい場合はちょっと問題です。

 

何が問題なのか

AudioClipによるSEやBGMの再生はtimeScaleの影響を受けません。つまり、かならず現実の時間と同じ時間だけ経過して音声を再生していきます。一方、Objectの方はtimeScaleの影響を受けてゲーム内の時間で動作するとなると、例えば、下図のような典型的な音ゲーを作る場合

 

f:id:Karvan:20190122224035p:plain

 

こんな感じの仕様となるので、各ノーツはそれに対応する音が再生されるより前に画面に表示する必要があります。

 

f:id:Karvan:20190122224156p:plain

 

しかし、移動処理でdeltaTimeを使用していると現実の時間 > ゲーム内の時間なのでノーツ移動が間に合いません。

 

f:id:Karvan:20190122224257p:plain

 

これはゲームとして致命的です。しかもUnity内部にて処理速度に応じて勝手に調整されているので(あくまで私の推測)、こちら側(製作者側)で遅くなるのを見越して移動速度を調整するような対処も行う事ができません。

 

なのでこんなときは・・・

timeScaleに影響ない前フレームからの時間差分を得る場合にはTime.unscaledDeltaTimeを使用します。

 

deltaTimeとunscaledDeltaTimeの違いはtimeScaleの影響ありなしだけなので、通常時はdeltaTime=unscaledDeltaTime=現実の時間となっていますが、上記のように音楽と同期させるために必ず(勝手にtimeScaleが変わっても)現実の時間とリンクが必要な場合はunscaledDeltaTimeを使用して処理を組み込む必要があります。

 

ちなみに、Objectを移動させるのにiTweenやDoTweenを使っていても特にオプションを指定してない限りは同様の現象になります。また、Animatorでも同様です。

 

以下にtimeScaleを考慮しない場合のオプションを記載します。

 

  • iTweenの場合:ignoretimescaleプロパティをtrueに設定する

   Hashtable ht = new Hashtable ();

   ht.Add ("ignoretimescale", true);

 

  • doTweenの場合:Updateオプションをtrueに設定する

   DOTween.To( ~ ).SetUpdate( true );

 

  • Animatorの場合:updateModeプロパティにUnscaledTimeを設定する

        animator.updateMode = AnimatorUpdateMode.UnscaledTime;

 

注意事項

前述のようにunscaledDeltaTimeはtimeScaleを考慮しないので、例えばPause処理などでtimeScale=0としていても関係なく動作します。

 

また、オブジェクトが一旦非Active状態になると、その間の差分時間が加算されていくのでActive状態に戻ってUpdateでunscaledDeltaTimeを取得すると、最初フレームでunscaledDeltaTime = 非Active状態だった時間、が返ってきて、一気に時間が経過したような動作になるようです。


これについては以下のkan.kikuchiさんのブログに詳しく書かれています。

 

kan-kikuchi.hatenablog.com

 

 

 

 

 

◇プライバシーポリシー

●個人情報の利用目的

当ブログでは、メールでのお問い合わせ、メールマガジンへの登録などの際に、名前(ハンドルネーム)、メールアドレス等の個人情報をご登録いただく場合がございます。

これらの個人情報は質問に対する回答や必要な情報を電子メールなどをでご連絡する場合に利用させていただくものであり、個人情報をご提供いただく際の目的以外では利用いたしません。

●個人情報の第三者への開示

当サイトでは、個人情報は適切に管理し、以下に該当する場合を除いて第三者に開示することはありません。

・本人のご了解がある場合
・法令等への協力のため、開示が必要となる場合

個人情報の開示、訂正、追加、削除、利用停止
ご本人からの個人データの開示、訂正、追加、削除、利用停止のご希望の場合には、ご本人であることを確認させていただいた上、速やかに対応させていただきます。

アクセス解析ツールについて

当サイトでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。

このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています。このトラフィックデータは匿名で収集されており、個人を特定するものではありません。
この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。

●免責事項

当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。

当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、誤情報が入り込んだり、情報が古くなっていることもございます。

当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。

●プライバシーポリシーの変更について

当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。

修正された最新のプライバシーポリシーは常に本ページにて開示されます。