Script Lifecycle
You never call Start or Update yourself. Unity calls them for you, at specific moments and in a fixed order. Knowing that order tells you where each piece of code belongs.
The order, simplified
A theater show. Unity is the stage manager with a script of cues, and your methods are actors waiting for their cue. Awake is the actor arriving backstage and getting into costume. Start is walking on stage right before the curtain rises, when everyone else is already in costume. Update is saying your line every time the stage manager points at you, once per frame, for the whole show. OnDestroy is leaving the building after the show. You never shout your own cue; you wait to be called.
Update (highlighted) always runs once per frame.When the object is created (once):
Awake(): the object exists. Set up references to your own components here.OnEnable(): the script was turned on. Subscribe to events here.Start(): runs just before this script's firstUpdate. Every object'sAwakehas already run, so it is safe to talk to other objects.
Every frame (repeats):
FixedUpdate(): runs at a fixed rate (50 times per second by default). May run 0, 1 or several times in a single frame. Put physics code here.- Unity simulates physics, then calls
OnTriggerEnter,OnCollisionEnterand similar callbacks. Update(): runs once per frame. Put input and most game logic here.- Coroutines that did
yield return nullcontinue. - Animations are updated.
LateUpdate(): runs after everyUpdatehas finished. Good for cameras that follow something.- The frame is drawn to the screen.
When the object goes away:
OnDisable(): the script was turned off or the object is being destroyed. Unsubscribe from events here.OnDestroy(): the object is being destroyed (or the scene is closing).
Which method should I use?
| Method | Called | Use it for |
|---|---|---|
Awake | Once, when the object loads. Runs even if the script component is disabled (as long as the GameObject is active). | GetComponent calls, initializing your own variables |
OnEnable | Every time the script becomes enabled / the GameObject becomes active | Subscribing to events, resetting state for reused (pooled) objects |
Start | Once, before the first Update, only if the script is enabled | Code that needs other objects to be set up already |
FixedUpdate | Fixed time step (default every 0.02 s) | Rigidbody forces and velocity |
Update | Every frame | Input, timers, non-physics movement, game logic |
LateUpdate | Every frame, after all Updates | Camera follow, anything that must react to where things ended up this frame |
OnDisable | When disabled or destroyed | Unsubscribing from events, stopping sounds |
OnDestroy | When destroyed | Final cleanup |
Example: seeing the order yourself
Attach this to a GameObject, press Play, then disable the GameObject and stop the game. Watch the Console.
using UnityEngine;
public class LifecycleLogger : MonoBehaviour
{
void Awake() { Debug.Log("1. Awake"); }
void OnEnable() { Debug.Log("2. OnEnable"); }
void Start() { Debug.Log("3. Start"); }
void FixedUpdate() { if (Time.frameCount < 3) Debug.Log("FixedUpdate, frame " + Time.frameCount); }
void Update() { if (Time.frameCount < 3) Debug.Log("Update, frame " + Time.frameCount); }
void LateUpdate() { if (Time.frameCount < 3) Debug.Log("LateUpdate, frame " + Time.frameCount); }
void OnDisable() { Debug.Log("OnDisable"); }
void OnDestroy() { Debug.Log("OnDestroy"); }
}
Example: a camera that follows the player
The player moves in Update. If the camera also moved in Update, it might run before the player and lag one frame behind, which looks jittery. LateUpdate guarantees the player has already moved.
using UnityEngine;
public class FollowCamera : MonoBehaviour
{
[SerializeField] private Transform target;
[SerializeField] private Vector3 offset = new Vector3(0f, 5f, -8f);
void LateUpdate()
{
if (target == null) return;
transform.position = target.position + offset;
transform.LookAt(target);
}
}
Example: subscribing to events safely
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneListener : MonoBehaviour
{
void OnEnable()
{
SceneManager.sceneLoaded += HandleSceneLoaded;
}
void OnDisable()
{
// Always unsubscribe. Otherwise the event keeps a reference to a destroyed object.
SceneManager.sceneLoaded -= HandleSceneLoaded;
}
void HandleSceneLoaded(Scene scene, LoadSceneMode mode)
{
Debug.Log("Loaded " + scene.name);
}
}
Common Mistakes
- Relying on the order between different objects. Unity does not promise that object A's
Awakeruns before object B'sAwake. The rule to rely on: allAwakecalls for objects in a loaded scene happen before anyStart. So set up yourself inAwakeand talk to others inStart. (If you really need a fixed order, use Project Settings > Script Execution Order.) - Reading input in FixedUpdate.
Input.GetKeyDownis only true for one frame, andFixedUpdatemight not run that frame, so presses get missed. Read input inUpdate, store it in a variable, and use it inFixedUpdate. - Heavy work in Update.
GameObject.FindorGetComponentevery frame is slow. Cache the result inAwake/Start. - Empty Update methods. An empty
Update()still has a small cost. Delete it if you don't use it.
See also
- MonoBehaviour
- Working with Update & FixedUpdate
- Time (deltaTime and fixedDeltaTime)
- Coroutines
This page is a simplified, AI-assisted interpretation. For the complete and authoritative reference, see the official Unity documentation.