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

C#非MonoBehaviour类中添加1秒动画延迟的实现难题

非MonoBehaviour类中实现延迟动画的可行方案

针对你的场景:AnimationManager不是继承自MonoBehaviour无法用协程,DoSomething因含ref参数无法转为async Task,以下是三种可行解决方案:


方案1:使用Unity协程包装器(推荐)

通过一个独立的MonoBehaviour类托管协程,让非MonoBehaviour类也能调用协程实现延迟,完全贴合Unity工作流:

步骤1:创建协程托管类

public class CoroutineRunner : MonoBehaviour
{
    public static CoroutineRunner Instance { get; private set; }

    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
    }

    public void RunCoroutine(IEnumerator coroutine)
    {
        StartCoroutine(coroutine);
    }
}

将这个脚本挂载到场景中的空GameObject上(比如命名为CoroutineManager),确保场景加载时它存在。

步骤2:修改AnimationManager的方法

public class AnimationManager
{
    public static string CreateAnimation(GameData data)
    {
        Sword newSword = new Sword(data.SwordData);
        string returnString = newSword.GetSwordString();
        
        AnimateSwords(data.SwordData, data.SwordObjects, returnString);
        return returnString; // 补充原代码遗漏的return语句
    }

    public static void AnimateSwords(SwordData data, List<Swords> swordObjects, string returnString)
    {
        // 委托给协程托管类执行延迟动画
        CoroutineRunner.Instance.RunCoroutine(DelayedAnimationLogic(data, swordObjects, returnString));
    }

    private static IEnumerator DelayedAnimationLogic(SwordData data, List<Swords> swordObjects, string returnString)
    {
        // 延迟1秒
        yield return new WaitForSeconds(1f);
        // 这里写你的动画逻辑
        foreach (var sword in swordObjects)
        {
            // 示例:播放剑的动画
            sword.PlayAnimation(data.AnimationClip);
        }
    }
}

方案2:使用async/await结合主线程调度

利用Task.Delay实现延迟,同时通过主线程调度器确保Unity API在主线程执行:

步骤1:创建主线程调度器

public class UnityMainThreadDispatcher : MonoBehaviour
{
    public static UnityMainThreadDispatcher Instance { get; private set; }
    private readonly Queue<Action> _pendingActions = new Queue<Action>();

    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
        }
        else
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
    }

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

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

同样挂载到场景中的空GameObject上。

步骤2:修改AnimateSwords为异步方法

public static async void AnimateSwords(SwordData data, List<Swords> swordObjects, string returnString)
{
    // 延迟1秒
    await Task.Delay(1000);
    // 调度到主线程执行动画(Unity API必须在主线程调用)
    UnityMainThreadDispatcher.Instance.Enqueue(() =>
    {
        // 动画逻辑
        foreach (var sword in swordObjects)
        {
            sword.PlayAnimation(data.AnimationClip);
        }
    });
}

方案3:使用System.Timers.Timer

通过定时器实现延迟,同样需要主线程调度确保Unity API正常执行:

public static void AnimateSwords(SwordData data, List<Swords> swordObjects, string returnString)
{
    var delayTimer = new System.Timers.Timer(1000);
    delayTimer.Elapsed += (sender, e) =>
    {
        delayTimer.Stop();
        delayTimer.Dispose();
        // 调度到主线程执行动画
        UnityMainThreadDispatcher.Instance.Enqueue(() =>
        {
            // 动画逻辑
            foreach (var sword in swordObjects)
            {
                sword.PlayAnimation(data.AnimationClip);
            }
        });
    };
    delayTimer.Start();
}

(此方案依赖方案2中的UnityMainThreadDispatcher)


方案对比

  • 方案1:最符合Unity开发习惯,无需处理线程问题,协程天然在主线程执行,推荐使用。
  • 方案2:代码简洁,适合熟悉异步编程的开发者,但需注意async void的异常处理。
  • 方案3:适合习惯传统定时器的场景,但线程处理逻辑较繁琐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 18:05:37