Under Construction
Unity20 min170 views

Multithreading in mobile games and builds WebGL how is it different?

Minh Khoa

Minh Khoa

Author

In short: Mobile supports normal C# threads# and the Job System. Unity Web, on the other hand, Thread / Task.Run still does not support them; only from Unity 6.4C## Jobs can [BurstCompile] be run in parallel if configured correctly.

Version matters a lot: Unity 6.3 LTS and 6.4+ behave differently. On 6.3C## on the Web, there is still only one thread. In 6.4Burst Jobs are the exception and can use real worker threads.

image.png## Simply put

  • Mobile: the kitchen has many sous-chefs. You can assign work through Thread, Task, or the Job System.
  • Web 6.3: has only one C# chef#. Coroutines only help the chef switch to another task while waiting; they do not create more people.
  • Web 6.4: also has an extra team of sous-chefs, but they only accept “work tickets” that have been Job System + Burst standardized.
Mobile:  Main ─┬─ Task / Thread
               └─ Jobs / Burst ──► worker threads

Web 6.3: Main ──► toàn bộ C#

Web 6.4: Main ─┬─ C# thông thường
               └─ Burst Jobs ─────► worker threads

Quick comparison

TaskMobileWeb 6.3Web 6.4+
Thread, Task.RunUsableNot supportedStill not supported
Jobs without BurstCan run on workerRun on main threadRun on main thread
Jobs with [BurstCompile]Run in parallelNot yet running in parallelCan run in parallel
Coroutine / AwaitableAsynchronous, does not create threads by itselfAsynchronousAsynchronous
Edit GameObject / Transform / UIMain threadMain threadMain thread

Mobile: work can be moved to another thread

For example, heavy data computation that does not need Unity API:

async Awaitable<int> CalculateOnMobile(int[] input)
{
    await Awaitable.BackgroundThreadAsync();

    // Chỉ tính dữ liệu thuần, không gọi GameObject hay Transform.
    int result = HeavyCalculation(input);

    await Awaitable.MainThreadAsync();
    return result;
}

Mobile runs natively on Android/iOS so background threads can use CPU different cores.

But do not move everything to a worker thread. Creating GameObject, editing Transform, Animator or UI still has to be done on the main thread. With many small calculations on large arrays, Job System + Burst is often easier to control and more efficient than creating a large number of Tasks yourself.

Web 6.4: real multithreading, but only through Burst Jobs

Example of a job processing many elements:

using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;

[BurstCompile]
public struct SquareJob : IJobFor
{
    [ReadOnly] public NativeArray<int> input;
    [WriteOnly] public NativeArray<int> output;

    public void Execute(int i)
    {
        output[i] = input[i] * input[i];
    }
}

Schedule the job from the main thread:

handle = new SquareJob
{
    input = input,
    output = output
}.ScheduleParallel(input.Length, 64, default);

You should schedule it in Updatedo other work, then Complete in LateUpdate. If you call Completeright after scheduling, the main thread will wait again and the benefit of multithreading drops sharply.

The most important point is [BurstCompile]:

  • With Burst: the job can run on a worker thread.
  • Without Burst: the Web treats it as ordinary C## and runs it on the main thread.
  • Task.Run do not get to “piggyback” on this capability.

What is needed for Burst Jobs to run multithreaded on the Web?

If one of the following conditions is missing, the Web cannot be considered to have worker threads:

  1. Use Unity 6.4+.
  2. Burst package 1.8.26+.
  3. Job has [BurstCompile].
  4. Enable Enable Native C/C++ Multithreading in Web Player Settings. The name is a bit misleading: in Unity 6.4, this option enables both native threads and Burst Job threads.
  5. Host in a secure context, usually HTTPS.
  6. Server returns the required headers COOP, COEP, CORP; the browser supports SharedArrayBuffer.

Because the configuration is in both Unity and the server, being able to run in the Editor does not prove that the deployed build will run with multithreading.

What if 6.3 Web

or code that cannot use Burst?

async Awaitable<int> CalculateInChunks(int[] data)
{
    int total = 0;

    for (int i = 0; i < data.Length; i++)
    {
        total += Process(data[i]);

        if ((i + 1) % 500 == 0)
            await Awaitable.NextFrameAsync();
    }

    return total;
}

Split the work across multiple frames: This way helps the tab avoid freezing, but itdoes not run faster

. One person still does all the work, only resting between each turn so Unity can render the frame in time. async That is also why

  • await does not mean multithreading:
  • used to wait for a task to complete. NextFrameAsync Coroutine /
  • used to spread work across multiple frames. + Job CPU Burst is the way to take advantage of multiple 6.4.

core on the Web

  • So which approach should you choose? APIDownload a file, call , load scene: AsyncOperation use Awaitable,
  • CPU or Coroutine. heavy on Mobile: + prioritize the Job System# Burst; background threads are suitable for independent C
  • CPU data blocks. 6.4+: heavy on Web
  • use Burst Job if it meets the deployment conditions. 6.3 Web or logic that cannot use Burst:
  • reduce workload, cache, split across multiple frames, or move the appropriate calculations to the server. Modify Unity objects:
  • return to the main thread. Always profile on a real build

and a real browser. Easy-to-remember rule: Coroutine/Awaitable. If you need to wait, use async. If you need to spread load across multiple frames, use CPU If you need to take advantage of multiple + core, use Jobs and Burst — but check the version and platform.