Manual Initialization
By default, character components initialize through Unity’s Awake, OnEnable, and Start callbacks. Manual initialization lets project code defer the participating components’ initialization while assembling a character. Keep the character inactive until its required data is ready, then activate and initialize it synchronously before Unity advances to another lifecycle callback or frame.
When to use it
Use manual initialization when a character needs project setup before its participating components initialize:
- A spawner must assign ownership, initial configuration, or a transform before simulation registration.
- A networking implementation must establish authority before the local input and camera route is attached.
- A save system must provide configuration before initialization, then restore any runtime values through their supported APIs after the required components exist.
- A pool needs control over activation. Re-enabling a initialized instance does not rerun its completed Awake/Start phases; reset its gameplay state through the pool’s own reset workflow.
If the character can simply be instantiated and run, use the ordinary flow and skip this page.
How the deferral works
Opsive.UltimateCharacterController.Game.CharacterInitializer is a scene singleton that owns three callbacks: OnAwake, OnEnable, and OnStart.
With Auto Initialization enabled—the default—the participating components initialize directly from their Unity callbacks. With it disabled, those phases subscribe to CharacterInitializer and return. This does not suspend every callback on an active character: Ultimate Character Locomotion’s Unity Start still runs, and Item Handler’s Update needs references populated by its deferred initialization. Do not leave an active character waiting across frames.
These components participate in the deferral:
| Area | Components |
|---|---|
| Character | Character Locomotion, Character Handler, Animation Monitor, Character Foot Effects |
| Third person | Perspective Monitor |
| Items | Inventory, Item Set Manager, Item Handler |
| Traits | Character Attribute Manager, Character Health, Character Respawner |
Each deferred handler unsubscribes when it runs. Awake/Start initialization is normally once per instance, while participating OnEnable handlers can subscribe again on later activations. The three callback fields are nullable Action delegates; invoke them with ?.Invoke() so an empty phase is safe.
Disable automatic initialization
CharacterInitializer.AutoInitialization returns true whenever no initializer instance exists, so the singleton must exist and be configured before the character’s own Unity callbacks run. There are two ways to arrange this:
- Add a Character Initializer component to a scene GameObject and disable its Auto Initialization field. Ensure the initializer’s
Awakeruns before the character’s — the reliable way is to keep the character GameObject inactive in the scene or instantiate it later, as shown below. - Set the property from code before the character exists. Assigning
CharacterInitializer.AutoInitialization = falsecreates the singleton automatically if one is not already present.
using Opsive.UltimateCharacterController.Game;
// Run before the character GameObject is activated or instantiated.
CharacterInitializer.AutoInitialization = false;
If a character’s Awake runs while no initializer exists, that component initializes immediately and does not participate in the deferred sequence.
Initialize the character
Prepare the inactive character’s configuration first. Then activate it and complete all pending phases in the same call, without yielding or waiting for another frame. The initializer is scene-wide, so invoking a phase runs all subscribers currently waiting for that phase.
using Opsive.UltimateCharacterController.Camera;
using Opsive.UltimateCharacterController.Game;
using UnityEngine;
public class CharacterSpawner : MonoBehaviour
{
[Tooltip("A character which starts inactive in the scene.")]
[SerializeField] protected GameObject m_Character;
[SerializeField] protected CameraController m_CameraController;
private void Awake()
{
// Must run before any character to be deferred is activated.
CharacterInitializer.AutoInitialization = false;
}
public void SpawnCharacter()
{
if (m_Character == null || m_Character.activeSelf) { return; }
var initializer = CharacterInitializer.Instance;
if (initializer == null) { return; }
// Assign required transform, ownership, and initial configuration here.
m_Character.SetActive(true);
initializer.OnAwake?.Invoke();
initializer.OnEnable?.Invoke();
initializer.OnStart?.Invoke();
if (m_CameraController != null) {
m_CameraController.Character = m_Character;
}
}
}
Invoke pending callbacks in OnAwake, OnEnable, OnStart order. Awake phases cache references and initialize structures, including Item Set Manager; Enable phases register participating components for simulation; Start phases complete dependencies such as Inventory and Item Handler. Null-safe invocation skips a phase with no subscribers. Keep this sequence synchronous when automatic initialization is disabled.
Assign the Camera Controller’s Character after initialization. The camera does not initialize the character, and assigning it beforehand does not substitute for the callbacks.
Character Manager uses the same mechanism
The builder preserves the previous Auto Initialization value while configuring components. If that value was already false, AddEssentials and BuildCharacterComponents leave the callbacks to the caller; complete the synchronous sequence above after the build.
When the previous value was true, AddEssentials invokes pending Awake and Enable callbacks, while BuildCharacterComponents invokes pending Awake callbacks. Neither invokes OnStart directly; the ordinary Unity Start path can complete that phase with automatic initialization restored. Do not assume every builder call has completed all three phases, and use null-safe invocation for any pending manual callbacks.
Verify the result
- Enter Play Mode with the character inactive and confirm the Console reports no missing-manager or null-reference errors before the spawn call.
- Trigger the initialization and confirm the character appears, receives input, and moves.
- Select the character and confirm that Ultimate Character Locomotion shows its Movement Type, Abilities, and colliders as expected.
- Confirm the camera follows the intended character and that no second character is being driven by the same input.
- If items are used, equip one and confirm Inventory and Item Set Manager report the expected runtime state.
Troubleshoot common results
- The character initializes immediately despite the setting: The initializer did not exist when the character’s
Awakeran. Keep the character inactive, or setAutoInitializationfrom code that runs earlier. - Activation produces errors or leaves the character idle: Complete all pending callbacks synchronously after activation. Do not defer them to another frame; some ordinary Unity callbacks still execute while automatic initialization is disabled.
- The character moves but has no camera: The Camera Controller’s Character was not assigned after initialization.
- Items do not equip: Verify the Awake phase initialized Item Set Manager and its references, then verify Inventory and Item Handler completed their Start phases. Check the configured collection, rules, and loadout as well.
- Repeated direct callback invocation throws: A delegate can be null after its final subscriber removes itself. Use
?.Invoke(). Re-enabling an existing character can add new Enable subscribers, but does not recreate its completed Awake/Start initialization or reset its gameplay state.