From 02e5be1f6f9916adf847f7240376b09b08c0d056 Mon Sep 17 00:00:00 2001 From: Niclas Bolle Date: Fri, 16 Oct 2026 14:24:47 +0200 Subject: [PATCH] fix: off-main-thread null check in ReleaseMemoryTexture/ReleaseMemorySprite When a Reference is finalized without Dispose(), its finalizer clears the memory cache from the GC finalizer thread. The off-main-thread branch of ReleaseMemoryTexture / ReleaseMemorySprite called IsNull(), whose Unity == throws "EnsureRunningOnMainThread can only be called from the main thread". The cache entry was already removed, so the texture was never destroyed. Use ReferenceEquals for the off-thread pre-check; the UniTask.Post callback still does the full IsNull() check on the main thread. Co-Authored-By: Claude Opus 5.5 --- .../Assets/root/Runtime/Future/Types/FutureSprite.cs | 4 ++-- .../Assets/root/Runtime/Future/Types/FutureTexture.cs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Unity-Package/Assets/root/Runtime/Future/Types/FutureSprite.cs b/Unity-Package/Assets/root/Runtime/Future/Types/FutureSprite.cs index f702354..c058ddf 100644 --- a/Unity-Package/Assets/root/Runtime/Future/Types/FutureSprite.cs +++ b/Unity-Package/Assets/root/Runtime/Future/Types/FutureSprite.cs @@ -87,8 +87,8 @@ public static void ReleaseMemorySprite(Sprite sprite, DebugLevel logLevel = Debu } // 'sprite.texture' could be called only from main thread - // checking sprite.IsNull is enough until we are in main thread - if (sprite.IsNull()) + // Unity's == (used by IsNull) throws off the main thread, e.g. from a Reference finalizer + if (ReferenceEquals(sprite, null)) return; UniTask.Post(() => diff --git a/Unity-Package/Assets/root/Runtime/Future/Types/FutureTexture.cs b/Unity-Package/Assets/root/Runtime/Future/Types/FutureTexture.cs index 72d843b..bd97028 100644 --- a/Unity-Package/Assets/root/Runtime/Future/Types/FutureTexture.cs +++ b/Unity-Package/Assets/root/Runtime/Future/Types/FutureTexture.cs @@ -46,7 +46,8 @@ public static void ReleaseMemoryTexture(Texture2D obj, DebugLevel logLevel = Deb UnityEngine.Object.DestroyImmediate(obj); return; } - if (obj.IsNull()) + // Unity's == (used by IsNull) throws off the main thread, e.g. from a Reference finalizer + if (ReferenceEquals(obj, null)) return; UniTask.Post(() =>