ThreadHarmonizer guide

Setup

Go from a clean package import to a safe first optimization. Analyze the project, choose the appropriate execution model, inspect the generated result, and validate it in the scenes that matter.

Before you begin

  • Work in a Unity project with scripts available as source files.
  • Commit the project or create a backup before a large batch rewrite. ThreadHarmonizer keeps snapshots, but version control remains the strongest production safety net.
  • Open the project once after importing the package so Unity can compile the included assemblies and refresh the editor integration.

1. Import ThreadHarmonizer

Import the package from the Unity Asset Store into the Unity project you want to analyze. Let Unity finish compiling before opening any ThreadHarmonizer window. The package includes the runtime engine, rewrite services, editor UI, project analysis, and optional IDE diagnostics.

2. Bootstrap the required runtime manager

ThreadHarmonizerManager is required for Classic Multithreading and explicit worker/main-thread hand-offs. It owns the shared worker pool and the main-thread synchronization queue.

Auto-create Manager is enabled by default. In the standard setup, no manual bootstrap is required.
  1. Import the package and let Unity finish compiling.
  2. Leave Window > ThreadHarmonizer > Options > Auto-create Manager enabled.
  3. Enter Play Mode. Before scene Awake callbacks, ThreadHarmonizer reuses an existing enabled manager or creates one automatically.
  4. Only when automatic creation is deliberately disabled, add a manager with GameObject > ThreadHarmonizerManager.

The active manager is a singleton and uses DontDestroyOnLoad. Duplicate managers are rejected, and the shared worker pool is disposed when the application quits rather than during ordinary scene changes.

3. Open the Project Optimizer

Open Window > ThreadHarmonizer > Project Optimizer. The project view lists scripts found by the current analysis. Before every optimization action, ThreadHarmonizer refreshes that analysis so newly created scripts and changed dependencies are included.

Select one or more scripts, or use the broader project workflow. Scripts that cannot be changed safely or would not gain meaningful work are shown as skipped or disabled with a reason. A skipped script is not a project failure; it is the tool preserving code whose structure does not justify a rewrite.

4. Choose the optimization mode

4.1 Auto IntegrationEvaluates the script and chooses the strongest safe path. It keeps the source unchanged when neither mode provides a meaningful improvement.
4.2 Classic MultithreadingFits suitable MonoBehaviour logic that combines Unity-facing state with substantial Unity-independent calculation.
4.3 Unity Job SystemFits data-oriented, batchable workloads that can use native value-type data and avoid arbitrary scene access.

4.1 Auto Integration

Auto Integration prefers Unity Jobs for suitable data-oriented workloads and Classic Multithreading when the script’s Unity-facing structure makes that path more useful.

4.2 Classic Multithreading

A rewritten class can inherit from MonoBehaviourMultithreaded, register AddFunction(ParallelUpdate), cache Unity-bound values on the main thread, calculate on workers, and apply final Unity changes through EnqueueOnMainThread.

4.3 Unity Job System

Jobs cannot contain managed classes, most Unity object APIs, or arbitrary scene access. When appropriate, ThreadHarmonizer creates job-oriented state, schedules work, and synchronizes results later in the frame or on the configured delayed-frame path. It avoids an immediate Schedule(...).Complete() pair because that would remove the benefit of scheduling.

5. What ThreadHarmonizer changes

Main-thread values are collected or cached where possible, Unity writes are moved to the main-thread queue, and worker code is generated only where the analysis can preserve the program structure. A compiler preflight checks generated scripts before they replace the original source.

ClassicCreates a worker path such as ParallelUpdate, with cached main-thread data and queued Unity applies.
JobsUses the smallest appropriate job interface, native data only where required, and a later result-apply phase.
Worker tailsMoves only clearly isolated calculations whose results are not required synchronously by later code.

Using ThreadHarmonizerManager in your own code

Compute only data that is independent from Unity APIs on a worker. Then enqueue the final Unity object assignment back to the main thread. The hand-off is asynchronous, so code must not expect the result immediately after EnqueueOnWorker.

var target = transform;
var startPosition = target.position;

ThreadHarmonizerManager.EnqueueOnWorker(() =>
{
    var nextPosition =
        startPosition + Vector3.right * 2f;

    ThreadHarmonizerManager.EnqueueOnMainThread(() =>
    {
        target.position = nextPosition;
    });
});

Prefer cached values over GetFromMainThread, especially inside loops. Repeated synchronous main-thread fetches can consume the benefit of worker execution.

Diagnostics and validation

Keep ThreadHarmonizer.CodeAnalysis.dll with the package’s editor and analyzer installation. After Unity and the IDE refresh, the diagnostics identify Unity main-thread API usage inside worker code.

  1. Optimize a small, representative selection first.
  2. Let Unity compile the generated code.
  3. Open the affected scenes and test the relevant gameplay in Play Mode.
  4. Profile the original and rewritten paths with the real workload.
  5. Review diagnostics, skipped-script reasons, and generated source before expanding the change.

Normalize, restore, and keep control

Every successful rewrite stores a snapshot. Restore returns a script to its saved pre-change version. Normalize removes supported current Classic or Job System rewrite patterns and returns the script to a neutral MonoBehaviour structure.

When switching modes, ThreadHarmonizer first normalizes a supported previous rewrite and then analyzes the neutral result for the newly selected path. This avoids stacking incompatible transformations.