UnityMainThreadDispatcher 是做什么的?

2023-11-23

我读了这段代码。

https://github.com/johnjcsmith/iPhoneMoCapUnity/blob/master/Assets/NetworkMeshAnimator.cs

代码第62行周围有如下描述。

这是在做什么处理?

    if (UnityMainThreadDispatcher.Exists()) {
        dispatcher = UnityMainThreadDispatcher.Instance ();
    } 

GitHub 上有代码,但它是 Unity 中的标准功能吗?


这就是为什么你需要一个伪调度员在统一中:

在 Unity 中,大多数对象只能在 Unity 主线程中创建。

但是假设您有一些繁重的任务想要在后台运行,例如Task.Run,在您的任务中,您将无法实例化上述对象,但仍然希望实例化。

有很多解决方案可以解决这个问题,但它们都利用相同的东西:

捕获 Unity 的同步上下文并向其发送消息

这是一种原始的方法,灵感来自 Raymond Chen 的《旧新事物》:

C++/WinRT 羡慕:将线程切换任务引入 C#(WPF 和 WinForms 版本)

其概念如下:在方法中随时切换到特定线程!

公共类型

I线程切换器:

using System.Runtime.CompilerServices;
using JetBrains.Annotations;

namespace Threading
{
    /// <summary>
    ///     Defines an object that switches to a thread.
    /// </summary>
    [PublicAPI]
    public interface IThreadSwitcher : INotifyCompletion
    {
        bool IsCompleted { get; }

        IThreadSwitcher GetAwaiter();

        void GetResult();
    }
}

线程切换器:

using Threading.Internal;

namespace Threading
{
    /// <summary>
    ///     Switches to a particular thread.
    /// </summary>
    public static class ThreadSwitcher
    {
        /// <summary>
        ///     Switches to the Task thread.
        /// </summary>
        /// <returns></returns>
        public static IThreadSwitcher ResumeTaskAsync()
        {
            return new ThreadSwitcherTask();
        }

        /// <summary>
        ///     Switch to the Unity thread.
        /// </summary>
        /// <returns></returns>
        public static IThreadSwitcher ResumeUnityAsync()
        {
            return new ThreadSwitcherUnity();
        }
    }
}

私有类型

线程切换器任务:

using System;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;

namespace Threading.Internal
{
    internal struct ThreadSwitcherTask : IThreadSwitcher
    {
        public IThreadSwitcher GetAwaiter()
        {
            return this;
        }

        public bool IsCompleted => SynchronizationContext.Current == null;

        public void GetResult()
        {
        }

        public void OnCompleted([NotNull] Action continuation)
        {
            if (continuation == null)
                throw new ArgumentNullException(nameof(continuation));

            Task.Run(continuation);
        }
    }
}

线程切换器Unity:

using System;
using System.Threading;
using JetBrains.Annotations;

namespace Threading.Internal
{
    internal struct ThreadSwitcherUnity : IThreadSwitcher
    {
        public IThreadSwitcher GetAwaiter()
        {
            return this;
        }

        public bool IsCompleted => SynchronizationContext.Current == UnityThread.Context;

        public void GetResult()
        {
        }

        public void OnCompleted([NotNull] Action continuation)
        {
            if (continuation == null)
                throw new ArgumentNullException(nameof(continuation));

            UnityThread.Context.Post(s => continuation(), null);
        }
    }
}

统一线程:

using System.Threading;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;

#endif

namespace Threading.Internal
{
    internal static class UnityThread
    {
#pragma warning disable IDE0032 // Use auto property
        private static SynchronizationContext _context;
#pragma warning restore IDE0032 // Use auto property

        public static SynchronizationContext Context => _context;

#if UNITY_EDITOR
        [InitializeOnLoadMethod]
#endif
        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
        private static void Capture()
        {
            _context = SynchronizationContext.Current;
        }
    }
}

Example

尽管这是一种奇特的方法,但它具有巨大的优势,即通过使用单个调用,您可以在同一方法的不同线程中完成工作。下面的代码是用Task.Run但在实例化 Unity 对象时不会产生任何错误,因为它是在正确的线程中完成的。

private static async Task DoWork(CancellationToken token)
{
    token.ThrowIfCancellationRequested();

    var gameObjects = new List<GameObject>();

    await ThreadSwitcher.ResumeUnityAsync();

    for (var i = 0; i < 25; i++)
    {
        if (token.IsCancellationRequested)
            token.ThrowIfCancellationRequested();

        await Task.Delay(125, token);

        var gameObject = new GameObject(i.ToString());

        gameObjects.Add(gameObject);
    }
}

现在由您来精细地分割您的工作,因为从本质上讲,Unity 同步上下文并不意味着运行繁重的计算,而是只是实例化您无法从另一个线程获得的东西。

一个简单的例子是生成一些程序网格:

  • do all your maths in your task and produce enough data to create a mesh
    • 即顶点、法线、颜色、uvs
  • switch to Unity thread
    • 根据此数据创建一个网格,PERIOD,这将足够快以至于无法察觉

这是一个有趣的问题,我希望我已经回答了!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UnityMainThreadDispatcher 是做什么的? 的相关文章

随机推荐

  • 如何添加全局 ASP.Net Web Api 过滤器?

    我创建了一个 Web Api 过滤器 使用System Web Http Filters ActionFilterAttribute 但我无法让它在 ASP Net MVC 4 中工作 我尝试将其添加到RegisterGlobalFilte
  • 连接 postgresql 和 codeigniter

    我是 postgresql 的新手 并且已经使用 Codeigniter 一年了 我有一个小型 postgresql 数据库 我想从 Codeigniter 调用它 在我的database php 文件中我有这样的设置 active gro
  • Any、AnyVal、AnyRef、Object 之间有什么关系以及它们在 Java 代码中使用时如何映射?

    我通常会尝试每种组合直到它编译为止 有人可以解释我应该在哪里使用什么吗 我会不同意Chris s answer一方面 课程Any AnyRef and AnyVal are类 但由于 JVM 的内在限制 它们在字节码中不会显示为类 This
  • Python:matplotlib - 概率质量函数作为直方图

    我想在同一个图表上绘制直方图和线图 然而 要做到这一点 我需要将直方图作为概率质量函数 所以我想在 y 轴上有一个概率值 但是 我不知道该怎么做 因为使用normed选项没有帮助 下面是我的源代码和使用数据的预览 我将非常感谢所有的建议 d
  • 如何在运行时更改 Angular Material Datepicker 格式

    我正在研究一个Angular应用程序与Material设计 我正在使用Moment js解析和格式化日期 在我的其中一个页面中 我有一个材料的日期选择器 我遵循了材料的指南来使日期选择器与moment对象 而不是在本机上Date objec
  • 从自定义操作捕获 ArgumentTypeError 异常

    从我自己的自定义操作中抛出 ArgumentTypeError 异常并让 argparse 为我捕获它的最佳实践是什么 看来 argparse 的 try except 块不处理我的自定义操作的此异常 尽管它的内置操作做得很好 class
  • 如何从 checkout 获取 svn 版本号以在 dsl 中使用

    我创建了一个管道作业 并希望获取 svn 版本号 以便在调用 shell 脚本时启用进一步的下游处理 我正在使用类似于以下内容的管道脚本 node Mark the code checkout stage stage Checkout Ge
  • 在一个语句中打印多行,不带前导空格[重复]

    这个问题在这里已经有答案了 因此 对于我的第一个项目 它是一个简单的程序 可以打印您所在班级的姓名以及您就读的高中 让我困惑的一件事是对于其中的一个我必须使用一个print 所有这些的声明 我需要对其进行格式化 以便每条信息位于不同的行上
  • 尽管使用 DebugType=None,Visual Studio 发布仍生成 .pdb 文件

    我正在使用以下发布配置文件从 Visual Studio 中发布控制台应用程序
  • 如何使光标的高度与UITextField中文本的高度相同?

    我的 UITextField 光标太长 下图中 123123 的光标 如何让光标高度与文字高度一致 我偶然发现了这个问题 尽管它有点老了 但我还是觉得有必要回答它 因为接受的答案实际上是不正确的 您确实可以更改光标的高度 或宽度 只是子类化
  • 如何让java类线程安全?

    我有一个java类如下 class User String name String phone public String getName return name public String getPhone return phone 该类
  • 将 System.Drawing.Bitmap 转换为 stdole.StdPicture

    我当前有一个 System Drawing Bitmap 我需要将其转换为 stdole StdPicture 目前我正在使用 var pic stdole StdPicture Microsoft VisualBasic Compatib
  • 如何在 Mountain Lion 上安装 MySQLdb

    我是 Python 新手 在构建 MySQLdb 时遇到问题 试图让 Google AppEngine SDK 运行 我刚刚从 Snow Leopard 升级到 Mountain Lion 并安装了最新的 XCode 4 4 我已经下载了h
  • 无法使用 SelectListitem 获取不同的值

    我试图获取下拉列表的不同值 但是当使用以下语法时 它会带回所有行 有人可以告诉我如何使用正确的语法获取不同的值集吗 IEnumerable
  • Google 云端硬盘文档时间戳

    我假设修改日期搜索字段是修改日期 显然 或上传到驱动器的日期 有没有办法在其本机系统上保留文件的原始创建日期 或者有没有可能修改这个字段 谢谢你 肖恩 您可以使用 File Update 设置上传后的修改日期 https developer
  • Objective C - init 和构造函数之间的区别?

    我试图找到 Objective C 中 init 和构造函数之间的区别 我不是 C 开发人员 但我需要将一些 Objective C 代码转换为 Java 实际上我无法理解两者之间的区别 在 Objective C 中 对象的生成方式分为两
  • 在 Lambda 中捕获值而不是引用 [重复]

    这个问题在这里已经有答案了 我对 Eli Bendersky 给出的这个例子感到有点惊讶 http eli thegreenplace net 2015 the scope of index variables in pythons for
  • 我可以强制子类重写方法而不使其抽象吗?

    我有一个带有一些抽象方法的类 但我希望能够在设计器中编辑该类的子类 然而 设计者不能编辑子类 除非它可以创建父类的实例 所以我的计划是用存根替换抽象方法并将它们标记为虚拟 但如果我创建另一个子类 如果我忘记实现它们 我不会得到编译时错误 有
  • WooCommerce-如何从网址中删除产品和产品类别?

    我在 WordPress 上使用 WooCommerce 它将产品和产品类别添加到 URLs http dev unwaveringmedia com 8dim product category all party supplies htt
  • UnityMainThreadDispatcher 是做什么的?

    我读了这段代码 https github com johnjcsmith iPhoneMoCapUnity blob master Assets NetworkMeshAnimator cs 代码第62行周围有如下描述 这是在做什么处理 i