【面试题一】Unity3D协同程序的学习理解与说明

首先.unity3d是否支持写成多线程?如果支持的话要注意什么?

支持:如果同时你要处理很多事情或者与Unity的对象互动小可以用thread,否则使用coroutine.{ [kəru:'ti:n] n. 协同程序}

注意:C#中有lock这个关键字,以确保只有一个线程可以在特定时间内访问特定的对象

其次.Unity3D中的协程(Coroutine)和C#线程之间的区别是什么?

Unity3d没有多线程的概念,不过unity也给我们提供了StartCoroutine(协同程序)和LoadLevelAsync(异步加载关卡)后台加载场景的方法。 StartCoroutine为什么叫协同程序呢,所谓协同,就是当你在StartCoroutine的函数体里处理一段代码时,利用yield语句等待执行结果,这期间不影响主程序的继续执行,可以协同工作。而LoadLevelAsync则允许你在后台加载新资源和场景,所以再利用协同,你就可以前台用loading条或动画提示玩家游戏未卡死,同时后台协同处理加载的事宜asynchronous[eɪˈsɪŋkrənəs].synchronous同步

接下来主要说说这个协同程序

一。什么是协同程序

       协同程序,即在主程序运行时同时开启另一段逻辑处理,来协同当前程序的执行。换句话说,开启协同程序就是开启一个线程。

 

二。协同程序的开启与终止

       在Unity3D中,使用MonoBehaviour.StartCoroutine方法即可开启一个协同程序,也就是说该方法必须在MonoBehaviour或继承于MonoBehaviour的类中调用。

       在Unity3D中,使用StartCoroutine(string methodName)和StartCoroutine(IEnumerator routine)都可以开启一个线程。区别在于使用字符串作为参数可以开启线程并在线程结束前终止线程,相反使用IEnumerator 作为参数只能等待线程的结束而不能随时终止(除非使用StopAllCoroutines()方法);另外使用字符串作为参数时,开启线程时最多只能传递一个参数,并且性能消耗会更大一点,而使用IEnumerator 作为参数则没有这个限制。

        在Unity3D中,使用StopCoroutine(string methodName)来终止一个协同程序,使用StopAllCoroutines()来终止所有可以终止的协同程序,但这两个方法都只能终止该MonoBehaviour中的协同程序。

        还有一种方法可以终止协同程序,即将协同程序所在gameobject的active属性设置为false,当再次设置active为ture时,协同程序并不会再开启;如是将协同程序所在脚本的enabled设置为false则不会生效。这是因为协同程序被开启后作为一个线程在运行,而MonoBehaviour也是一个线程,他们成为互不干扰的模块,除非代码中用调用,他们共同作用于同一个对象,只有当对象不可见才能同时终止这两个线程。然而,为了管理我们额外开启的线程,Unity3D将协同程序的调用放在了MonoBehaviour中,这样我们在编程时就可以方便的调用指定脚本中的协同程序,而不是无法去管理,特别是对于只根据方法名来判断线程的方式在多人开发中很容易出错,这样的设计保证了对象、脚本的条理化管理,并防止了重名。

 

三。协同程序的输入、输出类型

        协同程序的返回类型为Coroutine类型。在Unity3D中,Coroutine类继承于YieldInstruction,所以,协同程序的返回类型只能为null、等待的帧数(frame)以及等待的时间。

        协同程序的参数不能指定ref、out参数。但是,我们在使用WWW类时会经常使用到协同程序,由于在协同程序中不能传递参数地址(引用),也不能输出对象,这使得每下载一个WWW对象都得重写一个协同程序,解决这个问题的方法是建立一个基于WWW的类,并实现一个下载方法。如下:

using UnityEngine;
using System.Collections;
public class WWWObject : MonoBehaviour 
{
 public WWW www;
 
 public WWWObject(string url)
 {
  if(GameVar.wwwCache)
   www = WWW.LoadFromCacheOrDownload(url, GameVar.version);
  else
   www = new WWW(url);
 }
 
 public IEnumerator Load()
 {
  Debug.Log("Start loading : " + www.url);
  while(!www.isDone)
  {
   if(GameVar.gameState == GameState.Jumping || GameVar.gameState == GameState.JumpingAsync)
    LoadScene.progress = www.progress;
   
   yield return 1;
  }
  if(www.error != null)
   Debug.LogError("Loading error : " + www.url + "\n" + www.error);
  else
   Debug.Log("End loading : " + www.url);
 }
 
 public IEnumerator LoadWithTip(string resourcesName)
 {
  Debug.Log("Start loading : " + www.url);
  LoadScene.tipStr =  "Downloading  resources <" + resourcesName + "> . . .";
  while(!www.isDone)
  {
   if(GameVar.gameState == GameState.Jumping || GameVar.gameState == GameState.JumpingAsync)
    LoadScene.progress = www.progress;
   
   yield return 1;
  }
  if(www.error != null)
   Debug.LogError("Loading error : " + www.url + "\n" + www.error);
  else
   Debug.Log("End loading : " + www.url);
 }
} 
调用:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class LoadResources : MonoBehaviour 
{
 static string url = "http://61.149.211.88/Package/test.unity3d";
 public static WWW www = null;
 IEnumerator Start()
 {
  if(!GameVar.resourcesLoaded)
  {  
   GameVar.gameState = GameState.Jumping;
   
   WWWObject obj = new WWWObject(url);
   www = obj.www;
   yield return StartCoroutine(obj.LoadWithTip("Textures"));
   
   GameVar.resourcesLoaded = true;
   GameVar.gameState = GameState.Run;
  }
 }
} 

文章主要参考http://wg2009perfect.blog.163.com/blog/static/127997663201211111222126/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值