unity3d 线程_unity3d多线程 - CSDN
  • Unity3D游戏开发之多线程及使用多线程   Unity3D中的多线程线程是一个相当复杂的话题,但如果掌握了它,就可以从容的使用多个硬件处理器或处理很难划分管理数据块。   如在场景中用A*算法进行大量的数据计算,...


    Unity3D中的多线程。线程是一个相当复杂的话题,但如果掌握了它,就可以从容的使用多个硬件处理器或处理很难划分管理数据块。

     

    如在场景中用A*算法进行大量的数据计算,变形网格中操作大量的顶点,持续的要运行上传数据到服务器,二维码识别等图像处理,如果同时你要处理很多事情或者与Unity的对象互动小可以用thread,否则使用coroutine。

     

    线程是在程序中与其他线程同时运行的进行。在多处理器的计算机上可以做到多个线程的真正的同步,更多的线程取决于有多个处理核心。

     

    编程时,总有个主线程执行你的代码,也可以创建额外的线程和主线程同时运行。而Unity中,你仅能从主线程中访问的组件,对象和Unity3D系统调用。任何企图访问这些项目的第二个线程都将失败并引发错误,这是一个要重视的一个限制。

     

    所以当你写代码时,你认为一个函数开始并达到它执行的点后返回,同样你做的东西又在另外一个函数中执行,但又没有发生相应的变化。操作系统决定你代码的执行,任何时候,你的代码只能暂时”休眠”掉,然后让另外的代码开始运行。

     

     

     

    多线程及使用多线程

     

    在这个例子中,在第一个线程将A的值加载到CPU寄存器中准备+1后被中断,第二个线程来读取A的值,并减去1000,这时A应该是-950,现在第一个线程重新开始,它在寄存器中的50+1的结果存储于A,A变成了51,而-950已经丢掉了。

     

    从根本上说,要在用多个线程在同时对变量或内存访问时,要采取很多预防措施来确保不会发生这样的事。所以Unity决定从另外线程访问这些变量或者内存是无效的,只是为了避免所有系统和框架对象出现问题。所以要确保一次只有一个线程来修改变量,这不意味着你不能用多线程工作,你可以用”排序”来解决这个问题。

     

    C#中有lock这个关键字,以确保只有一个线程可以在特定时间内访问特定的对象,这里说对象是因为法锁定一个类型值(value type)或原型(primitive)。

     

    1. int a = 50;

    2. 

    3. object guard = new object();

    4. 

    5. void ThreadOneCode()

    6. {

    7. //一些代码在这

    8. 

    9. lock(guard)

    10. {

    11. a = a + 1;

    12. }

    13. 

    14. //其余一些代码在这

    15. 

    16. }

    17. 

    18. void ThreadTwoCode()

    19. {

    20. //一些代码在这

    21. 

    22. lock(guard)

    23. {

    24. a = a - 1000;

    25. }

    复制代码

     

    所有都锁定在guard内,保证同一个时间只有一个线程通过guard访问它,你可以使用任何合适的对象。现在你可能会有各种各样的问题,比如你要锁定的不止一件事,可能是互相嵌套的。那我们该怎么办呢?

     

    我们这个类叫Loom,让你可以轻松在另一个线程运行代码,这里有两个要注意的功能:

     

    RunAsync(Action)-在另一个线程上运行的一组代码.

     

    QueueOnMainThread(Action,[可选]float time)-运行在主线程的语句(可选延迟).

     

    用Loom.Current访问Loom-创建一个看不见的GameObject用来处理游戏主线程的互动,下面这个例子用Loom来更新一个网格所有的顶点乘的结果。

     

     

    展开全文
  • Unity里面关于资源加载我们都知道是下载更新AssetBundle,关于AssetBundle我之前的文章已经详细介绍过,没看过的朋友可以在看一下。下面介绍的资源加载的Demo有以下几点: 1.WWW下载图片资源 2.HTTP下载apk文件,...

    这里写图片描述

    前言

    此文章适合不太了解资源加载的萌新,有了入门基础之后再去github上搜大牛写的专业的资源加载方案才能得心应手,不然的话会看的很吃力或者说一脸懵逼。Unity里面关于资源加载我们都知道是下载更新AssetBundle,关于AssetBundle我之前的文章已经详细介绍过,没看过的朋友可以在看一下。下面介绍的资源加载的Demo有以下几点:
    1.WWW下载图片资源
    2.HTTP下载apk文件,并且支持断点续传,并且显示加载进度条
    3.HTTP多线程下载文件

    部分核心代码和讲解

    WWW下载

    思路:

    WWW是Unity给我们封装的一个基于HTTP的简单类库,如果我们做很简单的下载,或者网络请求可以用这个类库,个人觉得这个封装的并不是很好,所以一般商业项目开发都不会使用这个,宁可自己去封装一个HTTP请求和下载的类库,可控性更好。仅仅是个人观点,不喜勿喷。

    代码:

    using UnityEngine;
    using System.Collections;
    using System;
    using System.IO;
    
    public class WWWLoad
    {
        private WWW www = null;
        static System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
        /// <summary>
        /// 下载文件
        /// </summary>
        public IEnumerator DownFile(string url, string savePath, Action<WWW> process)
        {
            FileInfo file = new FileInfo(savePath);
            stopWatch.Start();
            UnityEngine.Debug.Log("Start:" + Time.realtimeSinceStartup);
            www = new WWW(url);
            while (!www.isDone)
            {
                yield return 0;
                if (process != null)
                    process(www);
            }
            yield return www;
            if (www.isDone)
            {
                byte[] bytes = www.bytes;
                CreatFile(savePath, bytes);
            }
        }
    
        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="bytes"></param>
        public void CreatFile(string savePath, byte[] bytes)
        {
            FileStream fs = new FileStream(savePath, FileMode.Append);
            BinaryWriter bw = new BinaryWriter(fs);
            fs.Write(bytes, 0, bytes.Length);
            fs.Flush();     //流会缓冲,此行代码指示流不要缓冲数据,立即写入到文件。
            fs.Close();     //关闭流并释放所有资源,同时将缓冲区的没有写入的数据,写入然后再关闭。
            fs.Dispose();   //释放流
            www.Dispose();
    
            stopWatch.Stop();
            Debug.Log("下载完成,耗时:" + stopWatch.ElapsedMilliseconds);
            UnityEngine.Debug.Log("End:" + Time.realtimeSinceStartup);
        }
    
    }
    
    

    HTTP下载并加载AB资源

    思路:

    主要用的核心类是HttpWebRequest,用这个类创建的对象可以申请下载的文件的大小以及下载的进度。移动上可读写的目录是PersidentDataPath,并且各个移动设备的路径不同,这点要注意,所以我们下载的AB资源就会下载到这个目录。

    效果图:

    这里写图片描述

    核心代码:

    using UnityEngine;
    using System.Collections;
    using System.Threading;
    using System.IO;
    using System.Net;
    using System;
    
    /// <summary>
    /// 通过http下载资源
    /// </summary>
    public class HttpDownLoad {
    	//下载进度
    	public float progress{get; private set;}
    	//涉及子线程要注意,Unity关闭的时候子线程不会关闭,所以要有一个标识
    	private bool isStop;
    	//子线程负责下载,否则会阻塞主线程,Unity界面会卡主
    	private Thread thread;
    	//表示下载是否完成
    	public bool isDone{get; private set;}
        const int ReadWriteTimeOut = 2 * 1000;//超时等待时间
        const int TimeOutWait = 5 * 1000;//超时等待时间
    
    
        /// <summary>
        /// 下载方法(断点续传)
        /// </summary>
        /// <param name="url">URL下载地址</param>
        /// <param name="savePath">Save path保存路径</param>
        /// <param name="callBack">Call back回调函数</param>
        public void DownLoad(string url, string savePath,string fileName, Action callBack, System.Threading.ThreadPriority threadPriority = System.Threading.ThreadPriority.Normal)
    	{
    		isStop = false;
            System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
            //开启子线程下载,使用匿名方法
            thread = new Thread(delegate() {
                stopWatch.Start();
                //判断保存路径是否存在
                if (!Directory.Exists(savePath))
    			{
    				Directory.CreateDirectory(savePath);
    			}
    			//这是要下载的文件名,比如从服务器下载a.zip到D盘,保存的文件名是test
    			string filePath = savePath + "/"+ fileName;
    			
    			//使用流操作文件
    			FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write);
    			//获取文件现在的长度
    			long fileLength = fs.Length;
    			//获取下载文件的总长度
    			UnityEngine.Debug.Log(url+" "+fileName);
    			long totalLength = GetLength(url);
                Debug.LogFormat("<color=red>文件:{0} 已下载{1}M,剩余{2}M</color>",fileName,fileLength/1024/1024,(totalLength- fileLength)/ 1024/1024);			
    			
    			//如果没下载完
    			if(fileLength < totalLength)
    			{
    				
    				//断点续传核心,设置本地文件流的起始位置
    				fs.Seek(fileLength, SeekOrigin.Begin);
    
    				HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest;
                    
                    request.ReadWriteTimeout = ReadWriteTimeOut;
                    request.Timeout = TimeOutWait;
    
                    //断点续传核心,设置远程访问文件流的起始位置
                    request.AddRange((int)fileLength);
    
                    Stream  stream = request.GetResponse().GetResponseStream();
    				byte[] buffer = new byte[1024];
    				//使用流读取内容到buffer中
    				//注意方法返回值代表读取的实际长度,并不是buffer有多大,stream就会读进去多少
    				int length = stream.Read(buffer, 0, buffer.Length);
                    //Debug.LogFormat("<color=red>length:{0}</color>" + length);
                    while (length > 0)
    				{
    					//如果Unity客户端关闭,停止下载
    					if(isStop) break;
    					//将内容再写入本地文件中
    					fs.Write(buffer, 0, length);
    					//计算进度
    					fileLength += length;
    					progress = (float)fileLength / (float)totalLength;
    					//UnityEngine.Debug.Log(progress);
    					//类似尾递归
    					length = stream.Read(buffer, 0, buffer.Length);
    
    				}
    				stream.Close();
    				stream.Dispose();
    
                }
                else
    			{
    				progress = 1;
                }
                stopWatch.Stop();
                Debug.Log("耗时: " + stopWatch.ElapsedMilliseconds);
                fs.Close();
    			fs.Dispose();
    			//如果下载完毕,执行回调
    			if(progress == 1)
    			{
                    isDone = true;
                    if (callBack != null) callBack();
                    thread.Abort();
                }
                UnityEngine.Debug.Log ("download finished");	
    		});
    		//开启子线程
    		thread.IsBackground = true;
            thread.Priority = threadPriority;
    		thread.Start();
        }
    
    
    	/// <summary>
    	/// 获取下载文件的大小
    	/// </summary>
    	/// <returns>The length.</returns>
    	/// <param name="url">URL.</param>
    	long GetLength(string url)
    	{
    		UnityEngine.Debug.Log(url);
    		
    		HttpWebRequest requet = HttpWebRequest.Create(url) as HttpWebRequest;
    		requet.Method = "HEAD";
    		HttpWebResponse response = requet.GetResponse() as HttpWebResponse;
    		return response.ContentLength;
    	}
    
    	public void Close()
    	{
    		isStop = true;
    	}
    
    }
    
    

    多线程下载文件

    思路:

    多线程下载思路是计算一个文件包大小,然后创建几个线程,计算每一个线程下载的始末下载的位置,最后是合并成一个整体的文件包写入到本地。

    效果图:

    这里写图片描述

    核心代码:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using System.Net;
    using UnityEngine;
    using System.Threading;
    
    public class MultiHttpDownLoad : MonoBehaviour
    {
    	string savePath = string.Empty;
    	string FileName = "ClickEffect.apk";
    	//string resourceURL = @"http://www.aladdingame.online/wuzhang/Resources/ClickEffect.apk";// @"http://www.dingxiaowei.cn/birdlogo.png";
    	string resourceURL = @"http://www.dingxiaowei.cn/ClickEffect.apk";
    	string saveFile = string.Empty;
    	public int ThreadNum { get; set; }
    	public bool[] ThreadStatus { get; set; }
    	public string[] FileNames { get; set; }
    	public int[] StartPos { get; set; }
    	public int[] FileSize { get; set; }
    	public string Url { get; set; }
    	public bool IsMerge { get; set; }
    	private int buffSize = 1024;
    	DateTime beginTime;
    
    	void Start()
    	{
    #if UNITY_EDITOR || UNITY_STANDALONE_WIN
    		savePath = Application.streamingAssetsPath;
    #elif UNITY_ANDROID
              savePath = Application.persistentDataPath;;
    #endif
    		saveFile = Path.Combine(savePath, FileName);
    
    		DownDoad();
    	}
    
    	void Init(long fileSize)
    	{
    		if (ThreadNum == 0)
    			ThreadNum = 5;
    
    		ThreadStatus = new bool[ThreadNum];
    		FileNames = new string[ThreadNum];
    		StartPos = new int[ThreadNum];//下载字节起始点
    		FileSize = new int[ThreadNum];//该进程文件大小
    		int fileThread = (int)fileSize / ThreadNum;//单进程文件大小
    		int fileThreade = fileThread + (int)fileSize % ThreadNum;//最后一个进程的资源大小
    		for (int i = 0; i < ThreadNum; i++)
    		{
    			ThreadStatus[i] = false;
    			FileNames[i] = i.ToString() + ".dat";
    			if (i < ThreadNum - 1)
    			{
    				StartPos[i] = fileThread * i;
    				FileSize[i] = fileThread;
    			}
    			else
    			{
    				StartPos[i] = fileThread * i;
    				FileSize[i] = fileThreade;
    			}
    		}
    	}
    
    	void DownDoad()
    	{
    		UnityEngine.Debug.Log("开始下载 时间:" + System.DateTime.Now.ToString());
    		beginTime = System.DateTime.Now;
    		Url = resourceURL;
    		long fileSizeAll = 0;
    		HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
    		fileSizeAll = request.GetResponse().ContentLength;
    		Init(fileSizeAll);
    
    		System.Threading.Thread[] threads = new System.Threading.Thread[ThreadNum];
    		HttpMultiThreadDownload[] httpDownloads = new HttpMultiThreadDownload[ThreadNum];
    		for (int i = 0; i < ThreadNum; i++)
    		{
    			httpDownloads[i] = new HttpMultiThreadDownload(request, this, i);
    			threads[i] = new System.Threading.Thread(new System.Threading.ThreadStart(httpDownloads[i].Receive));
    			threads[i].Name = string.Format("线程{0}:", i);
    			threads[i].Start();
    		}
    		StartCoroutine(MergeFile());
    	}
    
    	IEnumerator MergeFile()
    	{
    		while (true)
    		{
    			IsMerge = true;
    			for (int i = 0; i < ThreadNum; i++)
    			{
    				if (ThreadStatus[i] == false)
    				{
    					IsMerge = false;
    					yield return 0;
    					System.Threading.Thread.Sleep(100);
    					break;
    				}
    			}
    			if (IsMerge)
    				break;
    		}
    
    		int bufferSize = 512;
    		string downFileNamePath = saveFile;
    		byte[] bytes = new byte[bufferSize];
    		FileStream fs = new FileStream(downFileNamePath, FileMode.Create);
    		FileStream fsTemp = null;
    
    		for (int i = 0; i < ThreadNum; i++)
    		{
    			fsTemp = new FileStream(FileNames[i], FileMode.Open);
    			while (true)
    			{
    				yield return 0;
    				buffSize = fsTemp.Read(bytes, 0, bufferSize);
    				if (buffSize > 0)
    					fs.Write(bytes, 0, buffSize);
    				else
    					break;
    			}
    			fsTemp.Close();
    		}
    		fs.Close();
    		Debug.Log("接受完毕!!!结束时间:" + System.DateTime.Now.ToString());
    		Debug.LogError("下载耗时:" + (System.DateTime.Now - beginTime).TotalSeconds.ToString());
    		yield return null;
    		DeleteCacheFiles();
    	}
    
    	private void DeleteCacheFiles()
    	{
    		for (int i = 0; i < ThreadNum; i++)
    		{
    			FileInfo info = new FileInfo(FileNames[i]);
    			Debug.LogFormat("Delete File {0} OK!", FileNames[i]);
    			info.Delete();
    		}
    	}
    }
    
    public class HttpMultiThreadDownload
    {
    	private int threadId;
    	private string url;
    	MultiHttpDownLoad downLoadObj;
    	private const int buffSize = 1024;
    	HttpWebRequest request;
    
    	public HttpMultiThreadDownload(HttpWebRequest request, MultiHttpDownLoad downLoadObj, int threadId)
    	{
    		this.request = request;
    		this.threadId = threadId;
    		this.url = downLoadObj.Url;
    		this.downLoadObj = downLoadObj;
    	}
    
    	public void Receive()
    	{
    		string fileName = downLoadObj.FileNames[threadId];
    		var buffer = new byte[buffSize];
    		int readSize = 0;
    		FileStream fs = new FileStream(fileName, System.IO.FileMode.Create);
    		Stream ns = null;
    
    		try
    		{
    			request.AddRange(downLoadObj.StartPos[threadId], downLoadObj.StartPos[threadId] + downLoadObj.FileSize[threadId]);
    			ns = request.GetResponse().GetResponseStream();
    			readSize = ns.Read(buffer, 0, buffSize);
    			showLog("线程[" + threadId.ToString() + "] 正在接收 " + readSize);
    			while (readSize > 0)
    			{
    				fs.Write(buffer, 0, readSize);
    				readSize = ns.Read(buffer, 0, buffSize);
    				showLog("线程[" + threadId.ToString() + "] 正在接收 " + readSize);
    			}
    			fs.Close();
    			ns.Close();
    		}
    		catch (Exception er)
    		{
    			Debug.LogError(er.Message);
    			fs.Close();
    		}
    		showLog("线程[" + threadId.ToString() + "] 结束!");
    		downLoadObj.ThreadStatus[threadId] = true;
    	}
    
    	private void showLog(string processing)
    	{
    		Debug.Log(processing);
    	}
    }
    
    

    线程下载速度跟线程的关系呈钟罩式关系,也就是说适量的线程数量会提高下载速度,但并不是说线程数越多就越好,因为线程的切换和资源的整合也是需要时间的。下面就列举下载单个文件,创建的线程数和对应的下载时间:

    • 单线程
      这里写图片描述
    • 5个线程
      这里写图片描述
    • 15个线程
      这里写图片描述

    这里我是1M的带宽,下载的是一个300KB左右的资源,一般不会做多线程下载单一资源,多线程下载一般用于下载多个资源,除非单一资源真的很大才有多线程下载,然后做合包操作。

    Demo下载

    http://git.oschina.net/dingxiaowei/UnityResourceDownload
    关注后续更新请点start或者fork,感谢!

    开发交流

    1群
    QQ群
    unity3d unity 游戏开发

    1群如果已经满员,请加2群
    159875734

    后续计划

    写一个实际商业项目中用到的资源更新案例。

    更多精品文章

    Aladdin的博客

    展开全文
  • Unity3d线程

    2019-06-30 00:47:51
    (一)多线程的创建 Thread t = new Thread(new ThreadStart(Go)); Thread t1 = new Thread(Go); 两种创建方式没有区别; (二)多线程的状态控制和优先级 多线程有4种状态:Start()开始;Abort()终止;...

    (一)多线程的创建

    Thread t = new Thread(new ThreadStart(Go)); 

    Thread t1 = new Thread(Go);

    两种创建方式没有区别;

    (二)多线程的状态控制和优先级

    多线程有4种状态:Start()开始;Abort()终止;Join()阻塞;Sleep()休眠;

    有5种优先级:从高到底依次为:Highest,AboveNormal ,Normal ,BelowNormal ,Lowest;

    线程的默认优先级为Normal;


    多线程实例

    /*
     * 
     * 游戏多线程
     * */
    using UnityEngine;
    using System.Threading;
    
    
    public class BaseThread{
    	
    	private static BaseThread instance;
    
        object obj = new object();
        int num = 0;
        private BaseThread()
    	{
    
            /*测试线程优先级 
            /*/
            Thread th1 = new Thread(Th_test1);              //创建一个线程
            Thread th2 = new Thread(Th_test2);
            Thread th3 = new Thread(Th_test3);
            th1.Start();
            th2.Start();
            th3.Start();
            //学习优先级
            th1.Priority = System.Threading.ThreadPriority.Highest;         //优先级最高
            th2.Priority = System.Threading.ThreadPriority.Normal;
            th3.Priority = System.Threading.ThreadPriority.Lowest;
            //**/
    
    
            ///*测试线程锁
            
            /*/
    
            Thread th1 = new Thread(new ThreadStart(Th_lockTest));
            th1.Name = "test1";
            th1.Start();
    
            Thread th2 = new Thread(new ThreadStart(Th_lockTest));
            th2.Name = "test2";
            th2.Start();
    
    		//*/
    
    
    
    
        }
    
    
        public static BaseThread GetInstance()  
    	{
    		if (instance == null)  
    		{
                instance = new BaseThread();  
    		}  
    		return instance; 
    	}
    	
    
        //测试多线程锁
        public void Th_lockTest()
        {
            
            Debug.Log("测试多线程");
            while (true)
            {
                lock (obj)
                {                                //线程“锁”         
                    num++;
                    Debug.Log(Thread.CurrentThread.Name + "测试多线程" + num);
                }
                Thread.Sleep(100);
                if (num > 300)
                {
                    Thread.CurrentThread.Abort();
                }
            }
        }
    
        //测试多线程优先级
        public void Th_test1()
        {
            for (int i = 0; i < 500; i++)
            {
               
                Debug.Log("测试多线程1执行的次数:" + i);
                if(i >200)
                {
                    Thread.CurrentThread.Abort();
                }
            }
        }
        public void Th_test2()
        {
            for (int i = 0; i < 500; i++)
            {
             
                Debug.Log("测试多线程2执行的次数:" + i);
                if (i > 300)
                {
                    Thread.CurrentThread.Abort();
                }
            }
        }
        public void Th_test3()
        {
            for (int i = 0; i < 500; i++)
            {
          
                Debug.Log("测试多线程3执行的次数:" + i);
                if (i > 400)
                {
                    Thread.CurrentThread.Abort();
                }
            }
        }
    
    }
    



     

    转载于:https://www.cnblogs.com/lexiaoyao-jun/p/5208255.html

    展开全文
  • 前几天做的热力图中, foreach (var pos in PositionList) { PosArrayAdd(posArray, pos,size); } void PosArrayAdd(float[,] posArray, Position pos,INT size) ...

    前几天做的热力图中,

                foreach (var pos in PositionList)
                {
                    PosArrayAdd(posArray, pos,size);
                }
    void PosArrayAdd(float[,] posArray, Position pos,INT size)
            {
                //由于放大scale倍  需要计算给周围点贡献值  距离越近 贡献值越大 本点贡献值加scale/2 最远点加1  我们设定贡献值范围为scale/2 
                //限制贡献范围 加入把贴图放在第一象限且有一个顶点在原点,则所有点不能离开第一象限 xy大于等于0且小于等于最大点坐标
                int minx = Mathf.Clamp(pos.x - scale / 2, 0, size.x + 1);
                int maxx = Mathf.Clamp(pos.x - scale / 2 + scale, 0, size.x + 1);
     
                int miny = Mathf.Clamp(pos.y - scale / 2, 0, size.y + 1);
                int maxy = Mathf.Clamp(pos.y - scale / 2 + scale, 0, size.y + 1);
     
                for (int i = minx; i < maxx; i++)
                {
                    for (int j = miny; j < maxy; j++)
                    {
                        float dis = Vector2.Distance(new Vector2(i, j), new Vector2(pos.x, pos.y));
                        if (dis <= scale / 2)
                        {
                            //距离小于等于scale / 2的  我们要插值计算贡献值 
                            posArray[i, j] += Mathf.Lerp(1, scale / 2, 1 - dis * 2 / scale);
                        }
                    }
                }
            }

    这里的计算量比较大,我们在放大100倍的情况下,假如有一千个数据,要计算一千万次。领导怀疑我的这个算法在大量数据的情况下会不会死机。测试中发现在1800个数据即1800万次计算(4个循环,每个循环里有600个数据)的时候就会有些卡,在12000万次计算的时候基本要等待4-5秒。很慢很慢。于是我想是否可以通过多线程优化这里。是的,可以!

    我们将此计算方法放到自己封装的线程类中计算,这样就不会影响主线程的运算。下面是我封装的线程类:

    namespace Unite
    {
        public class ThreadManager
        {
            public bool IsOver = false;
    
            private Thread thread;
    
            private List<PeoplePosition.Position> PositionList = new List<PeoplePosition.Position>();
    
            private int scale;
            private float[,] posArray;
            private PeoplePosition.INT size;
    
            public ThreadManager(List<PeoplePosition.Position> PositionList,int scale, float[,] posArray, PeoplePosition.INT size)
            {
                this.PositionList = PositionList;
                this.scale = scale;
                this.posArray = posArray;
                this.size = size;
                thread = new Thread(new ThreadStart(Cal));
            }
    
            public float[,]  Start()
            {
                IsOver = false;
                thread.Start();
                return posArray;
            }
    
            public void Cal()
            {
                Debug.Log(PositionList.Count);
                foreach (var pos in PositionList)
                {
                    PosArrayAdd(posArray, pos, size);
                }
    
                Debug.Log("线程结束");
                IsOver = true;
                thread.Abort();
                
            }
    
    
            void PosArrayAdd(float[,] posArray, PeoplePosition.Position pos, PeoplePosition.INT size)
            {
                //由于放大scale倍  需要给点周围插值打点 离得近打的多 离得远打的少  本点打scale/2个值 边缘打1个点
                int minx = Mathf.Clamp(pos.x - scale / 2, 0, size.x + 1);
                int maxx = Mathf.Clamp(pos.x - scale / 2 + scale, 0, size.x);
    
                int miny = Mathf.Clamp(pos.y - scale / 2, 0, size.y + 1);
                int maxy = Mathf.Clamp(pos.y - scale / 2 + scale, 0, size.y);
                for (int i = minx; i <= maxx; i++)
                {
                    for (int j = miny; j <= maxy; j++)
                    {
                        float dis = Vector2.Distance(new Vector2(i, j), new Vector2(pos.x, pos.y));
                        if (dis <= scale / 2)
                        {
                            posArray[i, j] += Mathf.Lerp(1, scale / 2, 1 - dis * 2 / scale);
                        }
                    }
                }
            }
        }
    
      
    }

    从代码中我们可以看到我们在自己定义的类中声明了标志线程是否结束的字段IsOver。我们在协程中就可以如下调用:

      ThreadManager threadManager = new ThreadManager(PositionList, scale, posArray, size);
                threadManager.Start();
    
                while (!threadManager.IsOver)
                {
                    yield return new WaitForEndOfFrame();
                }
    
                Debug.Log("运算结束");
                //TODO

    运算速度超快。在计算4个6000个数据,即四个线程同时计算6000个数据要2.4s,对于主线程的UI显示也没有造成卡顿影响。而主线程算4个600个数据基本要在1.33s左右。

    展开全文
  • Unity线程访问类实现 unity中子线程无法使用unity中的方法,但很多时候我们需要在子线程中调用unity的方法(比如网络游戏),为了解决这个问题,我们就必须将需要在子线程调用的unity方法的代码,在主线程中执行...

    #Unity跨线程访问类实现 #

    unity中子线程无法使用unity中的方法,但很多时候我们需要在子线程中调用unity的方法(比如网络游戏),为了解决这个问题,我们就必须将需要在子线程调用的unity方法的代码,在主线程中执行。可是,如何能实现呢?既然是方法的传递,很容易想到 委托,为了在子线程能轻松将执行unity方法的代码放在主线程执行,可以将具体实现放在一个单例类中,即跨线程访问类。

    具体代码实现:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    //跨线程访问类,继承自单例类
    public class AccrossThreadHelper : MonoSingleton<AccrossThreadHelper>
    {
    	//定义个无参数无返回值的委托类型(可根据需求改进)
        public delegate void AccrossThreadFunc();
    	//一个委托集合
        private List<AccrossThreadFunc> delegateList;
        private void Start()
        {
    	    //初始化委托集合,并开启协程(Update替代协程也可以)
            delegateList = new List<AccrossThreadFunc>();
            StartCoroutine(Done());
        }
    	
    	//协程具体实现
        IEnumerator Done()
        {
            while(true)
            {
                if (delegateList.Count > 0)
                {
    	            //遍历委托链,依次执行
                    foreach (AccrossThreadFunc item in delegateList)
                    {
                        item();
                    }
                    //执行过的委托代码,清空
                    delegateList.Clear();
                }
                yield return new WaitForSeconds(0.1f);
            }
        }
    	//公开的添加委托方法
        public void AddDelegate(AccrossThreadFunc func)
        {
            delegateList.Add(func);
        }
    }
    
    
    

    调用格式:

    AccrossThreadHelper.Instance.AddDelegate(() => { ...});
    

    最后注意:

    跨线程访问类的初始化,要在主线程进行(⊙o⊙)。
    

    更多个人原创博客,可关注公众号SFGame
    在这里插入图片描述

    展开全文
  • unity3d 线程安全问题

    2019-06-15 16:37:27
    2019独角兽企业重金招聘Python工程师标准>>> ...
  • Unity异步线程调用主线程脚本程序,在Unity中异步线程调用主线程会报错,所以编写了一个Loom
  • unity3d做网游的同学应该不少,其中一个很蛋疼的问题就是主线程中尤其是UI部分很多实例都是不允许子线程修改的,那么我们就只有想办法把这些子线程里的数据缓存起来,让主线程自己拿着这些数据该干嘛干嘛去。...
  • Unity3D 协程与线程

    2017-08-30 22:47:12
    1 线程、进程、协程的区别 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。 协程和线程...
  • Unity3D协程-基础篇

    2019-07-18 10:45:05
    本课程为Unity3D协程技术精讲中的基础部分,协程是UnityEngine技术里面为常用且设计为精髓的技术;基础部分主要讲解协成的前世今生,其中包括设计模式、实现模式、验证模式的递进式推进过程让同学们掌握协程原理与...
  • 熟悉Unity的developer都知道在Unity中的线程不能使用Unity的对象,但可以使用Unity的值类型变量,如Vector3等。这样就使得线程Unity中显的很鸡肋和蹩脚,因为很多函数很都是UnityEngine类或函数的调用的,对于哪些...
  • 一个新建项目,做了两个多月才发现忘记写多线程获取数据导致卡顿,然后尝试去改动,但是不想把主动被动的部分的结构打乱,使用了Loom解决子线程完成后向主线程广播。 Messenger本身用在子线程会出现 get_isActiveAnd...
  • Unity线程Loom类

    2018-12-06 18:05:29
    using UnityEngine; using System.Collections; using System.Collections.Generic; using System; using System.Threading; using System.Linq;...public class Loom : MonoBehaviour ... public static int maxT...
  • Unity3D线程写法

    2014-08-13 08:21:59
    unity3D更多资源教程免费下载,群193521697 邀请...Unity3D的多线程写法如下: usingUnityEngine; using System.Collections; usingSystem.Threading; publicclass MyThread { publicint count; s
  • Unity3D线程访问类

    2020-04-03 18:46:59
    using System.Collections;...//跨线程访问类,继承自单例类 public class AccrossThreadHelper : MonoSingleton<AccrossThreadHelper> { //定义个无参数无返回值的委托类型(可根据需求改进)...
  • unity3d线程处理

    2013-08-26 11:28:52
    这就是我要做的是在一个Unity3D组件安全。当它是安全的时候,读取或更改其他组件的变量。例如,如果你试图修改或查询物理组件,你会遇到问题,同时一FixedUpdate发生了!这个组件使用互斥锁,让线程知道什么时候可以...
  • C#多线程的使用Unity支持多线程Unity支持多线程Unity支持多线程,重要三遍。 当大家使用到Unity读取外界数据或者操作网格的时候,多线程会非常的好用,因为操作可能比较昂贵,多开辟一个线程充分利用多核CPU的...
  • Unity 引擎的游戏逻辑和渲染,都是在主线程中进行的,和大多数其他游戏引擎一样,Unity 也是一个单线程的引擎。这与常规开发的思路可能不太一样,通常认为多线程能够很大程度上提升程序的性能效率,何况是游戏这种...
1 2 3 4 5 ... 20
收藏数 5,276
精华内容 2,110
关键字:

unity3d 线程