😇

【VRChat/UdonSharp】FixedUpdateの罠

2023/06/06に公開

予防線

2023年6月時点での話です。今後仕様が変わる可能性はありますし(あってくれ)、私の知識に間違いがある可能性もあります。

FixedUpdateを使いたい

事前知識

必要かは分かりませんが、一応説明。
VRChatのU#(というかUnity)において、常時動き続けるイベントにUpdateとLateUpdateとFixedUpdateがあります。(他にもあるかも)
Updateは毎フレーム呼ばれます。LateUpdateはUpdateの処理が終わった後に呼び出されます。
そしてFixedUpdateは一定間隔で呼ばれます。

UnityにおけるFixedUpdate

デフォルトでは50FPS、0.02秒間隔、つまり1秒に50回呼ばれます。
これはProject Settingから変更することもできて、割と融通の効く良い子です。

U#におけるFixedUpdate

人によって動作が違う

U#のFixedUpdateはプレイヤーのモニターのリフレッシュレートで呼ばれます。
なんのこっちゃ?となるかもしれませんので説明。
モニター毎に何FPSまで表示できるかは違いがあります。それを表したのがリフレッシュレートです。
一般的なモニターなら60Hz(つまり60FPS)、ゲーミングモニターなら144Hz(144FPS)くらいが普通ですかね。

つまり、プレイヤーによってFixedUpdateが呼び出される間隔が違います。
60Hzのモニターのプレイヤーが見ているワールドのFixedUpdateは60FPSで動きます。
同じワールドにいる144HzのモニターのプレイヤーはFixedUpdateが144FPSで動いています。
これはVRHMDでも同じです。そのHMDのリフレッシュレートで動きます。

変更ができない

この間隔を変更する手段はありません。なんで?

そしてその事は公式のどこにも書いてはいない

書いてません。
挙動が個々人のモニター依存なため、デバッグ時点では気付かない可能性もあります。

結論

残念ながらUpdateの方が安全です。
それでも使いたい場合、世の中には30Hzのモニターが存在する事を覚えておくといいかもしれません。ゲーミングモニターだと今は360Hzとかあるらしいですよ。

おまけ

あとUpdateとかFixedUpdateはStartの前に呼び出される事があります。
(呼び出されない事もある)

private int[] _numArray;
void Start()
{
    _numArray = new int[5];
}
void FixedUpdate()
{
    for(int i; i < _numArray.Length; i++)
    {
        //なんか処理
    }
}

こういうのはたまにエラーが出ます。なんで?

Discussion