Unity主線程和子線程跳轉調用(1)

来源:https://www.cnblogs.com/ferryqiu/archive/2018/01/05/8202911.html
-Advertisement-
Play Games

Unity除了一些基本的數據類型,幾乎所有的API都不能在非unity線程中調用,如果項目中有一段很耗時操作,unity可能會出現“假死”。如果這段操作是和unity無關的,我們可以把這個耗時的操作放到子線程中去運行,防止unity假死提高性能,如下麵這個偽代碼 必須保證LoadLocalFile( ...


  Unity除了一些基本的數據類型,幾乎所有的API都不能在非unity線程中調用,如果項目中有一段很耗時操作,unity可能會出現“假死”。如果這段操作是和unity無關的,我們可以把這個耗時的操作放到子線程中去運行,防止unity假死提高性能,如下麵這個偽代碼

Function
{
    //這個函數會進行大量文件讀寫操作
    LoadLocalFile();

    //這個函數是unity函數
    UnityFunction();
}

  必須保證LoadLocalFile() 不“假死”。怎麼做呢?只要把Function放到多線程中,UnityFunction()回到主線程即可

  網上的做法一般都是借鑒Loom,摘錄一個腳本

  1 using UnityEngine;
  2 using System.Collections;
  3 using System.Collections.Generic;
  4 using System;
  5 using System.Threading;
  6 using System.Linq;
  7 
  8     public class Loom :MonoBehaviour
  9     {
 10         public static int maxThreads = 8;
 11         static int numThreads;
 12 
 13         private static Loom _current;
 14         //private int _count;
 15         public static Loom Current
 16         {
 17             get
 18             {
 19                 Initialize();
 20                 return _current;
 21             }
 22         }
 23 
 24         void Awake()
 25         {
 26             _current = this;
 27             initialized = true;
 28         }
 29 
 30         static bool initialized;
 31 
 32         public static void Initialize()
 33         {
 34             if (!initialized)
 35             {
 36 
 37                 if (!Application.isPlaying)
 38                     return;
 39                 initialized = true;
 40                 var g = new GameObject("Loom");
 41                 _current = g.AddComponent<Loom>();
 42 #if !ARTIST_BUILD
 43                 UnityEngine.Object.DontDestroyOnLoad(g);
 44 #endif
 45             }
 46 
 47         }
 48         public struct NoDelayedQueueItem
 49         {
 50             public Action<object> action;
 51             public object param;
 52         }
 53 
 54         private List<NoDelayedQueueItem> _actions = new List<NoDelayedQueueItem>();
 55         public struct DelayedQueueItem
 56         {
 57             public float time;
 58             public Action<object> action;
 59             public object param;
 60         }
 61         private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();
 62 
 63         List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>();
 64 
 65         public static void QueueOnMainThread(Action<object> taction, object tparam)
 66         {
 67             QueueOnMainThread(taction, tparam, 0f);
 68         }
 69         public static void QueueOnMainThread(Action<object> taction, object tparam, float time)
 70         {
 71             if (time != 0)
 72             {
 73                 lock (Current._delayed)
 74                 {
 75                     Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = taction, param = tparam });
 76                 }
 77             }
 78             else
 79             {
 80                 lock (Current._actions)
 81                 {
 82                     Current._actions.Add(new NoDelayedQueueItem { action = taction, param = tparam });
 83                 }
 84             }
 85         }
 86 
 87         public static Thread RunAsync(Action a)
 88         {
 89             Initialize();
 90             while (numThreads >= maxThreads)
 91             {
 92                 Thread.Sleep(100);
 93             }
 94             Interlocked.Increment(ref numThreads);
 95             ThreadPool.QueueUserWorkItem(RunAction, a);
 96             return null;
 97         }
 98 
 99         private static void RunAction(object action)
100         {
101             try
102             {
103                 ((Action)action)();
104             }
105             catch
106             {
107             }
108             finally
109             {
110                 Interlocked.Decrement(ref numThreads);
111             }
112 
113         }
114 
115 
116         void OnDisable()
117         {
118             if (_current == this)
119             {
120 
121                 _current = null;
122             }
123         }
124 
125 
126 
127         // Use this for initialization
128         void Start()
129         {
130 
131         }
132 
133         List<NoDelayedQueueItem> _currentActions = new List<NoDelayedQueueItem>();
134 
135         // Update is called once per frame
136         void Update()
137         {
138             if (_actions.Count > 0)
139             {
140                 lock (_actions)
141                 {
142                     _currentActions.Clear();
143                     _currentActions.AddRange(_actions);
144                     _actions.Clear();
145                 }
146                 for (int i = 0; i < _currentActions.Count; i++)
147                 {
148                     _currentActions[i].action(_currentActions[i].param);
149                 }
150             }
151 
152             if (_delayed.Count > 0)
153             {
154                 lock (_delayed)
155                 {
156                     _currentDelayed.Clear();
157                     _currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time));
158                     for (int i = 0; i < _currentDelayed.Count; i++)
159                     {
160                         _delayed.Remove(_currentDelayed[i]);
161                     }
162                 }
163 
164                 for (int i = 0; i < _currentDelayed.Count; i++)
165                 {
166                     _currentDelayed[i].action(_currentDelayed[i].param);
167                 }
168             }
169         }
170     }

使用方式

Function
{
//非同步在多線程下運行
Loom.RunAsync(() =>
    {
        //這個函數會進行大量文件讀寫操作
        LoadLocalFile();

        //回到unity線程繼續運行
        Loom.QueueOnMainThread(()=>
        {    
            //這個函數是unity函數
            UnityFunction();
        }
    }
}

這個Loom類的大概思路就是把整個代碼塊放多線程中,並把需要在主線程運行的代碼按委托的方式封裝起來保存的list里,Updata函數是unity函數,他會自動每幀執行一次。所以他可以判斷list是否有任務並執行任務,從而實現了回到主線程


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • using System.Xml;using System.IO;using System; namespace Framework.Common{ /// /// 用於獲取或設置Web.config/*.exe.config中節點數據的輔助類 /// public sealed class App... ...
  • 就算懂正則的朋友,在遇到需要用正則校驗數據時,也往往是在網上去找很久,結果找來的還是不很符合要求。 所以我最近把開發中常用的一些正則表達式整理了一下,在這裡分享一下。給自己留個底,也給朋友們做個參考。 一、校驗數字的表達式 二、校驗字元的表達式 三、特殊需求表達式 ...
  • 現在比較流行C#與C++融合:C#做GUI,開發效率高,C++做運算,運行效率高,二者兼得。 但是C++與C#必然存在數據交互,C#與C++dll的數據交互從來都是一個讓人頭疼的問題。 從調用方式看也有兩種情況: 1、C#調用C++函數 這種情況用的比較多,數據流向可以是C#流向C++,通過參數將數 ...
  • 1、微信小程式免費SSL證書Https 申請(阿裡雲申請) 進入阿裡雲控制台後,選擇 選擇 但是阿裡雲的免費SSL證書藏得比較深,得這樣操作才能顯示出免費證書 點擊 點擊 點擊 支付即可 步驟1: 步驟2: 步驟3: 步驟4: 步驟5: 進入證書控制台 補全證書信息,由於是免費證書,因此只能填寫一個 ...
  • 屬性分為CSS片段和JS片段。 CSS類定義:1、div easyui-window 生成一個window視窗樣式。 屬性如下: 1)modal:是否生成模態視窗。true[是] false[否] 2)shadow:是否顯示視窗陰影。true[顯示] false[不顯示] 2、div easyui- ...
  • 前段時間公司系統中有一塊需要發送郵件calendar outlook可以接受查看calendar 發送outlook主要是有rrule腳本的邊界 網上找過一些資料,主要有兩種實現方式 1、一種是已ics的附件格式發送附件,但是這樣用戶接收到的calendar 需要點開附件才能查看calendar,用 ...
  • 本系列將分析ASP.NET Core運行原理 "【ASP.NET Core】運行原理(1):創建WebHost" "【ASP.NET Core】運行原理(2):啟動WebHost" "【ASP.NET Core】運行原理(3):認證" 【ASP.NET Core】運行原理(4):授權 在認證階段通過 ...
  • 前兩天在博客園看到 .NET開發一個微信跳一跳輔助程式, 原來可以通過C#連接手機操作。正好朋友圈有人分享“沖頂大會”。沖頂大會是一個線上答題APP。每次12道題,每道題有10秒鐘的答題時間,全對者瓜分1萬或10萬獎金。於是試著答了一次,大部分題目都不算難,即便不知道但通過關鍵詞搜索應該也很容易找到 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...