区别点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的内部和外部不能合批
在平面组成的2D坐标系上,分为四个象限,再分为8块,
例如:当一个方向为东北或者西北上面时,记为“向上滑”
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
点乘:
点积的计算结果是个标量,只有大小 没有方向,也称为标量积
公式: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)在自己的后方
③计算投影向量
叉乘:
叉乘结果是向量,其模是两个向量为边的平行四边形面积,叉积只能用于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
返回值为正时,目标在自己的右方,反之在自己的左方
根据平行四边形公式 S=a*h,h为高,a为底。a = |a|
又因为h = |b|*sinθ,则 a*h = |a|*|b|*sinθ 即 |aXb| = S
Unity的协程作用及用途
①协程是:主线程运行的同时开启另一段逻辑处理,来协助当前程序的执行,协程不是多线程。Unity的协程是在每帧结束之后去检测yield的条件是否满足
②主要用于:延时、WWW、等待异步加载、等待某个条件是否满足
③协程和多线程的区别:
多线程是独立于主线程的,同一时间可以有多个多线程运行。协程只能存在于主线程,同一时间最多执行一个协程。
④协程和子程序(方法)区别:
如加载文件,子程序会卡主主线程,直到加载完毕,才执行下面程序。协程类似异步,主线程执行加载文件,只加载0.1s然后挂起执行其他程序,主线程下次再来,恢复协程,以此往复,不卡主线。
防止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;
}
常见的冒泡、选择、插入、希尔、归并、快速排序
详细讲解
值类型:
数字类型:整形(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.引用类型变量的数据一修改,所有指向同一地址的变量的数据都会修改
抽象类和接口都不能实例化,继承都必须实现所有抽象方法
抽象类不是完全抽象可以有抽象和未抽象的方法,接口是完全抽象
抽象类可以定义属性、构造函数,接口不能定义
接口是多继承的,类是单继承的
接口是不能用访问修饰符修饰,抽象类必须用public修饰
类是引用类型,存储在堆中,内存GC回收,结构体是值类型,存储在栈中,内存自动回收。
定义成员类可以初始化,结构体只有static\cost的可以,数据成员不行
类的变量可以设置null,结构体不行
类定义无参构造和私有无参构造,结构体只能定义有参构造,且必须为所有成员赋初始值
类有析构函数,结构体没有
类可以被继承,结构体不能被继承。
结构体适用于数据量小,层级简单。类适用于数据量大或层级复杂比如多继承。
1.将同一画面图片放到同一图集中
2.图片和文字尽量不要交叉,会产生多余drawcall(相同材质和纹理的UI元素是可以合并的)
3.UI层级尽量不要重叠太多
4.取消勾选不必要的射线检测RaycastTarget
5.将动态的UI元素和静态的UI元素放在不同的Canvas中,减少canvas网格重构频率