这是我前一阵子找实习所准备的有关内容,部分是来自于网上搜索到的别人的面经问题,部分是自己整理的一些比较基础的问题。这里我主要是自己又整理了一遍,结合网上的解释,以自己的理解写了写问题的解答。大家可以参考一下。有什么不太正确的地方,欢迎大家指正。
分为四部分:渲染、unity、C#、其他。
流水线:
Cpu应用阶段,gpu几何阶段,光栅化阶段。
应用阶段:主要是指用户在unity上面的操作包括准备场景数据(模型、光源、摄像机位置等)
粗粒度剔除(不可见物体的剔除、优化、不留到集合阶段深度检测)
设置模型的渲染状态(材质纹理、shader)
↓(输出渲染所需要的集合信息“渲染图元”,包括点、线、三角面)
几何阶段:定点着色器(顶点空间变换、顶点着色、把顶点坐标转换到齐次裁剪空间)
可选的曲面细分着色器、几何着色器
裁剪(将不在摄像机范围内的顶点裁剪掉)
屏幕映射(降维,把图元坐标系(三维)转换到屏幕坐标系(二维)中,但是Z坐标会保留与屏幕坐标系形成窗口坐标系供深度检测使用)
↓(输出屏幕坐标系、z坐标、法线方向、视角方向)
光栅化阶段:三角形设置(三角形边界表示方式)、三角形遍历(扫描变换,计算哪些片元被三角形覆盖、返回一个片元序列片元不单单只一个像素还包括屏幕坐标、深度信息、顶点信息(法线、纹理坐标等))
片元着色器(逐片元操作、纹理采样)
逐片元操作(修改颜色、模板、深度、缓冲、混合)
顶点着色器作用
细分曲面着色器
几何着色器
三种shader语言的区别:
OpenGL Shader Language,High-Level Shader Language,C for Graphic。
GLSL(OpenGL):跨平台、没有提供着色器编译器、依靠显卡驱动完成编译工作、不同显卡不同驱动编译效果不同。
HLSL(DirectX):微软提供着色器编译器、不同硬件效果相同但是只限windows、xbox等。
Cg:真正意义跨平台、微软NVIDIA合作,根据不同平台编译成相应的中间语言。
前向渲染、延迟渲染的区别:
前向渲染流程:1遍历所有三角形片元。2深度检测。3通过检测的进行光照计算。4更新帧缓冲区域。在5回到1直到遍历结束。第三部会产生多余的计算。
延迟渲染:1遍历所有三角形片元。2深度检测。3通过的将坐标与光照信息写入GBuffer。4返回1直到光源遍历结束。5遍历GBuffer。6利用GBuffer中的数据进行光照计算。7更新缓冲区域。8返回5直到遍历结束。
区别:前者,通过了深度检测就会计算光照,但是在遍历了新的片元后,若深度检测使得覆盖之前的,这使得前面的计算光照就白做了。后者将所有的片元遍历完后,通过深度检测,把通过的写入GBuffer,再遍历GBuffer中的数据进行高效的,无浪费的光照计算,再更新到缓冲区域。这里称之为延迟。
AlphaTest和Alpha Blend:
透明度测试:得到的结果非常极端,要么完全透明,要么完全不透明。原因是:只要一个片元的透明度不满足条件,就会被舍弃,否则就会按照普通的不透明物体来进行深度测试、写入深度缓冲。不需要关闭深度写入,与其他普通物体最大的区别是会根据透明度来舍弃一些片元。
透明度混合:可以得到真正的半透明效果,它沪江当前的透明度作为混合因子,与颜色缓冲区域中的颜色值进行混合,得到新颜色。需要关闭深度写入(如果不关闭,做透明时原本后面的能够显示出来参与混合的,就被“遮挡”,不显示了),不关闭深度检测,要小心物体的渲染顺序。如果先渲染了半透明的前面的物体,在渲染后面的物体,后面的物体就会被挡住。透明度混合渲染一个物体时,也会比较深度缓冲中的值,如果更远,就不会进行混合操作了。
补充,透明度混合的原理:
Color=原颜色alpha/255
卡通渲染、阴影和描边
渲染:需要不同的贴图
阴影:卡通渲染的阴影没有那么强烈(具有比较分明的明暗变化),可以通过shader修改顶点的法线,来调整光打在物体上产生的阴影
描边:两次pass,先只显示背面,把背面膨胀一点点(法线外扩)。然后再把正面的模型做正常渲染。然后叠加起来就有描边的效果
pbr美术流程:
PBR:基于物理的渲染过程是一种着色和渲染技术,尝试基于真实世界光照物理模型,用于更精确的描述光如何与物体表面互动。可以通过直接的物理参数来直观地达到想要的结果,不用通过拙劣的各种参数来调整,物理参数一般直接通过贴图来传递给Shader。
优势:方法论和算法基于精确的计算公式免除创作表面的猜想过程。在任何光照环境都能表现出正确的结果。为不同的艺术家,提供统一的工作流程。
材质工作流:
金属/粗糙度工作流(Metal/Roughness):
basecolor:RGB贴图反照率颜色Albedo或F0,不含任何光照信息。
metallic:灰度贴图遮罩,表示金属成分的占比,1表示纯金属。
roughness:灰度贴图,数值越大越粗糙。
镜面反射/光泽度工作流(Specular/Glossiness):
diffuse:Albedo RGB贴图,如果是金属diffuse贴图给出的值是纯黑(0)。
specular:RGB贴图定义金属和非金属的F0。
glossiness:灰度贴图,数值越大越光滑,与M/R的roughness相反。
F0:入射角为0度时的反射光线radiance占入射光线radiance的比例。非金属反射的光线比金属少,F0更小,0.04。
光照模型:
当物体的几何形态确定后光照决定了整个场景的显示结果因此,真实感图形的生成取决于如何建立一个合适的光照模型光照模型即模拟物体表面的光照物理现象的数学模型。根据材质属性、光源信息使用相应公式去计算沿着某个观察方向的出射度的过程,这种公式被称为光照模型。
Lambert模型(漫反射):能够较好地表现粗糙表面上的光照现象,如石灰墙,纸张等等,但是在渲染金属材质制成的物体时,则会显得呆板,表现不出光泽,主要原因是其没有考虑到镜面反射效果。
Phong模型(镜面反射):对Lambert模型其进行了很好的补充。
Blinn-Phong模型(修正镜面光):渲染效果比Phong模型更加柔和。但是由于引入了半角向量来对比法线向量来计算光照,使得光照计算更快,成为了大多数cg软件的光照渲染方法。在OpenGL和Direct3D渲染管线中,Blinn-Phong就是默认的渲染模型。
Rendering Equation(全局光照模型):
几种抗锯齿:
super sampling AA(SSAA超级采样):将渲染的分辨率成倍提高然后再降采样将多个像素融合,映射回显示器。性能差。
multi sampling AA(MSAA多重采样):对边缘部分进行放大分辨率然后缩小像素性能差。
fast approximate AA(FXAA快速近似):通过亮度和对比度提取“边缘”像素进行模糊。
subpixel morphological AA(SMAA):一系列算法、检测边缘、然后模糊。
BRDF光照模型:
当已知光源位置和方向、视角方向时,我们就需要知道一个表面是如何和光照进行交互的。当光线从某个方向照射到一个表面时,有多少光线被反射?反射的方向有哪些。BRDF就是回答这个问题的。
BRDF中法线分布函数的定义
DrawCall多少为好,怎样减少:
150一下、游戏优化、代码、模型、渲染方面)
批处理,动态批处理,静态批处理。
unityGI(global illumination全局光照):
全局光照分为直接光源和间接光源,直接光源就是灯光对象,间接光源就是物体表面在接受光照后反射发出来的光。局部光照没有反射光。没有GI阴影部分会黑的比较严重,打开GI由于光线的反射,阴影正常。
优化内存:
1、将暂时不用而以后要用的物体隐藏而非直接Destory
2、降低模型的片面数 ,骨骼数量,贴图分辨率
3、使用LightMap光照贴图,使用LOD多层次细节,使用shader着色器,使用预设prefab,使用MipMap
4、代码中少使用临时变量
半角向量意义:
半角向量H是光照向量L(实际上应该是平面上该点指向光源的向量),与观察者向量V的取中向量。观察者向量与反射向量越接近,半角向量与法向量N越接近,观察者看到镜面光成分越强
Phong光照是比较反射方向和视线方向的夹角,而Blinn-Phong光照,是比较半角向量与法线的夹角。半角向量计算比反射向量计算的复杂度要简单的多,这样Blinn-Phong的性能要高得多。OpenGL的固定渲染管线就是实用的Blinn-Phong。
LOD(level of detail)多层次细节
最常用的游戏优化技术,按照模型的位置和重要程度,来决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染计算,但是增加了内存。
MipMap:
Mipmap是一种贴图,目的是为加快渲染速度和减少图形锯齿。
应用在纹理贴图 ,当摄像机离得远则贴图模糊,离得近则清晰 。
LightMap:光照贴图
在三维软件里打好光,然后渲染把场景各表面的光照输出到贴图上,最后又通过引擎贴到场景上 ,使得物体有了光照的感觉 。
场景渲染顺序(渲染队列render queue)
Unity提供了自己的渲染队列,可以用SubShader的Queue标签来决定模型属于哪个渲染队列。内部用一系列整数索引来表示每个渲染队列,索引号越小越早被渲染。
geometry:几何结构 overlay:覆盖物
齐次矩阵
33矩阵可以用来旋转、缩放,但是不能移动坐标系。需要在4维空间切变实现3维平移(3维空间实现2维平移),44平移矩阵不会影响旋转、缩放功能。4维向量中w分量能开关4*4矩阵的平移部分。齐次坐标系,描述透视关系。
Unity可以合并哪些纹理
阴影算法PCF(percentage-closer filtering)
PCF算法消除阴影的锯齿,也就是实现软阴影(soft shadows)。
1、正常渲染场景得到ShadowMap
2、形成一张2D的仅有黑白的纹理图
3、模糊算法处理,模糊阴影的锯齿
4、对表面进行正常渲染,用模糊后的黑白色2d纹理对地面进行阴影处理
真实流水的实现
除了真实的流体计算以外,还有一种简易的方式,计移动贴图的UV坐标,在静态物体贴图上模拟出水流的效果。
表面着色器方法,有个内置的变量,IN.uv_MainTex,对其做偏移处理(加上流速等)。
卡通湖泊
1、水颜色的渐变,模拟水的深度渐变:基于深度着色,对不同深度值进行边界控制,分配颜色。计算湖面与地面的距离,从而对湖面颜色进行渐变。计算两者到摄像机的深度差来模拟,恰好_CameraDepthTexture可以获得摄像机到地面的深度值。水面渲染应该在地面渲染之后,才能得到正确的深度信息,可以通过设置渲染队列Render Queue来实现。
2、白色的波浪:噪声图,对灰度值进行边界处理,加上UV动画
MVP矩阵空间变换过程
M矩阵中旋转、平移、缩放顺序,分别在M矩阵的哪个部分
颜色模型
显示器:RGB,[0,255],加色混色模型
印刷出版:CMYK青(Cyan) 品红(Magenta) 黄(Yellow) 黑(blacK)减色混色模型(颜色混在一起亮度会降低),加入k是因为由CMY组成的黑色不够纯粹。
HSV:色相(Hue)(颜色的相貌)、饱和度(Saturation)(色彩的纯净度)、明度(Value/Brightness)
菲涅尔效果
指当光到达两种材质的接触面时,一些光在接触面的表面被反射出去,而另一部分光将发生折射穿过接触面。
高斯模糊原理
模糊,可以理解成每一个像素都取周边像素(九宫格中间像素的周围一圈像素)的平均值。既然每个点都要取平均值,那么应该如何分配权重?加权平均,距离近的点权重大,距离远的点权重小。
高斯模糊,用高斯分布(正态分布)来取中心点周围点的权重。
边缘检测(采样)
灰度或者结构等的信息突变之处称为边缘,反应在数据上,可以看到灰度值会有一定的跃迁变化,可以通过求导数,设定合适的阈值来提取图像的边缘。
延迟渲染中 GBuffer每次渲染存储的什么数据
几何信息(位置坐标、法线向量、纹理坐标、反射系数)
几种光照模型
shadowmap底层原理(屏幕空间阴影映射技术)
将摄像机与光源位置重合,会有一张光源空间的深度信息图,这就是shadow map。凡是物体的深度值大于shadow map上的深度值得都是被遮挡的部分,表示处于阴影之中。
unity光照系统
平行光、点光源、聚光灯、区域光。反射探头、光照探头组。
unity烘培、光照探针LightingProbe、光照图
烘培:烘培完毕后,删除灯光,而光照贴图已经赋给了游戏物体,灯光的作用已经消失了。静态物体可以这么做,但是场景中新增了一个动态物体,就应该使用混合光照。
光照探针,烘培为了减小光照的性能消耗,但是烘培把光照信息变成了一张光照贴图,并不会有反射,所以加入动态物体,可能出现物体不受反射光的影响。光照探针就可以保证物体可以通过环境中的光改变自身的颜色,又能保证性能比较好。
混合光照
混合光照时提供一种介于全烘培光照和全实时光照的一种折中方案,即某些物体的光照采用烘培另一些物体的光照采用实时计算。
subtractive:烘培后,动态物体只受一盏主光源影响。
shadowmask:动态静态都能显示完整的阴影效果,但是动态物体不受静态物体的阴影影响。
baked indirect:只烘培间接光,其余均为实时光照,是最高级的模式。
shadowmask shadow mask distance
烘培阴影后,动态物体处于静态物体阴影之中,并未受到阴影的影响。
把混合光照的渲染模式shadowmask更改为Shadowmask Distance。shadow distance数值为150,就表示摄像机视野的150米内,所有静态物体的阴影不是光照贴图预先计算好的阴影,而是实时计算的,动态物体就会受到阴影的影响。
后处理
包括雾特效、抗锯齿、景深、运动模糊、Bloom高光模糊
tiling贴图、普通贴图脏迹
法线贴图
URP、HDRP
变换矩阵每一列
现在需要在UI层绘制一个圆,使用图片难免受到分辨率的影响,如何用shader来实现(屏幕空间,UV)
unity函数调用顺序,脚本生命周期:
Awake-OnEnable-Start-Update-FixedUpdate-LateUpdate-OnGUI-OnDisable-OnDisabled-OnDestory
进程、线程、协程(协程是unity中的一种多线程机制):
进程:操作系统进行资源分配的最小单位。是操作系统对正在运行的程序的一种抽象,打开一个浏览器、一个聊天窗口分别就是一个进程,进程可以有多个子任务,如聊天工具接收消息、发送消息,这些子任务是线程。
线程:CPU调度和分配的基本单位。一个进程可以由多个线程的执行单元组成。线程数是一种逻辑概念,模拟出CPU的核心数
协程:单核并行两个线程,操作系统会在两个线程之间切换,达到伪并行(并发)的效果。而协程的方式是先运行协程A、结束时让位给协程B,只发生一次切换,提高整体效率。双核就可以让AB两个线程实现真并行。
Unity中的协程:
Unity协程长得有点像线程,但不是线程,因为协程仍然在主线程中执行。协程只是控制代码等到特定的时机后再执行后续步骤。
开启协程:StartCoroutine(func())、StartCoroutine(func(1))、StartCoroutine(“func”)、StartCoroutine(“func”,1),以上可以开启当前MonoBehaviour对象的协程。
协程有许多种等待方式,如等到FixedUpdate结束后才执行:
void FixedUpdate(){}
IEnumerator Coruting_WaitForFixedUpdate(){}
总结:在脚本生命周期中的固定地方,插入步骤,如上面提到的,再调用了一次FixedUpdate()后面执行协程。等等
Animator-Parameters
Animator面板中的Parameters(参数)中有四个类型:float、int、bool、trigger。
在脚本中获取Animator组件后,可以ResetTrigger()和SetTrigger()来控制trigger。
Animator中每个动画之间的线的Conditions可以添加Parameters设置的trigger变量,代表走这条线的条件。
trigger设置(触发)一下后就会迅速重置为未触发状态。
碰撞体OnCollisionEnter如何做碰撞检测,触发器OnTriggerEnter
两者的触发条件是不相同的。
共同要求:碰撞的两个物体都要有碰撞体(collider)。
当A、B都添加了刚体(Rigidbody):
OnCollisionEnter():
A、B碰撞时,无论是谁碰谁,两者都能触发OnCollisionEnter(),前提是两者都没有勾选isTrigger。
OnTriggerEnter():
A、B中有一个或者两个都勾选isTrigger后,A、B都可以触发OnTriggerEnter(),但是不能进入OnCollisionEnter()。
当A、B有一个添加了刚体(Rigidbody):
OnCollisionEnter():
若A有刚体,B无刚体,A碰B,A会被弹开,B不动,A、B都会OnCollisionEnter()。
若A有刚体,B无刚体,B碰A,不会发生碰撞效果,A、B都不会OnCollisionEnter()。
OnTriggerEnter():
只要A、B中有一个添加了刚体,无论谁碰谁,两者都会触发OnTriggerEnter()。
总结:
OnCollisionEnter()要求碰撞的发起方必须拥有刚体,而被碰撞方有无刚体不重要。
OnTriggerEnter()只需要双方有一个具有刚体即可触发。
补充:
OnCollisionEnter ():刚碰撞(接触)
OnCollisionStay ():一直接触着,每帧调用
OnCollisionExit ():离开,不接触
unity实现跨平台的原理
unity的跨平台技术是通过一个Mono虚拟机实现的。通过Mono将C#脚本代码编译成中间语言,Mono运行时在将中间语言编译成目标平台的原生代码以此实现跨平台。mono是.net的一个开源平台工具,类似Java虚拟机。.net只能在Windows下面运行,mono可以实现跨平台跑 ,C#是基于mono的.net。
Quaternion四元组:
transform.rotation实际上是个四元数,是不单纯的Vertor3(0,0,0),想要实现赋值,必须要用Quaternion.Euler(0,0,0),打印这个值就知道它是一个四元数。好处是避免万向锁。
还有一种方法就是transform.eulerAngles=new Vector3(0,0,0),也有localEulerAngles
矩阵旋转,使用了44的齐次矩阵来表示绕任意轴旋转的变换矩阵。旋转轴可以是任意向量,但是实际上旋转只需要知道一个向量和角度(四个值),而矩阵有16个值,乘法也会增加计算量。
欧拉旋转,按照每个轴旋转一定角度来变换坐标,是一系列轴旋转的组合。只需要3个值来表示,但实际上也是3个33的矩阵做变换。会造成“万向锁”(当两个旋转面重合,就会确实一个轴的旋转能力)。
四元数,本质是一种高阶复数,是一个四维空间。包括一个实部,虚部包含三个虚数单位i、j、k,一个四元数可以表示为x = a + bi + cj + dk。可以避免万向锁
对象池
对象池技术可以通过重复使用对象来降低堆内存的分配和回收频率。对象池在游戏中广泛的使用,特别是在游戏中需要频繁的创建和销毁相同的游戏对象的时候,例如枪的子弹这种会频繁生成和销毁的对象。
unity动态导入资源的方式
Resources.Load()
string url = “Data/Image/inside”;
inside = Resources.Load(url) as Texture;
AssetBundle打包
AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
AssetDatabase.loadset
Texture2D t = AssetDatabase.LoadAssetAtPath(“Assets/Textures/texture.jpg”, typeof(Texture2D)) as Texture2D;
WWW模块加载外部资源
WWW www = new WWW(“” + fileInfo.FullName);
outside = www.texture;
unity .meta文件
.meta存储两个重要信息:guid(Global Unique Identifier)、import settings.
guid是.meta中最重要的数据,每当资源导入时,unity就会为创建一个同名包含后缀的.meta。通过guid就可以找到工程中的这个文件,如果.meta的guid被修改了,其他资源对这个资源的引用就会失效
客户端接入第三方SDK
登录、分享、付费
Cinemachine
摄像机轨道设定,模拟现实的摄像机运动拍摄手法等。
ngui与ugui区别
DoTween
值、引用类型、栈(stack)和堆(heap):
值类型存储与栈,存储速度快,内存是自动调配的。引用类型存储于堆,存储速度慢,是通过GC去回收的
重写和重载:
重写override:父类方法无法满足子类的业务需求,需要对父类方法进行重写。子类中重写的方法,必须和父类中的方法一致,相同方法名、返回值类型、参数列表。 重载:函数或者方法有相同的名称相似的功能,但是参数列表不同。会根据不同的参数列表寻找相应的方法。
数组、ArrayList、List
数组在堆中存储,存储的类型都是相同的但是如果想在中间或者尾部插入数据就不方便。
ArrayList:解决了数组的缺点、方便插入删除 ,可以插入不同类型的数据因为所有的数据都转化成了Object类 。
List:转化成Object类用到装箱操作,非常消耗内存 。List指定了存储的类型 。
装箱操作:
值类型隐式转化成Object类型。1、在堆内存中开辟空间 。2、将值类型的数据复制到堆内存中 。3、返回堆中心分配对象的地址 。
拆箱操作:
装箱操作的逆向过程 ,从Object类型显示转换到值类型。1、判断给定的类型是否是装箱时的类型。2、返回已装箱实例中属于原值类型字段地址 。
sealed用于类声明和函数声明
用于类声明,密封类该类不能被其他类继承。
用于函数声明:不能被子类重写
HashMap HashTable
HashMap线程不安全,允许null key和null value,效率高于HashTable。
HashTable线程安全,在多线程并发的环境下,可以直接使用HashTable。
在不知道一个类的源码的情况下,怎么给这个类扩充方法、功能(虚函数)
在某个基类中声明为virtual并且在一个或多个派生类中重新定义的成员函数为虚函数。(允许在派生类中重新定义与基类同名的函数)
c# 各种值类型的长度,最大最小值
bool -> 布尔型,其值为 true 或者 false
char -> 字符型,占2字节,表示 1 个 Unicode 字符
short -> 短整型,占 2 字节,表示 16 位整数,范围 -32,768 ~ 32,767
int -> 整型,占 4 字节,表示 32 位整数,范围 -2,147,483,648 到 2,147,483,647
float -> 单精度浮点型,占 4 个字节
long -> 长整型,占 8 字节,表示 64 位整数,范围大约 -(10 的 19) 次方 到 10 的 19 次方
double -> 双精度浮点型,占8 个字节
c#的GC,unity的GC
C#的GC用来回收引用类型对象所占用的内存,只要某个对象和子对象没有任何有效的引用,即判定是垃圾,回收。CLR会进行托管,GC只负责回收托管对象,不负责回收非托管对象。
unity的GC,何时会触发GC:
堆内存上进行内存分配而内存不够时,
GC会自动触发,不同平台运行频率不一样
GC也可以被强制执行
String、StringBuffer、StringBuilder
String的值不可变,当它需要被修改(增加字符、修改字符)时,就需要创建新的内存来存储。
StringBuffer(线程安全)和StingBuilder(非线程安全、快)可以多次修改而不产生新的对象,
结构体和类
结构体是值类型,无法被继承,类是引用类型。
命名空间
将自己写的类用 namespace{}包裹,在别的脚本中,就可以using的方式导入命名空间,然后使用那个名命空间中的类名作为类型,声明引用与对象。
委托和事件
委托类似于c语言上的指针,是指向一个函数的指针,也可以理解为,委托是复制了这个函数的使用。
在类中定义一个方法函数,在外部定义一个委托类型。
new一个对象,声明一个委托变量。
将对象的方法,赋值给委托变量。就可以调用委托并设置形参,实现调用对象方法。
事件就是委托类型,在声明事件时要用event修饰委托类型,声明事件变量。事件的作用与委托变量一样,功能上有更多限制,只能通过+= -=来绑定方法,只能在内部调用事件。
TCP和UDP:
前者安全传输信息准确,用于游戏中聊天。后者便捷、不考虑丢包速度快、常用于实时游戏、直播视频、物联网(TCP三次握手、必须要有服务器、稳定效率低。UDP一次就可以、但是不稳定,如何可以稳定。)
TCP怎样防止数据流失(自己定义协议包)
TCP、UDP补充:
TCP:传输控制协议(Transmission Control Protocol) 面向连接,如打电话需要先拨号建立连接。提供可靠的服务,传输的数据稳定、不丢失 。
UDP:无连接的发送数据之前不需要连接,尽最大努力交付,不保证可靠的交付,可能丢包。网络不好,也不会使得源主机的发送速率降低,实时应用,视频会议 。
TCP的三次握手:1、客户端向服务器端发送请求建立连接 。2、服务器端确认应答,并且请求建立连接。3、客户端确认应答 。
TCP的四次挥手:1、客户端请求断开连接 。2、服务器端确认应答 。3、服务器端请求断开连接。4、客户端确认应答 。
Socket编程
TCP/IP协议族包括运输层(TCP、UDP)、网络层(IP)、链路层。socket是一个接口在用户进程与TCP/IP协议之间充当中间人完成TCP/IP协议的书写用户只需要理解接口即可。
同步异步:
同步:一个程序在执行某个请求时,若该请求需要一段时间返回数据,那么这个进程就会一直等下去,直到成功返回数据在进行下一步操作。
异步:不需要等待不管其他进程的状态继续执行下一步操作,当有数据返回时就会通知这个进程处理,提高执行效率。
在unity中例如场景加载,小场景资源就可以同步加载,大场景资源就可以使用异步加载 ,就会有进度条 。同步,管理起来方便准备资源及时返回,没有异步快。异步快,调用玛麻烦不确定什么时候准备完成 ,可以用回调,但是回调多。
MVC框架(Model View Controller)
是一种软件设计典范。不是三层而是三个部分,属于框架模型。大概可以理解为:用户与视图交互使得控制器将数据、指令传递给模型 ,模型与数据库交互 ,将结果传递给视图,反馈给用户 ,用户再进行下一步操作 。
Model:模型表示应用程序核心数据记录列表 。
View:显示视图,对数据进行显示 。用户进行交互的界面也就是网页
Controller:控制器,对数据库的各种操作进行控制 。
MVC在unity中的应用
线程安全
在多个线程访问的情况下会产生线程安全问题,我们要确保在多条线程访问的时候,我们的程序还能按照我们的预期的行为去执行。
当多个线程访问某个方法时,不管你通过怎样的调用方式、或者说这些线程如何交替地执行,我们在主程序中不需要去做任何的同步,这个类的结果行为都是我们设想的正确行为,那么我们就可以说这个类是线程安全的。
在uigi两个image之间插入粒子或者三维模型
两个canvas中间夹模型
UE4的shader和U3D的shader区别
EBO
迭代器
敏捷开发
场景设计流程思路
批处理、动态静态区别
面部表情编辑器
继承父类的子类的虚表怎么调用
基于物理渲染的基本原理(微表面、能量守恒)
图形学基础知识
水体、植被、地形、皮肤、毛发渲染
unity插件、nature pack、easy road、ugui
Project Setting
委托Func Action Predicate返回bool
调用委托BeginInvoke、EndInvoke
ngui在VR里不能用
动态规划、最短路径算法
堆排序的应用
GPU并行运算
STL
反转链表
游戏中的寻路算法,最短路径算法、迪特斯科拉算法、贪心算法
对象是怎么创建的