当前位置: 移动技术网 > IT编程>开发语言>c# > C#在Unity游戏开发中进行多线程编程的方法

C#在Unity游戏开发中进行多线程编程的方法

2019年07月18日  | 移动技术网IT编程  | 我要评论
在这之前,有很多人在质疑unity支不支持多线程,事实上unity是支持多线程的。而提到多线程就要提到unity非常常用的协程,然而协程并非真正的多线程。协程其实是等某个操

在这之前,有很多人在质疑unity支不支持多线程,事实上unity是支持多线程的。而提到多线程就要提到unity非常常用的协程,然而协程并非真正的多线程。协程其实是等某个操作完成之后再执行后面的代码,或者说是控制代码在特定的时机执行。而多线程在unity渲染和复杂逻辑运算时可以高效的使用多核cpu,帮助程序可以更高效的运行。本篇主要介绍在unity中如何使用多线程。

首先引入c#中使用多线程的类库

using system.threading;

创建线程实例的四种方式

一、线程执行无参方法

构造语法

// 初始化 thread 类的新实例。
// < param name="start">无参委托对象.</ param>
public thread(threadstart start)

start

类型:system.threading.threadstart
表示开始执行此线程时要调用的方法的 threadstart 委托。

void start()
{
 //创建无参线程对象
 thread thr = new thread(func_noarguments);
 //启动线程
 thr.start();
}
// function of no arguments.

void func_noarguments()
{
 debug.log("run func_noarguments");
}

二、线程执行有参方法

构造语法

// 初始化 thread 类的新实例。
// < param name="start">有参委托对象.< /param>
public thread(parameterizedthreadstart start)

start

类型:system.threading.parameterizedthreadstart
一个委托,它表示此线程开始执行时要调用的方法。
注意:参数只能有一个,且必须为object类型

实例

void start()
{
 //创建有参线程对象
 thread thr = new thread(func_arguments);
 //启动线程,传入参数
 thr.start("lanou");
}
// function of have arguments.
void func_arguments(object data)
{
 debug.log("run func_arguments, data = " + data);
}

三、线程执行无参方法,限制线程要使用的最大堆栈大小

构造语法

// 初始化 thread 类的新实例。
// < param name="start">无参委托对象.< /param>
// < param name="maxstacksize">使用的最大堆栈大小.< /param>
public thread(threadstart start,int maxstacksize)

start

类型:system.threading.threadstart
表示开始执行此线程时要调用的方法的 threadstart 委托。

maxstacksize

类型:system.int32
线程要使用的最大堆栈大小(以字节为单位);如果为 0,则使用可执行文件的文件头中指定的默认最大堆栈大小。
重要事项:对于部分受信任的代码,如果 maxstacksize 大于默认堆栈大小,则将其忽略。 不引发异常。

void start()
{
 //创建无参线程对象,限制256kb堆栈大小
 thread thr = new thread(func_noarguments,262144);
 //启动线程
 thr.start();
}
// function of no arguments.
void func_noarguments()
{
 debug.log("run func_noarguments");
}

四、线程执行有参方法,限制线程要使用的最大堆栈大小

构造语法

// 初始化 thread 类的新实例。
// < param name="start">有参委托对象.< /param>
// < param name="maxstacksize">使用的最大堆栈大小.< /param>
public thread(parameterizedthreadstart start,int maxstacksize)

start

类型:system.threading.parameterizedthreadstart
一个委托,它表示此线程开始执行时要调用的方法。
注意:参数只能有一个,且必须为object类型

maxstacksize

类型:system.int32
线程要使用的最大堆栈大小(以字节为单位);如果为 0,则使用可执行文件的文件头中指定的默认最大堆栈大小。
重要事项:对于部分受信任的代码,如果 maxstacksize 大于默认堆栈大小,则将其忽略。 不引发异常。

实例

void start()
{
 //创建有参线程对象,限制256kb堆栈大小
 thread thr = new thread(func_arguments,262144);
 //启动线程,传入参数
 thr.start("lanou");
}
// function of have arguments.
void func_arguments(object data)
{
 debug.log("run func_arguments, data = " + data);
}

启动线程(上文已使用)

无参启动

void start()
{
 //创建无参线程对象
 thread thr = new thread(func_noarguments);
 //启动线程
 thr.start();
}
// function of no arguments.
void func_noarguments()
{
 debug.log("run func_noarguments");
}

有参启动

void start()
{
 //创建有参线程对象
 thread thr = new thread(func_arguments);
 //启动线程,传入参数
 thr.start("lanou");
}
// function of have arguments.
void func_arguments(object data)
{
 debug.log("run func_arguments, data = " + data);
}


常用方法

1.public static void sleep( int millisecondstimeout)将当前线程挂起指定的毫秒数。
(1)millisecondstimeout
类型:system.int32
挂起线程的毫秒数。 如果 millisecondstimeout 参数的值为零,则该线程会将其时间片的剩余部分让给任何已经准备好运行的、有同等优先级的线程。 如果没有其他已经准备好运行的、具有同等优先级的线程,则不会挂起当前线程的执行。
(2)public void resume()
继续已挂起的线程。(已过时)
(3)public void abort()
在调用此方法的线程上引发 threadabortexception,以开始终止此线程的过程。 调用此方法通常会终止线程。
(4)public void join()
阻止调用线程直到线程终止,同时继续执行标准的 com 和 sendmessage 传送。
(5)public enum threadpriority
指定 thread 的调度优先级。

2016421152923973.png (1248×630)

通过线程池执行线程

2.threadpool.queueuserworkitem 方法 (waitcallback)
public static bool queueuserworkitem(waitcallback callback)
callback
类型:system.threading.waitcallback
一个 waitcallback,表示要执行的方法。
返回值
类型:system.boolean
如果此方法成功排队,则为 true;如果无法将该工作项排队,则引发 notsupportedexception。

unity使用多线程注意

变量都是共享的(都能指向相同的内存地址)
unityengine的api不能在分线程运行
unityengine定义的基本结构(int,float,struct定义的数据类型)可以在分线程计算,如 vector3(struct)可以 , 但texture2d(class,根父类为object)不可以。
unityengine定义的基本类型的函数可以在分线程运行
unity多线程插件

loom multi threading framework 1.7 

核心方法

// unlike "startmultithreadedworkloadexecution", you will have to build your own ithreadworkerobject.
 // downside: it requires some extra work. upside: you got more controll over what goes in and comes out
 // infact: you can create you own polymorphed ithreadworkerobject-array, each ellement being a completely different type. for example: the statemachines of enemies are ithreadworkerobject's and the array contains completely different classes with enemies/ai-behaviours.
 // < param name="workerobjects">an array of ithreadworkerobject objects to be handled by the threads. if you want multiple cores/threads to be active, make sure that the number of ithreadworkerobject's proves matches/exeeds your preferred number maxworkingthreads. < /param>
 // < param name="oncomplete">fired when all re-packaged workload-objects are finished computing< /param>
 // < param name="onpackageexecuted">fires foreach finished re-packaged set of workload-object< /param>
 // < param name="maxthreads"> lets you choose how many threads will be run simultaneously by the threadpool. default: -1 == number of cores minus one, to make sure the mainthread has at least one core to run on. (quadcore == 1 core mainthread, 3 cores used by the threadpoolscheduler)< /param>
 // < param name="scheduler">if null, a new threadpoolscheduler will be instantiated.< /param>
 // < param name="safemode">executes all the computations within try-catch events, logging it the message + stacktrace< /param>
 // < returns>a threadpoolscheduler that handles all the repackaged workload-objects< /returns>
 public static threadpoolscheduler startmultithreadedworkerobjects(ithreadworkerobject[] workerobjects, threadpoolschedulerevent oncompletecallback, threadedworkcompleteevent onpackageexecuted = null, int maxthreads = -1, threadpoolscheduler scheduler = null, bool safemode = true)
{
  if (scheduler == null)
  scheduler = createthreadpoolscheduler();

 scheduler.startasyncthreads(workerobjects, oncompletecallback, onpackageexecuted, maxthreads, safemode);
 return scheduler;
}


结束语

unity可以使用多线程,但对其有很多限制,所以在不使用unityengine api的情况下,可以使用多线程,提高多核cpu的使用率。通常可以将需要大量计算的算法内容,放置到多线程中执行,包括逻辑框架也可以放到多线程中执行。本篇理论性较强,后期会陆续发布实战型文章。

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网