Unity 面试题整理2020

一.Unity部分

1. Mask和RectMask2D 区别

 区别点1:
  mask:可以处理不规则图形遮罩 依赖Image组件 剪裁范围是Image大大小
  rectMask2D:只能处理矩形遮罩效果,不依赖Image组件,剪裁范围是他RectTransform的rect大小

 区别点2:
  mask:会在首尾(首=mask节点 尾=maks节点的子节点遍历完毕) –产生2个drawcall 并且Mask会增加一层的overdraw
  rectMask2D:rectMask2D 不产生drawcall

 区别点3:
  mask:多个maks之间如何符合合批的条件 就可以合批 (mask1的首和mask2的首 合批 mask1的尾和mask2的尾合批 首尾不能合批–需要同渲染层级depth 同材质,同图集)
  rectMask2D:多个rectMask2D之间不能合批

 相同点4:
  rectMask2D:mask和rectMask2D的内部和外部不能合批

2. 手指/鼠标如何判断向左向右向上向下

在平面组成的2D坐标系上,分为四个象限,再分为8块,
例如:当一个方向为东北或者西北上面时,记为“向上滑”
Unity 面试题整理2020_第1张图片

	if (m_Dir.y < m_Dir.x && m_Dir.y > -m_Dir.x)//向右
	    dir = FingerDragDir.right;
	else if (m_Dir.y > m_Dir.x && m_Dir.y < -m_Dir.x)//向左
	    dir = FingerDragDir.left;
	else if (m_Dir.y > m_Dir.x && m_Dir.y > -m_Dir.x)//向上
	    dir = FingerDragDir.up;
	else if (m_Dir.y < m_Dir.x && m_Dir.y < -m_Dir.x)//向下
	    dir = FingerDragDir.down;1部分 m_Dir.y < m_Dir.x-->向右--》
	x=斜边*cos(度数)  y=斜边*sin(度数)
	度数在[0,45]之间 cos() < sin()--》y<x

3. 向量的点乘和叉乘

点乘:
 点积的计算结果是个标量,只有大小 没有方向,也称为标量积
 公式:UV=UxVx+UyVy+UzVz==》|U|*|v|*cos(θ)==》U·V=V·U
 几何意义:
  U * V=0–》U和V相互垂直
  U * V>0–》U和V夹角小于90度,V在U的前方
  U * V<0–》U和V夹角大于90度, V在U的后方
 用途:
  ①计算2个向量之间的夹角 θ∈【0-180】

	//如果u、v都是单位向量,u.v=cos(a)==>a:
    private float GetAngle(Vector3 u, Vector3 v)
    {
        var dot = Vector3.Dot(u.normalized, v.normalized);//计算角度
        var cross = Vector3.Cross(u.normalized, v.normalized);//叉乘判断顺时针【+】逆时针【-】
        // 通过反正弦函数获取 向量 u、b 夹角(默认为 弧度)  
        float radians = Mathf.Acos( dot);
        // 将弧度转换为 角度  
        var angle = radians * Mathf.Rad2Deg;

        if (cross.z < 0)//逆时针
            angle = -1 * angle;

        return angle;
    }//==>Vector3.SingleAngle
    
	// 通过向量直接获取两个向量的夹角(默认为 角度), 此方法范围 [0 - 180]  
	float angle = Vector3.Angle(a, b); 

  ②判断敌人在自己的前方还是后方
   Vector3.Dot(transform.forward, target.position-transform.position)
   返回值为正(0<夹角<90)时,目标在自己的前方,反之(90<180)在自己的后方
  ③计算投影向量
Unity 面试题整理2020_第2张图片

叉乘:
 叉乘结果是向量,其模是两个向量为边的平行四边形面积,叉积只能用于3D向量,2D向量没有叉积
 公式:UV=(UxVy-UyVx)+(UxVz-UzVx)+(UyVz-UzVy)》|U|*|v|*sin(θ)**》U·V=-V·U
 计算方式:
  对2个3D向量 u、v 计算叉积 结果w 向量 同时垂直于 u和v
  左手拇指法则:提起左手,将拇指之前的 4个手指指向第一个向量u,然后朝着v的方向 沿角度 0  用途:
  ①计算2个向量之间的夹角 θ∈【0-90】

	//如果u、v都是单位向量,u.v=sin(a)==>a:
	private float GetAngle(Vector3 u, Vector3 v)  
	{  
	    // 计算 u、v 单位向量的叉积,得到夹角正弦值,|u.normalized|*|v.normalized|=1;  
	    var result = Vector3.Cross(u.normalized, v.normalized);  
	    // 通过反正弦函数获取 向量 u、b 夹角(默认为 弧度)  
	    float radians = Mathf.Asin(result);  
	    // 将弧度转换为 角度  
	    var angle = radians * Mathf.Rad2Deg;  
		return angle;
	} 

  ②计算平面法线 【法线:垂直一个平面的向量】
  ③求转向【顺时针还是逆时针】

	判断顺、逆时针,是在 2D 平面内的,所以需指定一个平面,下面以X、Z轴组成的平面为例,--》判断Y轴上的正负,即为“叉乘的正负值”,判断 b 在 a 的顺时针或者逆时针方向。
	Vector3 c = B.position - A.position;
    CrossTest(A.forward, c.normalized);
	private void CrossTest(Vector3 tmpA, Vector3 tmpB)
	{
	    Vector3 result = Vector3.Cross(tmpA, tmpB);
	    if(result.y> 0)
	        Debug.Log("tmpB在 tmpA的顺时针方向");
	    if (result.y == 0)
	        Debug.Log("tmpB在tmpA同向");
	    if (result.y < 0)
	        Debug.Log("tmpB在tmpA的逆时针方向");
	}
	
	Vector3.Cross(transform.forward, target.position-transform.position).y
	返回值为正时,目标在自己的右方,反之在自己的左方

  ④计算出两向量组成的平行四边形面积
Unity 面试题整理2020_第3张图片

	根据平行四边形公式  S=a*h,h为高,a为底。a = |a|
	又因为h = |b|*sinθ,则 a*h = |a|*|b|*sinθ 即 |aXb| = S
  1. Unity的协程作用及用途
     ①协程是:主线程运行的同时开启另一段逻辑处理,来协助当前程序的执行,协程不是多线程。Unity的协程是在每帧结束之后去检测yield的条件是否满足
     ②主要用于:延时、WWW、等待异步加载、等待某个条件是否满足
     ③协程和多线程的区别:
      多线程是独立于主线程的,同一时间可以有多个多线程运行。协程只能存在于主线程,同一时间最多执行一个协程。
     ④协程和子程序(方法)区别:
      如加载文件,子程序会卡主主线程,直到加载完毕,才执行下面程序。协程类似异步,主线程执行加载文件,只加载0.1s然后挂起执行其他程序,主线程下次再来,恢复协程,以此往复,不卡主线。

  2. 防止UI穿透

    /// 
    /// 检测是否点击3d对象【自己实现的 UI防穿透、移动端有效】
    /// 
    public static bool CheckIsClick3DObj_Self()
    {//EventSystem.current.IsPointerOverGameObject Unity自带的 移动端无效
        EventSystem eventSystem = EventSystem.current;
        PointerEventData eventData = new PointerEventData(eventSystem);
        if (Application.isMobilePlatform)//移动端
        {
            if (Input.touchCount > 0)
            {
                eventData.pressPosition = Input.GetTouch(0).position;
                eventData.position = Input.GetTouch(0).position;
            }
        }
        else//Unity_Editor 下或者电脑上能运行
        {
            eventData.pressPosition = Input.mousePosition;
            eventData.position = Input.mousePosition;
        }
        List<RaycastResult> list = new List<RaycastResult>();
        eventSystem.RaycastAll(eventData, list);
        //graphicRayCaster.Raycast(eventData, list);
        return list.Count > 0;
    }
    
  3. transform.forward和Vector3.forword的区别:
    Unity 面试题整理2020_第4张图片
    7.2D和3D混合界面 的渲染顺序
    Unity 面试题整理2020_第5张图片

二.C#部分

  1. 排序算法–[原理]

    常见的冒泡、选择、插入、希尔、归并、快速排序
    详细讲解

  2. 值类型与引用类型作用、区别

    值类型:
     数字类型:整形(u)byte (u)short (u)int (u)long 浮点类型double float decimal
     布尔类型:bool
     复合类型:enum struct
    引用类型:
     数组:Array、字符串:string、类:class、接口:interface、委托:delegate、object

    区别:
     1.值类型的变量和值在栈中分配,引用类型变量在栈中分配,引用实例在堆中分配
      譬如:Object A=new A(); 变量A存放在栈区,栈区A的值存放的是引用对象的地址,引用对象的内容是存放在堆
     2.值类型数据读取速度快,引用类型数据读取速度满
     3.栈中的内存自动回收,堆中的内存由.net的GC自动释放
     4.值类型继承System.TypeValue,引用类型继承System.Object
     5.值类型变量在赋值或传递参数时,是重新开辟空间,将值拷贝给新的变量
     6.引用类型变量的数据一修改,所有指向同一地址的变量的数据都会修改

  3. 抽象类与接口区别:

     抽象类和接口都不能实例化,继承都必须实现所有抽象方法
     抽象类不是完全抽象可以有抽象和未抽象的方法,接口是完全抽象
     抽象类可以定义属性、构造函数,接口不能定义
     接口是多继承的,类是单继承的
     接口是不能用访问修饰符修饰,抽象类必须用public修饰

  4. 类与结构体区别:

     类是引用类型,存储在堆中,内存GC回收,结构体是值类型,存储在栈中,内存自动回收。
     定义成员类可以初始化,结构体只有static\cost的可以,数据成员不行
     类的变量可以设置null,结构体不行
     类定义无参构造和私有无参构造,结构体只能定义有参构造,且必须为所有成员赋初始值
     类有析构函数,结构体没有
     类可以被继承,结构体不能被继承。
     结构体适用于数据量小,层级简单。类适用于数据量大或层级复杂比如多继承。

三.Lua部分

四.优化部分

  1.UI优化:

    1.将同一画面图片放到同一图集中

    2.图片和文字尽量不要交叉,会产生多余drawcall(相同材质和纹理的UI元素是可以合并的)

    3.UI层级尽量不要重叠太多

    4.取消勾选不必要的射线检测RaycastTarget

    5.将动态的UI元素和静态的UI元素放在不同的Canvas中,减少canvas网格重构频率

你可能感兴趣的:(#Unity,杂类,unity面试题)