はじめに
8年ぶりにUnityを使ってカジュアルゲームを作ってAndroid向けにリリースしました。
弓を使うアクションゲームなのですが、その中で実装したかった機能の1つが
「弓で狙っているときは世界がスローモーションになる」です。
Skylimで言うところの「冷静沈着」というスキルですね。
開発環境
- Unity 2019.4.20f1
- Mac
スローモーションにする方法
スローにするだけならTime.timeScaleの値を変更するだけなので簡単に実現できます。
void BeginSlow() { // 速度を遅くする(10%) Time.timeScale = 0.1f; } void EndSlow() { // 速度を通常に戻す(100%) Time.timeScale = 1.0f; }
timeScaleを0にすればスローではなく停止になりますし、
timeScaleを2にすればスローではなく2倍に加速します。
スローにする・しないを制御する
上記のTime.timeScaleを変更する方法だとスローにしたくないものまでスローになってしまったりするので以下の通りUpdate関数とFixedUpdate関数を使い分けます。
- スローにする:FixedUpdate関数を使う(timeScaleの影響を受ける)
- スローにしない:Update関数を使う(timeScaleの影響を受けない)
これに加えてUniRxやUnityのアニメーター機能、DoTweenの方も使い分けが必要です。
(UniRxとDoTweenについての解説記事はまた今度)
UniRXでの使い分け
- スローにする:UniRx.TriggersのFixedUpdateAsObservableを使う
- スローにしない:UniRx.TriggersのUpdateAsObservableを使う
例)
using UnityEngine; using UniRx; using UniRx.Triggers; public class Sample : MonoBehaviour { private void Start() { this.FixedUpdateAsObservable() .Subscribe(_ => Debug.Log("スローにする処理")); this.UpdateAsObservable() .Subscribe(_ => Debug.Log("スローにしない処理")); } }
DoTweenでの使い分け
- スローにする:なにもしない(もしくは.SetUpdate( false )をつける)
- スローにしない:.SetUpdate( true )をつける
例)
using UnityEngine; using DG.Tweening; public class Sample : MonoBehaviour { void Start() { // SetUpdate(true)をつけていないのでX軸移動はスローになる this.transform.DOMoveX(0, 1); // SetUpdate(true)をつけたのでY軸移動はスローにならない this.transform.DOMoveY(0, 1).SetUpdate(true); } }
アニメーターでの使い分け
- スローにする:インスペクタからAnimatorのUpdate ModeをNormalにする
- スローにしない:インスペクタからAnimatorのUpdate ModeをUnscaledTimeにする
スローする・しないを制御できないもの
下記については特殊な処理を書かない限りは通常制御できません。
- スローにならないもの
- BGMや効果音などの音
- スローになってしまうもの
- パーティクルのアニメーション
- シェーダーのアニメーション
Rigidbodyをスロー中もなめらかに動かすには?
スロー中に物理演算を行うオブジェクトがカクカクしてしまう場合は、
インスペクタからRigidbodyのInterpolateをInterpolateにするとなめらかになります。
↑Interpolateなし
↑Interpolateあり
おわりに
忘れないうちに自分がゲームを作ったときに理解したtimeScaleを使ったスロー演出の仕組みを記事に残しました。
スローモーション演出はおもしろい表現ができるのでぜひ試してみてください。
応用すればよく見るゲーム速度倍速モードなども同じように実装できるので、UnityのtimeScaleの仕様はしっかり抑えておきたいですね。
上記のスロー演出を実装した実際のゲームは以下から遊べますので、興味があればぜひ遊んでみてください。
0 件のコメント:
コメントを投稿