Unity3D中的多线程新体验-Timer

前面些时候要研究串口通讯,于是就接触到了多线程,期间呢,笔者想当然的把在线程里面使用了Unity 的 Text。然后就报错,然后呢就遇见了 Loom,嗯,设计的很巧妙,蛮好吃的!
所以,我就把自家曾经写的 Timer,重构了下,于是就有了本文,下面进入正题:

异常&解决方案

非主线程不能调用

Loom 提供的解决方案
Timer 提供的解决方案

Loom的设计

就是把操作Unity组件的逻辑块使用 Action 包裹埋入到非主线程的上下文,但这个线程执行到这个位置就把这些个 Action 抛入MonoBehaviour的 Update中执行他 ,实现的效果如下:

  1. 更优的代码的可读性和逻辑连续性
  2. 更小范围的数据可见性(闭包优势)
  3. 实时与 Unity 组件交互(闭包优势)

Timer的设计

只因为多看了一眼,才发现 Timer 的 TimerDriver 理念 原来跟这个 Loom 是那么的相近:
都是利用委托Action 把逻辑块插入其他逻辑块的上下文,然后利用闭包的优势共享这个被插逻辑块上下文的局部变量。
然后其实呢,执行这个 Action 的是另一个继承了MonoBehaviour 的类,在Timer中 我谓之:TimerDirver。

小结

综上,这个Loom 带来的 Unity多线程 炫酷体验,只需要简单的重构,俺家的 Tiemr 也必定兼并你的特色功能,下面就是重构大体思路

重构 Timer

  1. 剔除Timer 中 UnityEgine 相关的API : Time.realtimeSinceStartup 、Time.time。
  2. 将上述剔除的 CurrentTime 实际驱动 放到 TimerDriver Update中。
  3. 为线程安全,对定时器链表 List<Timer> timers 各处上锁。
  4. 如果在非主线程中TimerDriver初始化会报错,新增 Timer.IntializeDriver(),提供手动初始化TimerDriver 的能力,在主线程初始化不会这样麻烦。

应用场景1-简单的应用

using UnityEngine;
using System.Threading.Tasks;
using QFramework.TimeExtend;
using Timer = QFramework.TimeExtend.Timer;
using UnityEngine.UI;

public class TestForTimer : MonoBehaviour
{
    public Text text;
    private void Awake()
    {
        Timer.IntializeDriver(); //首次初始化不能放在非主线程内。
    }
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.R))
        {
            this.FunctionA();
        }
    }
    internal void FunctionA()
    {
        Task task = new Task(() =>
        {
            string _name = "CreateWithTimer ←";
            Timer.AddTimer(0).OnCompleted(() =>
            {
                text.text = _name;  //先演示异常
                new GameObject(_name);
            });
        });
        task.Start();
    }
}


动画演示


Tips:
先尝试在 Task 内直接更新 Text组件数据 ,失败!
再尝试 Timer 内运行,完美解决报错!

应用场景2 - Http下载

参考:Unity技术博客 - 客户端断点续传 - 简书

using UnityEngine;
using Timer = QFramework.TimeExtend.Timer;
using System;
using System.IO;
using UnityEngine.UI;

public class TestDownload : MonoBehaviour
{
    public string url = "http://localhost:8083/bigFile";
    public string savePath = "";
    public Text finish;
    public Text update;

    HttpDownLoader DownLoader;
    void Awake()
    {
        savePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "TestDownLoad");
        Timer.IntializeDriver();
        Loom.Initialize();
        DownLoader = new HttpDownLoader();
        DownLoader.OnDownLoadCompleted.AddListener(() =>
        {
            this.finish.text = "下载完成!";
        });
        DownLoader.OnDownLoadUpdate.AddListener(v =>
        {
            this.update.text = string.Format("下载进度:{0} %", (v * 100).ToString("f2"));
        });
    }
    private void Start()
    {
        this.DownLoader.DownLoad(url, savePath);
    }
    private void OnDisable()
    {
        this.DownLoader.Close();
    }
}

动画演示


使用 Timer 埋入 Update 事件更新下载进度

Tips:
使用 Timer 或者 Loom 将 OnComplete 和OnUpdate 回调埋进去,实现事件驱动的进度刷新和下载完成提示,无需额外的判断。

扩展阅读

  1. Unity多线程(Thread)和主线程(MainThread)交互使用类——Loom工具分享
  2. 重构后的 Timer -GitHub
  3. Unity技术博客 - 客户端断点续传 - 简书

Unity非主进程内访问Unity组件报错、怎么在其他进程直接操作Unity组件、Unity多线程
可以做为 Loom 插件的课外知识,但不保证这个Timer 能够合理的处理高并发,毕竟笔者是个菜鸡儿,尤其是多线程编程。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351

推荐阅读更多精彩内容

  • Unity 已可使用 Thread、Task 等处理多线程任务,但缺少成熟的多线程任务队列工具,所以在此实现一个,...
    Warl_G阅读 1,252评论 0 2
  • 在这个降低入门门槛的大环境下,Unity 因为考虑到降低门槛,设计之初就是一个单线程,不允许在另外的线程中进行渲染...
    耳朵里有只风阅读 8,259评论 0 5
  • 首先Unity一般是避免使用多线程的,unity提供了一种协程的概念(coroutine) yield,但是这个协...
    _Bob_阅读 4,375评论 0 1
  • 知乎链接:https://zhuanlan.zhihu.com/p/36930662 (阅读体验更好一些。) 四月...
    董夕阅读 1,826评论 1 10
  • 新工作的第7个月,北漂的第16个月,毕业的第17个月……北漂之后我严重怀疑我自己是不是有躁狂症,一点小事儿就易喜...
    韩庚是我前男友阅读 151评论 3 0