Unity主线程和子线程跳转调用(1)
2018-06-18 04:04:23来源:未知 阅读 ()
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是否有任务并执行任务,从而实现了回到主线程
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:SuperSocket 最基础入门(大神忽略)(1)
下一篇:6.C#知识点:反射
- 最详细的java多线程教程来了 2020-06-08
- 系统化学习多线程(一) 2020-06-08
- 多线程:生产者消费者(管程法、信号灯法) 2020-06-01
- 如何合理地估算线程池大小? 2020-05-31
- 那些面试官必问的JAVA多线程和并发面试题及回答 2020-05-28
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash