はじめに
Unityでは、スクリプトが実行される順序(ライフサイクル)を理解することが、効率的でバグの少ないコードを書くために重要です。特に、Awake()・Start()・U
pdate()・FixedUpdate()・LateUpdate() は、オブジェクトの動作に大きく影響します。
この記事では、Unityのライフサイクルの流れ、各メソッドの違いと用途、適切な使い分けとベストプラクティス について詳しく解説します。
この記事で学べること
- Unityのライフサイクルの基本的な流れ
- Awake()・Start()・Update()・FixedUpdate()・LateUpdate() の違いと適切な使い方
- オブジェクトの初期化・物理演算・カメラ制御の適切な処理方法
- ライフサイクルを考慮した最適なコード設計
Unityのイベント関数・ライフサイクルの流れ
Unityのオブジェクト(GameObject)は、生成されてから破棄されるまでに、特定の順序で関数が実行されます。
Awa
ke() → オブジェクトが生成された直後に実行(依存関係の初期化)- OnEnable() → オブジェクトがアクティブになったときに実行
- Start() → Awake() の後、最初のフレームの前に実行(スクリプトの準備)
- Update() → 毎フレーム実行(通常の処理)
- FixedUpdate() → 物理演算用の更新(一定時間ごとに実行)
- LateUpdate() → Update() の後に実行(カメラ追従など)
- OnDisable() → オブジェクトが無効化されたときに実行
- OnDestroy() → オブジェクトが破棄される前に実行(クリーンアップ処理)
※ 詳しいライフサイクルを知りたい方は公式サイトをご確認ください。
公式サイトリンク:イベント関数の実行順序
Awake() と Start() の違い
Awake()の説明と使用例
Awake()は、オブジェクトがシーンにロードされたとき、またはInstantiate()で生成されたときに 最初に呼び出されるメソッド です。
➡ 他のオブジェクトよりも早く実行される
➡ 依存関係の初期化に適している
➡ GameObject.SetActive(false) でも実行される
//Awake()の使用例(シングルトンの初期化)
public class GameManager : MonoBehaviour
{
public static GameManager instance;
void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
}
Start()の説明と使用例
Start()は、Awake()の後に実行され、オブジェクトがアクティブになった後に1回だけ呼ばれるメソッドです。
➡ Awake() の後に実行される
➡ コンポーネントの取得や、初期状態の設定に適している
オブジェクトの初期化の適切な処理方法
オブジェクトを適切に初期化するには、Awake() と Start() の使い分けが重要 です。
➡ Awake()で依存関係(他のスクリプトやデータ)を設定
➡ Start()で、オブジェクトの状態を初期化
public class GameManager : MonoBehaviour
{
public static GameManager instance;
//Awake() の使用例(依存関係の初期化)
void Awake()
{
instance = this;
DontDestroyOnLoad(gameObject);
}
Start() の使用例(オブジェクトの初期設定)
void Start()
{
Rigidbody rb = GetComponent<Rigidbody>();
rb.mass = 2.0f;
}
}
Update() と FixedUpdate() の違い
Update()の説明と使用例
Update()は毎フレーム実行されるため、プレイヤー操作やアニメーション処理などに適しています。
➡ フレームレートに依存するため、Time.deltaTimeを使って調整が必要
//Update() の使用例(プレイヤーの移動)
void Update()
{
float move = Input.GetAxis("Horizontal");
transform.position += new Vector3(move, 0, 0) * Time.deltaTime;
}
※ Transformについては以下のサイトを参考にしてください。
FixedUpdate()の説明と使用例
FixedUpdate()は物理演算のタイミングで実行され、フレームレートに関係なく一定間隔で呼ばれます。
➡ 物理演算(Rigidbodyの移動や衝突処理)に適している
//FixedUpdate() の使用例(Rigidbody の移動)
void FixedUpdate()
{
Rigidbody rb = GetComponent<Rigidbody>();
rb.velocity = new Vector3(0, 0, 5);
}
※ Rigidbodey、Colliderについては以下のサイトを参考にしてください。
物理演算を適切に処理する方法
物理演算を扱う場合、FixedUpdate()を使用することで安定したシミュレーションが可能 です。
➡ Update()ではなくFixedUpdate()でRigidbodyを制御
➡ Time.deltaTimeではなくTime.fixedDeltaTimeを使用する
//FixedUpdate() の使用例(Rigidbody の移動)
void FixedUpdate()
{
Rigidbody rb = GetComponent<Rigidbody>();
rb.velocity = new Vector3(0, 0, 5);
}
LateUpdate() の特徴と用途
カメラ制御の最適な方法
カメラをオブジェクトに追従させる場合、LateUpdate() を使うとブレが少なくなるためおすすめです。
➡ Upda
te()
の後に実行される
//LateUpdate() の使用例(カメラの追従)
public class CameraFollow : MonoBehaviour
{
public Transform player;
void LateUpdate()
{
transform.position = new Vector3(player.position.x, transform.position.y, transform.position.z);
}
}
ライフサイクルを考慮した最適なコード設計
より良いコード設計のポイント
➡ Awake()で他のオブジェクトやシングルトンの依存関係を初期化
➡ Start()でオブジェクトの初期設定やUIの準備を実施
➡ Update()はプレイヤーの入力処理に限定する
➡ FixedUpdate()で物理演算を処理し、安定した挙動を確保
➡ LateUpdate()でカメラ制御などの後処理を実施
//ライフサイクルを考慮したオブジェクト管理の例
public class PlayerController : MonoBehaviour
{
private Rigidbody rb;
void Awake()
{
rb = GetComponent<Rigidbody>(); // Rigidbody の取得
}
void Start()
{
rb.mass = 2.0f; // 初期設定
}
void Update()
{
// プレイヤーの入力処理
}
void FixedUpdate()
{
// 物理演算処理
}
}
まとめ
・ ライフサイクルの流れを理解し、適切なメソッドを選択する
・ オブジェクトの初期化は Awake()または Start()を使用する
・ プレイヤー操作やアニメーションは Update()に配置する
・ 物理演算は FixedUpdate()で処理する
・ カメラ追従や後処理はLateUpdate()を使う