こんにちは、Unityエンジニアのオオバです。
例えばキャラクターを動かしたいとき、 更新メソッド を使いますよね。
毎フレーム1cm動かすといった処理です。
Unityが提供する更新メソッドは3つあります。
- Update
- LateUpdate
- FixedUpdate
それぞれ役割と意味があり、 全くの別物 です。
本記事では UpdateとLateUpdateの違い について解説します。
正しく理解しておかないと、 描画周りの不具合 を出してしまいます。
ぜひ本記事を通して学んでいきましょう。
UpdateとLateUpdateの違いは実行タイミング
はじめに結論を簡単にまとめます。
①Update、LateUpdateとはイベント関数の1つ
②Updateはフレームの先頭で呼ばれる
③LateUpdateはすべてのUpdate終了後に呼ばれる
UpdateとLateUpdateの呼ばれるタイミングが違います。
LateUpdateがUpdateより早く呼ばれることはありません。
必ずこの順番です。
ここを勘違いして 描画周りの不具合はよく発生 します。
特に カメラを動かしたとき です。
今回はよくあるトラブルを例にしてUpdateとLateUpdateの違いを学びます。
👉DOTweenの教科書を読んでUnityアニメーションをプログラミングしてみよう!
UpdateとLateUpdateはイベント関数の1つ
UpdateとLateUpdateの違いの説明に入る前に前提知識を解説します。
UpdateとLateUpdateはイベント関数の1つ です。
イベント関数とは、MonoBehaviourクラスを継承した際に使用可能になる特別なメソッドです。
MonoBehaviourを継承、つまり自作コンポーネント内に記述したイベント関数はUnityから自動的に実行されます。
Update/LateUpdateはともに自動的にUnityから実行 されるのです。
つまりMonoBehaviourがなければUpdate/LateUpdateは実行されません。
MonoBehaviourの知識はUnity開発の基礎の基礎 。
もし理解に不安を感じている方はぜひこちらの記事を読んでみてください。
MonoBehaviourとはコンポーネントの一種です。
そもそもコンポーネントとはGameObjectに追加できる機能のこと。
コンポーネントの理解はUnity開発では必須。コンポーネントの理解に不安な方はぜひこちらの記事を読んでみてください。
Updateでカメラが何かを追いかける処理は落とし穴
Updateでカメラが何かを追いかける処理の実装は要注意です。
わかりやすく説明するためにサンプルを作ってみました。
このようなUnityちゃんを等速で歩かせます。
ソースコードは次の通り。
Unityちゃんを Update メソッドでメソッドで移動させただけです。
using UnityEngine;
public class UnityChanWalk : MonoBehaviour
{
void Update ()
{
// Unity-chanが毎フレーム2cm移動する
transform.Translate(new Vector3(0.02f, 0));
}
}
次にUnityちゃんをカメラが追いかけるようにします。
このような感じで毎フレームUnityちゃんを追いかけます。
サンプルコードはこちらです。
💻ソースコード : Unityちゃんを追いかけるカメラのサンプル
using UnityEngine;
public class ChaseUnityChanCamera : MonoBehaviour
{
public Transform unityChan;
void Update ()
{
var pos = unityChan.position;
pos.y = 0.7f;
// Unity-chanの方をマイフレーム向くようにする
transform.LookAt(pos);
}
}
一見大丈夫そうですよね。
しかし実はこれ とても危うい実装 なのです。
ここまで何度か登場している「Transform」。
Transformとは、UnityではどのGameObjectにもセットされている特別なコンポーネントです。
「移動」「回転」「拡大縮小」といった重要な機能を持っています。
Transformの理解はUnityでのゲーム開発には必須です。Transformの理解に自信がない方はこちらの記事を読んでみてください。
オブジェクトとカメラをUpdateで動かした不具合
最初に大事なことを書きます。
「MonoBehaviour同士のUpdateの実行順は保証されません。」
つまり カメラとUnityちゃんのUpdateはどちらが先に実行されるかわからない のです。
これがどういう問題なのかというと カメラが先に動くとマズイ 。
本来、Unityちゃんが動いた後にカメラが追いかけるという処理にしたいはずです。
【1フレーム目】
👱♀️Unityちゃん → 📷カメラ
【2フレーム目】
👱♀️Unityちゃん → 📷カメラ
【3フレーム目】
👱♀️Unityちゃん → 📷カメラ
この処理順であれば正常に描画されます。
しかしUpdateの順番は 保証されない ため、次のような順にもなりえます。
【1フレーム目】
👱♀️Unityちゃん → 📷カメラ
【2フレーム目】
📷カメラ → 👱♀️Unityちゃん
【3フレーム目】
👱♀️Unityちゃん → 📷カメラ
👆のように2フレーム目の 📷のカメラが先に動いてしまう とどうなるでしょうか。
結論から言うと、3フレーム目の👱♀️Unityちゃんを映し出す📷カメラは瞬間移動したUnityちゃんを捉えることになります。
つまり映像が一瞬 フレームをスキップしてしまう 感じです。
詳しく解説していきます。
カメラがフレームジャンプする理由
【1フレーム目】
- 👱♀️Unityちゃん : 2cm進む
- 📷カメラ : 2cm進んだUnityちゃんを映し出す
【2フレーム目】
- 📷カメラ : 2cm 進んだUnityちゃんを映し出す
- 👱♀️Unityちゃん : 4cm進む
【3フレーム目】
- 👱♀️Unityちゃん : 6cm進む
- 📷カメラ : 6cm進んだUnityちゃんを映し出す
このような処理になるのです。
つまり 4cmののときのUnityちゃんをカメラは移すことができないのです。
これがフレームスキップの理由です。
これを回避するために LateUpdate が活躍します。
LateUpdateでカメラを処理する
先の描画トラブルはカメラが Unityちゃんより先に処理 してしまったことです。
つまり カメラは必ず後 に処理されれば問題ありません。
そこでLateUpdate内にカメラの処理を移します。
LateUpdateとは 必ずUpdateの後 に処理する更新メソッドっです。
Unityちゃんの処理はUpdateのまま、
カメラが追いかける処理をLateUpdateに移すことで解決します。
解決したソースコードはこちらです。
💻ソースコード : LateUpdateでUnityちゃんを追いかけるカメラのサンプル
using UnityEngine;
public class ChaseUnityChanCamera : MonoBehaviour
{
public Transform unityChan;
// 「Update」から「LateUpdate」に変更
void LateUpdate ()
{
var pos = unityChan.position;
pos.y = 0.7f;
// Unity-chanの方をマイフレーム向くようにする
transform.LookAt(pos);
}
}
これで無事に想定通りの描画処理になりました。
どうしてもカメラの処理をUpdateで書いてしまうと、
先のフレームスキップの原因 になってしまいます。
カメラを動かす処理はLateUpdateで書きましょう。
UpdateとLateUpdateの違いまとめ
UpdateとLateUpdateの違いについて解説してきました。
最後に記事の内容を簡単にまとめます。
①UpdateとLateUpdateは実行タイミングが違う
②LateUpdateは必ずUpdateの後に実行
③カメラを動かす処理はLateUpdateに書くのが吉
こんな感じです。
Update と LateUpdate は用途が全然違います。
特にカメラ操作する際は顕著におかしくなるので要注意。
カメラの動きはLateUpdateで書きましょう。
カメラ以外にも処理的に最後に回したいものも出てきます。
そんなときに LateUpdate を使ってみてください。
この記事があなたのゲーム開発に役に立ったらうれしいです。
UpdateとLateUpdateは重要なイベント関数の1つ。
最も重要なイベント関数はAwakeです。
Awakeについて詳しく解説した記事はこちら。ぜひ読んでみてください。
この記事が気に入ったらフォローしよう
- Unity2020.3.26f1