unity 多线程
对于客户端来说,好的用户体验,需要保持一个快速响应的用户界面。于是便要求:网络请求、io操作等 开销比较大的操作必须在后台线程进行,从而避免主线程的ui卡顿。(注:协程也是主线程的一部分,进行大量的io操作也会造成UI卡顿)
在 WPF 中,DispatcherObject 只能通过与它关联的 Dispatcher 进行访问。 例如,后台线程不能更新与 UI 线程中的 Dispatcher 关联的 Button 内容。
在unity4.X中,unity的api 是线程不安全的,只允许主线程进行访问。于是,如果在后台线程中想调用unity的api,就必须从后台线程跨回主线程,进行调用。
然而,unity中并不能直接使用 .net中的 dispatcher,或者像android activity中的runOnUiThread 从后台线程 跨回主线程。
那么,unity 多线程中,主线程和后台线程之间通信要用什么方法去实现呢?
1、通过共享数据:
顺序图大致如下,主线程中用携程循环等待,或者在update中进行检测,直到后台线程完成,修改IsFinish=true,主线程再进行对应的逻辑操作。

详见demo中的CZCoroutine文件夹。(注:CZCoroutine为开发群里好友给的一个自己封装协程管理器,并可支持多线程。)
2、实现一个Loom的管理器,将后台线程中需要在主线程中处理的委托添加到 List<Action> _actions中,并在unity的update中进行处理:
public class Loom : MonoBehaviour
{ private static Loom _current; public static Loom Current
{
get
{
if (_current == null && Application.isPlaying)
{ var g = GameObject.Find("Loom");
if (g == null)
{
g = new GameObject("Loom");
} _current = g.GetComponent<Loom>() ?? g.AddComponent<Loom>();
} return _current;
}
} private void Awake()
{
if (_current != null && _current != this)
{
Destroy(gameObject);
}
else
{
_current = this;
}
} private List<Action> _actions = new List<Action>(); public class DelayedQueueItem
{
public float time;
public Action action;
public string name;
} private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>(); public static void QueueOnMainThread(Action action, float time, string name)
{
lock (Current._delayed)
{
if (Current._delayed.Any(d => d.name == name))
return;
QueueOnMainThread(action, time);
}
} public static void QueueOnMainThread(Action action, string name)
{
QueueOnMainThread(action, , name);
} public static void QueueOnMainThread(Action action, float time)
{
if (time != )
{
lock (Current._delayed)
{
Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action });
}
}
else
{
lock (Current._actions)
{
Current._actions.Add(action);
}
}
} public static void QueueOnMainThread(Action action)
{
lock (Current._actions)
{
Current._actions.Add(action);
}
} public static void RunAsync(Action a)
{
var t = new Thread(RunAction);
t.Priority = System.Threading.ThreadPriority.Normal;
t.Start(a);
} private static void RunAction(object action)
{
((Action)action)();
} private List<Action> toBeRun = new List<Action>();
private List<DelayedQueueItem> toBeDelayed = new List<DelayedQueueItem>(); private void Update()
{
//Process the non-delayed actions
lock (_actions)
{
toBeRun.AddRange(_actions);
_actions.Clear();
}
foreach (var a in toBeRun)
{
try
{
a();
}
catch (Exception e)
{
Debug.LogError("Queued Exception: " + e.ToString());
}
}
toBeRun.Clear();
lock (_delayed)
{
toBeDelayed.AddRange(_delayed);
}
foreach (var delayed in toBeDelayed.Where(d => d.time <= Time.time))
{
lock (_delayed)
{
_delayed.Remove(delayed);
}
try
{
delayed.action();
}
catch (Exception e)
{
Debug.LogError("Delayed Exception:" + e.ToString());
}
}
toBeDelayed.Clear(); }
}
详见: http://dsqiu.iteye.com/blog/2028503
http://answers.unity3d.com/questions/305882/how-do-i-invoke-functions-on-the-main-thread.html
3、unity多线程插件 Loom
https://www.assetstore.unity3d.com/en/#!/content/7285
这个插件和上面分享的工具类同名,而现在也找不到上面工具类的出处,或许是同个作者,进行了优化,封装拿到unity商店吧。
如果你对C# 中的Thread多线程还不熟悉,推荐 http://www.albahari.com/threading/ 进行学习
unity 多线程的更多相关文章
- Unity多线程(Thread)和主线程(MainThread)交互使用类——Loom工具分享
Unity多线程(Thread)和主线程(MainThread)交互使用类——Loom工具分享 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com ...
- unity多线程
多线程概念 多线程,是指实现多个线程并发执行的技术,合理利用多线程可以提升程序的性能,在unity中,一般是避免使用多线程的,unity对多线程的支持并不友好. 协程概念 协程,是指在主线程运行时开启 ...
- [Unity]多线程编程的一点心得
在做毕设的时候涉及到了较大数据的读取,每次从硬盘读都会卡很久,于是找资料之后自己做了个简单的多线程解决方案. 一共有两个类.第一个类ThreadJob如下: using System.Collecti ...
- Loom工具使用分享
Unity多线程(Thread)和主线程(MainThread)交互使用类——Loom工具分享 时间 2014-03-09 11:04:04 ITeye-博客 原文 http://dsqiu.it ...
- Unity3D性能优化最佳实践(四)资源审查
Asset auditing - 资源审查 许多项目发生效能问题的真正原因只是由于人员操作不当或是试东试西,而不小心改到导入设定影响到导入的资源.(例如最近的gitlab惨案) 对于较大规模的项目,最 ...
- Unity应用架构设计(10)————绕不开的协程和多线程(Part 1)
在进入本章主题之前,我们必须要了解客户端应用程序都是单线程模型,即只有一个主线程(Main Thread),或者叫做UI线程,即所有的UI控件的创建和操作都是在主线程上完成的.而服务器端应用程序,也就 ...
- Unity应用架构设计(10)——绕不开的协程和多线程(Part 2)
在上一回合谈到,客户端应用程序的所有操作都在主线程上进行,所以一些比较耗时的操作可以在异步线程上去进行,充分利用CPU的性能来达到程序的最佳性能.对于Unity而言,又提供了另外一种『异步』的概念,就 ...
- Unity应用架构设计(10)——绕不开的协程和多线程(Part 1)
在进入本章主题之前,我们必须要了解客户端应用程序都是单线程模型,即只有一个主线程(Main Thread),或者叫做UI线程,即所有的UI控件的创建和操作都是在主线程上完成的.而服务器端应用程序,也就 ...
- 关于Unity中协程、多线程、线程锁、www网络类的使用
协程 我们要下载一张图片,加载一个资源,这个时候一定不是一下子就加载好的,或者说我们不一定要等它下载好了才进行其他操作,如果那样的话我就就卡在了下载图片那个地方,傻住了.我们希望我们只要一启动加载的命 ...
随机推荐
- Adding DTrace Probes to PHP Extensions
By cj on Dec 06, 2012 The powerful DTrace tracing facility has some PHP-specific probes that can b ...
- WPF 之 鼠标双击事件
由于WPF中没有鼠标的双击事件,因而只能通过MouseDown事件来模拟.当连续的两次MouseDown事件的时间间隔,没有超过一个设定的时间阈值时,就计算为一个双击事件,并作相应的处理. 利用WPF ...
- 浏览器显示本地照片 image
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...
- uiview 的transitionWithView 方法使用
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [UIView transitionWithView:_imageV ...
- org-reveal
环境: Debian 8 Emacs 24.4 org-reveal是在emacs org-mode中使用reveal.js的一个插件. emacs 24.4自带的org版本是8.2.10,这个版本似 ...
- Swift中if let name = optionName {}解释
在Swift语法的if语句中,是不能出现这种情况的: let optionName = "Swift" if let name = optionName { print(" ...
- java 编程军规
军规条例军规一:[避免在程序中使用魔鬼数字,必须用有意义的常量来标识.]军规二:[明确方法的功能,一个方法仅完成一个功能.]军规三:[方法参数不能超过5个]军规四:[方法调用尽量不要返回null,取而 ...
- css+div网页设计(二)--布局与定位
在网页设计中,能否控制好各个模块中在页面中的位置是非常关键的,与传统的表格定位不同,css+div定位方式更加的灵活,本篇博客将为大家介绍css+div的布局与定位. 一.盒子模型 由图可以看出 盒子 ...
- asp.net中Response对象鱼Request对象
在asp.net中Response与Request对象是两个常用的对象,虽然他们长得有点像,但是作用却是截然不同,我们来看一下他们他们都有哪些不同. 一.Response对象主要作用:像浏览器输出信息 ...
- C#使用简单邮件传输协议(SMTP)发送邮件
1.首先引入命名空间: using System.Net.Mail; 2.定义邮件配置类: public class EmailServiceConfig { /// <summary> ...