Unity面试题(一)(包含答案)

1.协程

  定义:协程的官方定义是一种具有暂停执行并将控制权返回给Unity,待下一帧时继续执行。通俗点讲就是,协程是一种可以分部执行的函数,即该函数不是每次调用时都会执行函数体内的全部方法,而是只调用其中部分代码。

   协程其实与多线程一点关系都没有。协程是在主线程中执行的,且每次只能执行一个协程。

1.启动协程
  Coroutine StartCoroutine(string methodName,object value=null);

  Coroutine StartCoroutine(IEnumerator routine);

2.停止协程
  void StopCoroutine(string methodName);

  void StopCoroutine(IEnumerator routine);

  其中StopCortouine(string methodName)只能停止由与之相对应的StarCoroutine(string methodName)启动的协程。

  还有其它的方法来停止协程,但都不是停止某个指定的协程,而是停止多个协程。

  void StopAllCoroutines()

  停止该behavior内的全部协程

  void SetActive(bool value);

  将behavior的active设为false后,其内部的协程也都会停止。

3.返回值
  1. null和其它的数值,如0:
        和null类似,不过不推荐。因为会存在装箱,拆箱的问题,或多或少会影响性能。

  2. WaitForEndOfFrame
       等待至所有的Camera和GUI都呈现好了之后执行。

  3. WaitForFixedUpdate
       等待至所有物理都计算后执行
 
  4. WaitForSeconds
       在指定时间段内不执行

  5. WWW
       等待一个web请求完成

  6. 另一个协程
      这是比较有意思的一点。因为StartCoroutine的返回值是Coroutine,所以我们可以yield另一个协程。

      要注意的是,如果设置Time.timeScale为0时,yield return new WaitForSeconds(x)是不会恢复继续执行。

2.Prefabs

  优点:   

  1.      Prefab一个重要的优势就是编辑prefab资源后,场景中所有使用Prefab克隆的游戏对象将全部使用新编辑的资源,无需一个一个的给场景中的对象赋值。  
  2. 当游戏中需要频繁创建一个物体时,使用Prefab能够节省内存。
  3. 不论项目中存在多少实例。仅仅要对Prefab进行了改动。全部Prefab实例都将随之发生变化。
  4. 能够放到多个场景中。也能够在同一个场景中放置多次

   不便之处没查到资料,想了想觉得有以下几点:

     1.资源加载分类

     2.嵌套关联关系处理

   希望知道更多的童鞋能给博主留个言~

3.资源加载

    参考链接中有之前写过的关于AssetBundle使用的文章,在此不再多说,只是总结下相关知识

1.加载AssetBundle文件
Unity提供了三种不同的方法来加载AssetBundle,代码如下: 
  第一种:AssetBundle.LoadAsset
    // 通过资源名称标识名做为参数来加载对象
    public Object LoadAsset(string name);

  第二种:AssetBundle.LoadAssetAsync
    //执行方法类似前面的LoadAsset方法,但是在加载资源时不会阻碍主线程
    public AssetBundleRequest LoadAssetAsync(string name);

  第三种:AssetBundle.LoadAllAssets
   // 加载AssetBundle中包含的所有资源对象,并且可以通过对象类型来过滤此资源
     public Object[] LoadAllAssets(Type type);

2.卸载AssetBundle文件
卸载AssetBundle文件比加载要容易一些,我们需要使用AssetBundle.Unload方法来卸载AssetBundle创建出来的对象:
  // 释放AssetBundle文件内存镜像,但不销毁已经加载好的Assets对象
  AssetBundle.Unload(false);
 // 释放AssetBundle文件内存镜像,并同时销毁所有已经加载的Assets对象
  AssetBundle.Unldoad(true);

3.下载AssetBundle文件
  ①.AssetBundle.LoadFromMemoryAsync(异步,对应还有同步方法)
  ②.AssetBundle.LoadFromFile(也有对应的异步方法)
  ③.WWW.LoadFromCacheOrDownload
  ④.UnityWebRequest
  使用参考链接: https://blog.csdn.net/dengshunhao/article/details/80486774

   路径相关知识:

      资源文件夹的区别

资源类型 注释
Resources

是作为一个Unity3D的保留文件夹出现的,也就是如果你新建的文件夹的名

字叫Resources,那么里面的内容在打包时都会被无条件的打到发布包中。

它的特点简单总结一下就是:只读,即不能动态修改。所以想要动态更新

的资源不要放在这里。会将文件夹内的资源打包集成到.asset文件里面。

因此建议可以放一些Prefab,因为Prefab在打包时会自动过滤掉不需要的

资源,有利于减小资源包的大小。主线程加载。资源读取使用

Resources.Load()。

StreamingAssets

要说到StreamingAssets,其实和Resources还是蛮像的。同样作为一

个只读的Unity3D的保留文件夹出现。不过两者也有很大的区别,那就

是Resources文件夹中的内容在打包时会被压缩和加密。而

StreamingAsset文件夹中的内容则会原封不动的打入包中,因此

StreamingAssets主要用来存放一些二进制文件。下面也同样做一个简

单的总结:同样,只读不可写。主要用来存放二进制文件。只能用过

WWW类来读取。

AssetBundle

关于AssetBundle的介绍已经有很多了。简而言之就是把prefab或

者二进制文件封装成AssetBundle文件(也是一种二进制)。但是

也有硬伤,就是在移动端无法更新脚本。下面简单的总结下:是

Unity3D定义的一种二进制类型。最好将prefab封装成AseetBundle,

不过上面不是才说了在移动端无法更新脚本吗?那从Assetbundle中

拿到的Prefab上挂的脚本是不是就无法运了?也不一定,只要这个

prefab上挂的是本地脚本,就可以。使用WWW类来下载。

PersistentDataPath

看上去它只是个路径呀,可为什么要把它从路径里面单独拿出来

介绍呢?因为它的确蛮特殊的,这个路径下是可读写。而且在IOS

上就是应用程序的沙盒,但是在Android可以是程序的沙盒,也可

以是sdcard。并且在Android打包的时候,ProjectSetting页面有一

个选项Write Access,可以设置它的路径是沙盒还是sdcard。下面

同样简单的总结一下:内容可读写,不过只能运行时才能写入或者

读取。提前将数据存入这个路径是不可行的。无内容限制。你可以

从StreamingAsset中读取二进制文件或者从AssetBundle读取文件来

写入PersistentDataPath中。写下的文件,可以在电脑上查看。同样

也可以清掉。

Unity中的资源路径

路径字段 注释
Application.dataPath

此属性用于返回程序的数据文件所在文件夹的路径

。例如在Editor中就是Assets了。

Application.streamingAssetsPath

此属性用于返回流数据的缓存目录,返回路径为相对路径

,适合设置一些外部数据文件的路径。

Application.persistentDataPath

此属性用于返回一个持久化数据存储目录的路径

,可以在此路径下存储一些持久化的数据文件。

Application.temporaryCachePath 此属性用于返回一个临时数据的缓存目录。

    Android中的资源路径

路径字段 具体路径
Application.dataPath

/data/app

/xxx.xxx.xxx.apk

Application.streamingAssetsPath

jar:file:///data/ap

p/xxx.xxx.xxx.apk

/!/assets

Application.persistentDataPath

/data/data

/xxx.xxx.xxx/files

Application.temporaryCachePath

/data/data

/xxx.xxx.xxx/cache

Android中有一个小小的注意点:在Android可以是程序的沙盒,也可以是sdcard。并且在Android打包的时候,ProjectSetting页面有一个选项Write Access,可以设置它的路径是沙盒还是sdcard。 
       IOS中的资源路径

路径字段 具体路径
Application.dataPath Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data
Application.streamingAssetsPath

Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.ap

p/Data/Raw

Application.persistentDataPath

Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx

x/Documents

Application.temporaryCachePath

Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx

x/Library/Caches

4.预处理命令(#if #endif)

当C#编译器遇到一个由#if和#endif包围起来的语句块时,会检查#if后面的符号是否已经被定义了,如果已经被定义,那么才会编译语句块之间的代码。而定义一个可以被#if测试的符号需要事先用#define指令定义。(或/define指令,效果一样)

// 使用#define定义了一个DEBUG和MYTEST符号
#define DEBUG
#define MYTEST  
using System;  
public class MyClass   
{  
    static void Main()   
    {  
#if (DEBUG && !MYTEST)  // 不为true 以下代码不编译
        Console.WriteLine("DEBUG is defined");  
#elif (!DEBUG && MYTEST)  
        Console.WriteLine("MYTEST is defined");  
#elif (DEBUG && MYTEST)  // 为true,以下代码编译
        Console.WriteLine("DEBUG and MYTEST are defined");  
#else  
        Console.WriteLine("DEBUG and MYTEST are not defined");  
#endif  
    }  
}

除了用代码定义宏之外,还可以用:

如果你使用的Visual Studio编辑器,那么也可以在项目中定义全局宏

5.Unity生命周期

(1) Reset(): 组件重设为默认值时(只用于编辑状态)
(2)Awake() : 脚本组件载入时 (调用一次)
(3)OnEnable() : 是在游戏对象可以调用时调用
(4) Start() : 第一个Update发生之前 (调用一次)
(5)FixedUpdate() : 固定时间调用,常用于物理相关的计算,比如对Rigidbody的操作
(6)Update() : 大部分游戏行为代码被执行的地方,除了物理代码
(7)LateUpdate() : 每帧Update调用之后,物理代码一般放在这
(8)OnGUI() : 绘制GUI时调用
(9)OnDisable() : 当对象设置为不可用时
(10)OnDestroy() : 组件销毁时调用

全部生命周期:

生命周期常用简图:

参考链接:

   1.协程全解:http://www.cnblogs.com/mezero/p/3953838.html

   2.AssetBundle使用 : https://blog.csdn.net/dengshunhao/article/details/80480617

   3.AssetBundle分组策略 : https://blog.csdn.net/dengshunhao/article/details/80492836

   4.预处理命令 : https://www.cnblogs.com/plateFace/p/4282556.html

   5.生命周期 : https://www.jianshu.com/p/8c353abb42e4

猜你喜欢

转载自blog.csdn.net/dengshunhao/article/details/81280545
今日推荐