# Startup Script Management

Covered in [Organizing Startup Scripts](/unreal-python-recipe-book/startup-and-shutdown-scripts/organizing-startup-scripts.md), my `init_unreal.py` file usually looks something like this:

```python
from recipe_book import startup
startup.run()
```

The `startup` module is where I organize everything I want to happen on Unreal startup, split into two main sections:

1. **Pre Startup** - Python code that can is safe to run immediately the moment Python is loaded
   1. Examples might include:
      1. Initializing a custom Python logger
      2. Register metadata names
      3. Environment setup, such as fixing the sys.path if required as part of a pipeline
      4. Initialize Python classes other code might rely on
      5. Loading external config data or packages
2. **Post Startup** - Python code to run ***after*** the Editor is fully loaded
   1. I consider this step ready once the Asset Registry has scanned the entire UE Project
   2. Examples might include:
      1. Initializing the Python-defined Editor Menus
      2. Opening Editor Utility Widget startup tools (such as a homepage tool listing all ShotGrid tasks)
      3. Running any tools that rely on the Asset Registry

***

## Waiting for the Asset Registry&#x20;

The main separator of my Pre and Post Startup logic is whether the Asset Registry has finished loading the Unreal Project.&#x20;

Thankfully, there is an easy enough function to reference on the Asset Registry: [is\_loading\_assets()](https://docs.unrealengine.com/5.2/en-US/PythonAPI/class/AssetRegistry.html#unreal.AssetRegistry.is_loading_assets)

```python
# the Asset Registry
asset_registry_helper = unreal.AssetRegistryHelpers()
asset_registry        = asset_registry_helper.get_asset_registry()

print(
    f"Is Asset Registry Ready? "
    f"{'no' if asset_registry.is_loading_assets() else 'yes'}"
)
```

We can use this with [register\_slate\_post\_tick\_callback()](https://docs.unrealengine.com/5.2/en-US/PythonAPI/module/unreal.html#unreal.register_slate_post_tick_callback) to track the Asset Registry on startup to wait until it's ready:

```python
asset_registry_helper = unreal.AssetRegistryHelpers()
asset_registry        = asset_registry_helper.get_asset_registry()

startup_id = None

def wait_for_asset_registry(ignore=None):
    """Wait until the Asset Registry is ready before continuing"""
    if asset_registry.is_loading_assets():
        print(f"Still waiting on the Asset Registry...")
        return
    
    print(f"Asset Registry is ready!")
    
    # We can now remove the callback and continue
    global startup_id 
    unreal.unregister_slate_post_tick_callback(startup_id)
    
    # do the thing or call the next function here
    pass


# start the callback if not already running
if not startup_id:
    startup_id = unreal.register_slate_post_tick_callback(wait_for_asset_registry)
```

And here's an example of running this during startup on a large project:

<figure><img src="/files/N1kXNjniNZ4pcVXUDxCW" alt=""><figcaption></figcaption></figure>

{% hint style="info" %} <mark style="color:yellow;">Note</mark>: The Asset Registry data does get cached on disk. Depending on PC specs, project size, and the last time the project was opened, the Asset Registry might be fully loaded by the time Python initializes
{% endhint %}

***

## Full Startup Example

building off of the <mark style="color:green;">wait\_for\_asset\_registry</mark> function, my startup module generally has the following in it:

* A dedicated function that contains all Pre Startup commands
* A dedicated function that contains all Post Startup commands
* The Wait For Asset Registry callback function, which calls Post Startup when complete
* A run() function that calls Pre Startup and sets up the Wait For Asset Registry callback
  * the `run()` function is the main entry point in this module, and is the only function that should be called externally

And here's what that code looks like:

```python
asset_registry_helper = unreal.AssetRegistryHelpers()
asset_registry        = asset_registry_helper.get_asset_registry()

startup_id = None

def on_pre_startup():
    """Scripts that can run immediately on Editor Startup"""
    print("Running Pre Startup Scripts")
    # Import and run Pre Startup scripts here


def on_post_startup():
    """Scripts that should run after the Asset Registry is fully loaded"""
    print("Running Post Startup Scripts")
    # Import and run Post Startup scripts here


def wait_for_asset_registry(ignore=None):
    """Wait until the Asset Registry is ready before continuing"""
    if asset_registry.is_loading_assets():
        print(f"Still waiting on the Asset Registry...")
        return
    
    print(f"Asset Registry is ready!")
    
    # We can now remove the callback and continue
    global startup_id 
    unreal.unregister_slate_post_tick_callback(startup_id)
    
    # run Post Startup
    on_post_startup()


def run():
    """run Pre Startup and then schedule Post Startup"""
    
    # Pre Startup can run right away
    on_pre_startup()
    
    # Schedule Post Startup
    global startup_id
    if not startup_id:
        startup_id = unreal.register_slate_post_tick_callback(wait_for_asset_registry)
    else:
        unreal.log_warning("Unreal Startup has already been run!")
```

In this setup, the only thing that needs to be updated / maintained are the `on_pre_startup()` and `on_post_startup()` functions - we shouldn't need to ever touch `run()` or `wait_for_asset_registry()`.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bkortbus.gitbook.io/unreal-python-recipe-book/startup-and-shutdown-scripts/startup-script-management.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
