Skip to content

Non-allocating async/await threading facilities for Unity

License

Notifications You must be signed in to change notification settings

lumpn/unity-threading

Repository files navigation

unity-threading

Non-allocating async/await facilities for Unity. Coroutines that flow across threads, callbacks, and yield instructions.

Disclaimer

You should probably just use UniTask instead of this package. Coroutines are nice, but async is better, and UniTask is a great package with good documentation and an active community.

Installation

Download the entire repository from https://github.com/lumpn/unity-threading and use Unity's built in package manager to add package from disk.

Usage

    IEnumerator SaveAsync()
    {
        saveIcon.SetActive(true); // on Unity thread

        yield return ioThread.Context; // switch to I/O thread
        File.WriteAllBytes("savegame.dat", data); // on I/O thread

        var awaiter = new CallbackAwaiter();
        StorageAPI.WriteAsync("savegame", awaiter.Call);
        yield return awaiter; // wait for callback

        yield return unityThread.Context; // switch back to Unity thread
        saveIcon.SetActive(false); // on Unity thread
    }

Context switching

class SaveGameManager : MonoBehaviour
{
    IThread unityThread, ioThread;

    void Start()
    {
        unityThread = ThreadUtils.StartUnityThread("SaveGameManager", 10, this);
        ioThread = ThreadUtils.StartWorkerThread("Workers", "I/O", ThreadPriority.Normal, 10);        
    }

    void OnDestroy()
    {
        ThreadUtils.StopThread(ioThread);
        ThreadUtils.StopThread(unityThread);
    }

    void Save()
    {
        unityThread.StartCoroutine(SaveAsync());
    }

    IEnumerator SaveAsync()
    {
        saveIcon.SetActive(true); // on Unity thread
        yield return ioThread.Context; // switch to I/O thread

        var data = GatherSaveData();
        File.WriteAllBytes("savegame.dat", data); // on I/O thread

        yield return unityThread.Context; // switch back to Unity thread
        saveIcon.SetActive(false); // on Unity thread
    }
}

Callback handling

class SaveGameManager : MonoBehaviour
{
    IEnumerator LoadAsync(string fileName)
    {
        var awaiter = new CallbackAwaiter<ByteBuffer>();
        StorageAPI.LoadBytesAsync(fileName, awaiter.Call);
        yield return awaiter; // wait for callback

        var buffer = awaiter.arg;
        RestoreSaveData(buffer);
    }
}

Yield instructions

class SaveGameManager : MonoBehaviour
{
    IEnumerator RestoreOptionsAsync()
    {
        busyIndicator.SetActive(true);

        var bundleRequest = AssetBundle.LoadFromFileAsync("options");
        yield return bundleRequest;

        var bundle = bundleRequest.bundle;
        var assetRequest = bundle.LoadAssetAsync<TextAsset>("options.bytes");
        yield return assetRequest;

        var text = (TextAsset)assetRequest.asset;
        var data = text.bytes;

        yield return ioThread.Context;
        File.WriteAllBytes("options.dat", data); // on I/O thread

        // simulate really slow HDD
        yield return new WaitForSeconds(5f); // on I/O thread

        yield return unityThread.Context;
        busyIndicator.SetActive(false);
    }
}

Notes

  • See SwitchContextDemo for details.

About

Non-allocating async/await threading facilities for Unity

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages