You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity从URL下载图片时编辑器冻结问题求助

Unity编辑器冻结原因及解决方案

冻结原因

你的代码触发了死锁,导致Unity主线程完全阻塞:

  • 在SetImage方法中调用textureTask.Result,会强制阻塞当前主线程,等待异步任务完成。
  • GetRemoteTexture中的await Task.Delay需要回到主线程才能继续执行后续逻辑(Unity异步上下文默认绑定主线程)。
  • 主线程被Result卡死,无法处理await的回调,异步任务永远无法完成,形成循环等待的死锁,最终Unity编辑器完全冻结,连Debug.Log都无法输出(日志输出依赖主线程处理)。

另外代码存在冗余:连续调用两次Sprite.Create,第一次的结果未被使用。

修复方案

1. 用async/await替代Task.Result避免死锁

修改GenerateCard的SetImage为异步方法,同时让按钮触发的LoadSprite支持异步:

// 按钮挂载的脚本
[SerializeField] private SpriteRenderer card;
[SerializeField] private string url;

// Unity 2019.3+支持按钮直接调用async void方法
public async void LoadSprite()
{
    GenerateCard setCardSprite = new GenerateCard();
    await setCardSprite.SetImage(card, url);
}
// GenerateCard类
public class GenerateCard
{
    public async Task SetImage(SpriteRenderer card, string url)
    {
        Texture2D cardimage = await DownloadImages.GetRemoteTexture(url);
        
        if (cardimage == null)
        {
            Debug.LogError("加载卡牌纹理失败");
            return;
        }

        Rect rec = new Rect(0, 0, cardimage.width, cardimage.height);
        // 仅创建一次Sprite,锚点设为中心更符合常规卡牌显示需求
        Sprite cardSprite = Sprite.Create(cardimage, rec, new Vector2(0.5f, 0.5f), 100f);
        card.sprite = cardSprite;
    }
}

2. 优化异步等待逻辑(可选)

原DownloadImages中的循环等待可以用更高效的方式替代,避免频繁的Task.Delay:

public class DownloadImages
{
    public static async Task<Texture2D> GetRemoteTexture(string url)
    {
        Debug.Log("function was called");
        using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(url))
        {
            Debug.Log("begins request");
            AsyncOperation asyncOp = www.SendWebRequest();

            // 用TaskCompletionSource包装AsyncOperation,等待请求完成
            var completionSource = new TaskCompletionSource<bool>();
            asyncOp.completed += _ => completionSource.SetResult(true);
            await completionSource.Task;

            Debug.Log("finished waiting");
            if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError)
            {
#if DEBUG
                Debug.Log($"{www.error}, URL:{www.url}");
#endif
                return null;
            }
            else
            {
                Debug.Log("Texture downloaded");
                return DownloadHandlerTexture.GetContent(www);
            }
        }
    }
}

关键说明

  • Unity是单线程模型,任何阻塞主线程的操作都会导致编辑器/游戏冻结,绝对不要在主线程中调用Task.Result或Task.Wait()。
  • 所有Unity API(如SpriteRenderer.sprite赋值、Sprite.Create)必须在主线程执行,async/await在Unity中默认会回到主线程上下文,无需额外处理线程切换。

内容的提问来源于stack exchange,提问作者Gurkenschnitzel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 04:35:38