Unity Time.timeSinceLevelLoad WaitForEndOfFrame など時間の計算系で調べたこと
みなさんご存知のこちらの大変頼りになるブログを参考に、シーンのフェード遷移機能を自分なりにいじっていた際、少しよくわからないメソッドをたくさん使用していたので、書いておきます。
今回いじろうと思った場所
IEnumerator FadeinCoroutine (float time, System.Action action) { float endTime = Time.timeSinceLevelLoad + time * (1 - cutoutRange); var endFrame = new WaitForEndOfFrame (); while (Time.timeSinceLevelLoad <= endTime) { cutoutRange = 1 - ((endTime - Time.timeSinceLevelLoad) / time); fade.Range = cutoutRange; yield return endFrame; } cutoutRange = 1; fade.Range = cutoutRange; if (action != null) { action (); } }
各メソッドについて
Time.timeSinceLevelLoad
”フレームが開始された時間 (Read Only) 。最後のレベルが読み込まれてからの時間 (秒) です。”
WaitForEndOfFrame ()
”スクリーン上のレンダリングが完了するまで待ちます。”
とのことです。(スクリプトリファレンスより)あれ、以外と少なかった。
このコードが行なっていること
このコードはフェードインの場面です。条件として、この状態ではシーンの遷移には対応できていません。
・最初の一行目 ”float endTime = Time.timeSinceLevelLoad + time * (1 - cutoutRange);” はtimeをユーザが自分で指定した遷移時間だとして、終わる時間を計算し変数に格納しています。
・次の行 "var endFrame = new WaitForEndOfFrame ();" varについては以下を参照。
連載! とことん C#: 第 10 回 型を書かなくても強い型付け! (var とジェネリック) in C#
varは"ある型の値を返すメソッド"として使用しているのかな?僕全くvarを使用しないのでわからないですが。endFrameを呼べば、new WaitForEndOfFrame ()が呼べる状態にしているのでしょうか?
・その後のwhileでは、割合でMaxを意味する1から、現在から終了までの時間を指定した遷移時間で割ることによって現在のフェード具合を算出、それを別メソッドであるフェードの具合を実際に表示するメソッドに託し、先ほどのvarで準備したレンダリング終了まで待機するメソッドを呼び出しています。(きっとそう)これで、フェードを表現しているのですね。
このコードがシーン遷移に対応していなかったワケ
"Time.timeSinceLevelLoad"これだと思います。元々、今回使用させてもらっているスクリプトはシングルトンなものではなく、僕が無理やりDontDestroyなどをつけてしまっているのもありますが、シーンが変わったらこの値は絶対変化します。おそらく、endTimeを計算した最初の呼び出しでは遷移前のシーンの時間で計算されていました。その後の現在の遷移割合を計算しているwhile内の計算では、新しいシーンでの時間で計算されていました。これがシーン遷移時のフェードがうまくできなかった原因かなと思います。
追記
このスクリプトのフェードインとフェードアウトって逆に実装されている気がする。フェードインって徐々に画面が映る手法で、フェードアウトが徐々に暗転していくようなものだと思っていた。さてどちらが違うのか!笑