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

Unity C#中定时器结束后指定代码行未执行问题

问题原因与解决方案

核心问题

Unity中所有操作GameObject、Transform等组件的API只能在主线程调用,你用Task.Run开启了后台线程,在后台线程里修改transform的操作是非法的,要么不会执行,要么会触发线程安全异常(可查看Unity控制台确认)。


方案一:使用Unity原生协程(推荐)

这是Unity处理延迟逻辑最标准、最简单的方式:

using UnityEngine;
using System.Collections;

public class ClickingBehavior : MonoBehaviour
{
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            gameObject.transform.localScale += new Vector3(1, 1, 1);
            // 启动协程执行延迟逻辑
            StartCoroutine(ScaleBackAfterDelay());
        }
    }

    // 协程方法:等待2秒后缩放回原尺寸
    IEnumerator ScaleBackAfterDelay()
    {
        yield return new WaitForSeconds(2f);
        gameObject.transform.localScale += new Vector3(-1, -1, -1);
    }
}

方案二:基于Task的主线程调度

如果一定要用Task/async,需要把修改Transform的逻辑切回主线程执行,先实现一个主线程调度器:

using UnityEngine;
using System.Collections.Generic;
using System.Threading.Tasks;

public class MainThreadDispatcher : MonoBehaviour
{
    private static MainThreadDispatcher _instance;
    private readonly Queue<System.Action> _actions = new Queue<System.Action>();

    public static MainThreadDispatcher Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = FindObjectOfType<MainThreadDispatcher>();
                if (_instance == null)
                {
                    var dispatcherObj = new GameObject("MainThreadDispatcher");
                    _instance = dispatcherObj.AddComponent<MainThreadDispatcher>();
                    DontDestroyOnLoad(dispatcherObj);
                }
            }
            return _instance;
        }
    }

    private void Update()
    {
        lock (_actions)
        {
            while (_actions.Count > 0)
            {
                _actions.Dequeue().Invoke();
            }
        }
    }

    public void Enqueue(System.Action action)
    {
        lock (_actions)
        {
            _actions.Enqueue(action);
        }
    }

    public static async Task RunOnMainThread(System.Action action)
    {
        var tcs = new TaskCompletionSource<bool>();
        Instance.Enqueue(() =>
        {
            action();
            tcs.SetResult(true);
        });
        await tcs.Task;
    }
}

再修改你的原有代码:

using UnityEngine;
using System.Threading.Tasks;

public class ClickingBehavior : MonoBehaviour
{
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            gameObject.transform.localScale += new Vector3(1, 1, 1);
            _ = ScaleBackAsync();
        }
    }

    async Task ScaleBackAsync()
    {
        await Task.Delay(2000);
        // 切回主线程执行Transform修改
        await MainThreadDispatcher.RunOnMainThread(() =>
        {
            gameObject.transform.localScale += new Vector3(-1, -1, -1);
        });
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 13:47:31