Inputと各種Updateの関係

やたらキャラががたつく。

なんか入力が気持ち悪い。

入力がフレーム抜けする。

そんな経験ありません? たぶんそれはInputがUnityでどう働いているかよくわかってないから。

ということでそのシステムをちょびっと覗いてみましょう。

ちなみに正確な記述についてはここを見るといいかも。

ちなみに結論としてはUpdateで入力を受け取ってFixedUpdateで動かせ、ってことです。

更新頻度?

昔のゲームならフレーム単位で動いていた。

つまりは、60fps(=1秒に60回画面を切り替える)とか30fpsとかいってたので、その1/60秒に収まるような処理を書くようにしていた。

この場合が便利なのは、一回の処理が全部同じ間隔で呼ばれることが確定しているということだ。

ファミコンだと内部で掛け算ができないが、等間隔で呼ばれることを利用して微分して足し算に直して計算してたりする。

ただ、これだと問題がある。


・fpsを自由に変えられない

人間の視覚としては正直60fpsで十分なのだが、より多くしたほうがやっぱりより自然には近づく。(あんまり変わらないからどうでもいいとは思うけど)

あとはVsyncとかにはスクリーンに合わせてfpsを変える必要があるのだが、できないねーってなる。

・遅くなったとき不自然

1/60秒で処理が終わらなかったときどうなるか。かんたんにいうとザ・ワールドする。

1フレームの処理が終わらないと次にいけなくて、しかし1フレーム分遅くなったからといって次を速くすると、一時停止したあと時が加速する。

これじゃあだめだ。


というわけで、Unityなど今どきのゲームはfpsが変わるのに対応している。60ループしたら1秒、ではなく実際の時間で計算する。

UnityでいうとTime.deltaTimeとかでやってるやつ。

そういうわけで、等速直線運動なら速度にこいつをかけてやらないとうまく動かないわけだ。

Unityの更新頻度

それじゃ、Unityは実際どうやってんのかっていう話ですが、実はこのdeltaTime、2種類ある。

fixedDeltaTimeとdeltaTimeだ。

fixedDeltaTimeはFixedUpdateを呼ぶ間隔。

deltaTimeはUpdateを呼ぶ間隔。

Fixedと同じタイミングでは物理演算をしてるので、なるべく高い頻度で同じ間隔で呼ばないと不正確な動きをしてしまう。そこらへんの話は「微分」とかで検索かけたらわかると思う。

一方でUpdateと同じタイミングでは絵をかいている。こいつがここにいるからここに画像置いて……とかやってる。

とにかく、上下は独立に動いているとみなしてよい。

それで、入力状況の更新はUpdateと同じ頻度で行われている。だから

InputはUpdateの中に書かなければならない。

じゃないと押し始めであるGetKeyDownがtrueになってるタイミングの間にInputが呼ばれないことがありえる。押し込んだことはないけど押されてる、とかなって処理がおかしくなってしまう。

一方でRigidbodyの加速やらはFixedUpdateの中に書かなければならない。

じゃないと、「壁にめり込んどるやん!直したろ!」という物理演算的な処理がないまま画面に表示されて、壁に向かって微振動する主人公が発見されてしまう。

いかがでしたか?