《Unity知识点》
##《Unity知识点》发布说明:
++++这是立钻哥哥对Unity知识点的一个梳理和拓展,打造最权威的参考。
++++这里我们碰到了一个问题,那就是从什么地方入手比较合适,作为这个问题,通常立钻哥哥就顺其自然了,所以,我们这边就没有特别的顺序和章节归类。
++++Unity知识点0001:https://blog.csdn.net/vrunsoftyanlz/article/details/80302012
++++Unity知识点0008:https://blog.csdn.net/VRunSoftYanlz/article/details/81153606
##Unity知识点目录:
#知识点0001:什么是协同程序?
#知识点0002:ArrayList和List的区别?
#知识点0003:MeshRender中material和sharedmaterial的区别?
#知识点0004:对象池(Object Pool)技术。
#知识点0005:链条关节(Hinge Joint)
#知识点0006:PlayerPrefs
#知识点0007:Unity3d脚本生命周期
#知识点0008:LOD技术
#知识点0009:Mipmap技术
#知识点0010:ref引用参数和out输出参数和params数组参数
#知识点0011:delegate委托
#知识点0012:event事件
#知识点0008:LOD技术 |
#知识点0008:LOD技术
++++LOD(Level of detail):多层次细节,是最常用的游戏优化技术。LOD按照模型的位置和重要程度决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。(缺点是增加了内存。)
++++立钻哥哥:LOD(多层次细节)是内存优化的方式之一。(使用LOD,好处就是对那些离得远,看不清的物体的细节可以忽略。)
++LOD是什么,优缺点是什么?
++++LOD是Level of detail简称,意为多层次细节,是最常用的游戏优化技术。
++++LOD技术指根据物体模型的节点在显示环境中所处的位置和重要性,决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。
++++LOD优点:可根据距离动态的选择渲染不同细节的模型。
++++LOD缺点:增加美工工作量,增大了游戏的容量(要准备不同细节的同一模型)。
++LOD百科
++++LOD技术即Level of Detail的简称,意为多细节层次。(LOD技术指根据物体模型的节点在显示环境中所处的位置和重要度,决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算。)
++LOD在游戏里面的运用
++++立钻哥哥:LOD(Level of Detail)。
++++LOD模型制作:三个面数不同的造型:高模、一般、低模。
--高模油桶:三角面Tris:712,顶点数Verts:358;
--低模油桶:三角面Tris:28,顶点数Verts:16;
++++立钻哥哥:在制作LOD之前,将不同面数的模型放在同一个位置,否则会发生模型位置错乱的情况。
=>1.【空GameObject】
=>2.【添加LOD属性】
=>3.【Component=>Rendering=>LODGroup】
=>4.【在LODGroup的设置LOD的层级(LOD:0:100%、LOD:1:60%、LOD:2:30%、Culled:10%)】
=>5.【Add添加LOD所对应的模型】
=>6.【测试LOD效果:LOD0高模、LOD1一般、LOD3低模、Culled消失】
++++LOD(多层次细节Level of Detail)是根据物体在游戏画面中所占视图的百分比来调用不同复杂度的模型的。(就是当一个物体距离摄像机比较远的时候使用低模,当物体距离摄像机比较近的时候使用高模。)(这是一种优化游戏渲染效率的使用方法,缺点是占用大量内存。)(使用这种技术,一般是在解决运行时流畅度的问题,采用的是空间换时间的方式。)
++++立钻哥哥:创建LOD模型的步骤:
--步骤1:准备3组模型:高精度模型,中精度模型,低精度模型;
--步骤2:定义一个空对象,添加LODGroup组件;
--步骤3:分别将3种不同精度的模型,拖拽到空对象的LODGroup组件的各个级别上。
--步骤4:在LOD组件添加模型的过程中:【Yes, Reparent】:把添加的模型作为LODGroup组件所属对象的子物体。
--步骤5:对齐三个子物体,测试LOD效果。
#知识点0009:Mipmap多级纹理技术
#知识点0009:Mipmap多级纹理技术 |
#知识点0009:Mipmap多级纹理技术
++++立钻哥哥:Mipmap多级纹理技术有点类似于LOD技术,但是不同的是,LOD针对的是模型资源,而Mipmap多级纹理针对的纹理贴图资源使用Mipmap多级纹理后,贴图会根据摄像机距离的远近,选择使用不同精度的贴图。(缺点:会占用内存,因为Mipmap多级纹理会根据摄像机远近不同而生成对应的8张贴图,所以必然占内存。)(优点:会优化显存带宽,用来减少渲染,因为可以根据实际情况,会选择适合的贴图来渲染,距离摄像机越远,显示的贴图像素越低,反之,像素越高。)
++++使用MipMap多级纹理后图片大小会变大,这是因为使用MipMap多级纹理技术后,会对这个贴图生成八张精度质量不同的贴图,所以内存占用变大了。(所以关于这个技术是否使用,根据项目而定,什么都是有利有弊的。)
++++MipMapping:在三维计算机图形的贴图渲染中常用的技术,为加快渲染进度和减少图像锯齿,贴图被处理成由一系列被预先计算和优化的图片组成的文件,这样的贴图被称为MipMap多级纹理。(MipMap多级纹理是目前应用最为广泛的纹理映射技术之一。)
++++OpenGL实现Mipmap多级纹理的功能:void glTexImage2D(GLenum target, GLint level, GLint components, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels); :定义一个二维纹理映射。(纹理映射时一个相当复杂的过程,OpenGL最基本的执行纹理映射所需的步骤是:
--1、定义纹理glTexImage2D();
--2、控制滤波glTexParameterf();
--3、说明映射方式glTexEnvf();
--4、绘制场景,给出顶点的纹理坐标和几何坐标glEnable(GL_TEXTURE_2D)和glTexCoord2f()。 纹理映射只能在 RGBA方式下执行,不能运用于颜色表方式。)
++++MipMap多级纹理是GPU优化方案:当屏幕变小时,自动选择合适尺寸的图片进行渲染。(但会多使用33%的内存。)
#知识点0010:ref参数和out参数
#知识点0010:ref参数和out参数 |
#知识点0010:ref引用参数和out输出参数和params数组参数
++++立钻哥哥:ref引用参数和out参数的效果一样,都是通过关键字找到定义在主函数里面的变量的内存地址,并通过方法体内的语法改变它的大小。(ref引用参数必须初始化,out参数必须在函数里赋值。)(ref引用参数是引用;out参数是输出参数。)
++++【ref引用参数】:值类型参数想要达到引用类型参数的效果,需要用到引用参数。
--ref引用参数以ref修饰符声明;(public void Swap(ref int x, ref int y){ })
--public void Swap(ref int x, ref int y){ int temp = x; x = y; y = temp; }
--int score_1 = 100; int score_2 = 80;
--myMath.Swap(score_1, score_2);
--ref修饰的变量在传递参数前一定要有初始值。
++++【out输出参数】:如果想要一个方法返回多个值,可以用输出参数来处理。
--输出参数由out关键字标识;(public void Cal(int a, int b, out int x, out int y){})
--public void Cal(int a, int b, out int x, out int y){ x = a - b; y = a + b; }
--int numOne = 22; int numTwo = 8; int resultOne; int resultTwo;
--myMath.Cal(numOne, numTwo, out resultOne, out resultTwo);
++++【params数组参数】:如果形参表中包含了数组型参数,那么它必须在参数表中位于最后,而且必须是一维数组类型。
--数组参数params不能跟ref、out一起搭配使用;
--数组参数长度可变(长度可以为0);
--数组参数只能使用一次,而且要放到最后。
--public void Sum(){params int[] arr}{ int result = 0; foreach(int x in arr){ reslut += x; }}
--myMath.Sum(1, 2, 3, 4, 5);
++++协程中IEnumerator类型的方法不能带ref引用或者out输出型的参数,但可以带被传递的引用。
++++Physics类中Raycast()实现射线检测:bool Raycast(Ray ray, out RaycastHit hitInfo);
++++string类中格式化字符串:public static string Format(string format, params object[] args);
++++string类中分割字符串:public string[] Split(params char[] separator);
++C#方法中参数ref和out解析
++++立钻哥哥:ref是有进有出,out是只出不进;(ref是传递参数的地址,out是返回值)
++++C#中有4种参数类型:值类型、引用参数、输出参数、数组参数;
++++【值类型】:不附加任何修饰符;使用值参数,通过复制实参的值到形参的方式把数据传递到方法;
++++【ref引用参数】:以ref修饰符声明;使用引用参数时,必须在方法的声明和调用中都使用ref修饰符;实参必须是变量,在用作实参前必须被赋值,如果是引用类型变量,可以赋值为一个引用或者null值;
++++【out输出参数】:以out修饰符声明,可返回一个或多个值给调用者;必须在声明和调用中都使用修饰符。输出参数的修饰符是out不是ref。和引用参数相似,实参必须是变量,而不能是其他类型的表达式(因为方法需要内存位置保存返回值)。
++++【params数组参数】:以params修饰符声明;在一个参数列表中只能有一个参数数组;如果有,它必须是列表中的最后一个;
++++C#中方法参数ref和out区别:
--1、使用ref型参数时,传入的参数必须先被初始化。对out而言,必须在方法中对其完成初始化;(ref传进去的参数必须在调用前初始化,out不必)(ref传进去的参数在函数内部可以直接使用,而out不可以)(ref传进去的参数在函数内部可以不被修改,但out必须在离开函数体前进行赋值)
--2、使用ref和out时,在方法的参数和执行方法时,都要加ref或out关键字,以满足匹配;
--3、out适合用在需要return多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候;
--4、系统对ref的限制时更少一些的。(out虽然不要求在调用前一定要初始化,但是其值在函数内部是不可见的,也就是不能使用通过out传进来的值,并且一定要在函数内赋一个值。或者说函数承担初始化这个变量的责任)
--5、关于重载:有out/ref关键字的方法可以与无out和ref关键字的方法构成重载;但是想在out和ref间重载,编译器将提示:不能定义仅在ref和out的方法上重载;
--6、方法调用前初始值:ref作为参数的函数在调用前,实参必须赋初始值,否则编译器将提示:使用了未赋值的局部变量;(out作为参数的函数在调用前,实参可以不赋初始值)
--7、在函数内,引入的参数初始值问题:在被调用函数内,out引入的参数在返回前至少赋值一次,否则编译器将提示:使用了未赋值的out参数;(在被调用函数内,ref引入的参数在返回前不必为其赋值)
++++【ref的使用】:使用ref进行参数的传递时,该参数在创建时,必须设置其初始值,且ref侧重于修改;
++++【out的使用】:采用out参数传递时,该参数在创建时,可以不设置初始值,但是在方法中必须初始化,out侧重于输出;(当希望方法返回多个值时,可以用out,并且一个方法中的参数可以有一个或多个out参数;使用out参数,必须将参数作为out参数显式传递到方法中)
++++补充1:ref的实参必须初始化;out的实参可初始化也可不初始化,反正进去后都会清除;
++++补充2:C#中的ref和out提供了值类型按引用进行传递的解决方案,当然引用类型也可以用ref和out修饰,但这样已经失去了意义。(引用数据类型本来就是传递的引用本身而非值的拷贝。)
++++补充3:ref和out关键字将告诉编译器:现在传递的是参数的地址而不是参数本身,这和引用类型默认的传递方式是一样的。(编译器不允许out和ref之间构成重载:充分说明out和ref的区别仅是编译器角度的,它们生成的IL代码是一样的)
++++补充4:值类型在托管堆中不会分配内存,为什么可以按地址进行传递呢?:值类型也有它自己的地址,即指针:用ref和out修饰后,传递的就是这个指针,所以可以实现修改后a,b的值真正的交换:这就是ref和out给我们带来的好处。
++++补充5(非常重要):使用ref参数,则方法定义和调用方法都必须显式使用ref关键字。(使用out参数,方法定义和调用方法都必须显式使用out关键字)
#知识点0011:delegate委托
#知识点0011:delegate委托 |
#知识点0011:delegate委托
++++参考推荐“框架知识点”:https://blog.csdn.net/vrunsoftyanlz/article/details/80862879
++++立钻哥哥:delegate委托类似于一种安全的指针引用,在使用它时是当做类来看待而不是一个方法,相当于对一组方法的列表的引用。(用处:使用委托让程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用该引用方法的代码,而不必在编译时知道将调用哪个方法。)(与C++中的函数指针不同,委托是面向对象的,而且是类型安全的)
++++delegate(委托)是表示将方法作为参数传递给其他方法。(委托类似于函数指针,但与函数指针不同的是,委托是面向对象的,类型安全的和保险的。)
++++委托在编译的时候会编译成类,在任何可以声明类的地方都可以声明委托。
++++委托是一个类,它定义了方法的类型,使得可以将方法当做另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用if_else(switch)等语句,同时使得程序具有更好地可扩展性。
++++委托绑定方法时需要注意(多播委托),注意:第一次用“=”,是赋值的语法;第二次,用的是“+=”,是绑定的语法。(如果第一次就使用“+=”,将出现“使用了未赋值的局部变量”的编译错误。)
++++拓展1:C#中的event事件:实际上是一种具有特殊签名的delegate委托。(委托是对函数的封装,可以当作给方法的特征指定一个名称;事件则是委托的一种特殊形式,当发生有意义的事情时,事件对象处理通知过程。)
++++拓展2:一个委托可以搭载多个方法,所有方法被一次唤起;委托可以使得委托对象所搭载的方法并不需要属于同一个类。(委托对象所搭载的所有方法必须具有相同的原型和形式,也就是拥有相同的参数列表和返回值类型。)
++C#中delegate委托
++++立钻哥哥:delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类;与其它的类不同,delegate类能够拥有一个签名(signature),并且它“只能持有与它的签名匹配的方法的引用”。(它所实现的功能与C++中的函数指针十分相似。)
++++delegate委托与C++函数指针的区别:
--函数指针只能指向静态函数;而delegate既可以引用静态函数,也可以引用非静态成员函数。(在引用非静态成员函数时,delegate不但保存了对此函数入口指针的引用,还保存了调用此函数的类实例的引用)
--delegate是面向对象、类型安全、可靠的受控(managed)对象。(runtime能够保住delegate指向一个有效的方法,无须担心delegate会指向无效地址或者越界地址)
++利用委托功能实现参考:
++++实现一个delegate是很简单的,分3个步骤实现:
--第一步:声明一个delegate对象,它应当与想要传递的方法具有相同的参数和返回值类型;
--第二步:创建delegate对象,将想要传递的函数作为参数传入;
--第三步:在要实现异步调用的地方,通过上一步创建的对象来调用方法。
//立钻哥哥:委托应用参考
//A、内含委托的类 class HelloWorld{ public delegate void GreetingDelegate(string name); //第一步
public static void EnglishGreeting(string name){ Console.WriteLine(“立钻哥哥:hello, ” + name); }
//第一步:想要传递的方法具有与delegate相同的参数和返回值类型 public static void ChineseGreeting(string name){ Console.WriteLine(“立钻哥哥:你好, ” + name); }
public void GreetingPeople(string name, GreetingDelegate method){ method(name); } } //立钻哥哥:class HelloWorld{}
//B、测试运行 class Program{ static void Main(string[] args){ HelloWorld hw = new HelloWorld(); hw.GreetingPeople(“立钻哥哥”, HelloWorld.ChineseGreeting);
Debug.Log(“立钻哥哥:委托应用演示完毕~~”); } } //立钻哥哥:class Program{}
//C、委托同string都是类型,可以利用委托声明类似name这样的委托变量。 class Program{ static void Main(string[] args){ HelloWorld hw = new HelloWorld(); HelloWorld.GreetingDelegate delegate1, delegate2; delegate1 = HelloWorld.EnglishGreeting; delegate2 = HelloWorld.ChineseGreeting; hw.GreetingPeople(“立钻哥哥”, delegate1); hw.GreetingPeople(“Yanlz”, delegate2);
Debug.Log(“立钻哥哥:委托声明为变量-演示完毕~~”); } } //立钻哥哥:class Program{}
//D、委托不同于string类型的一个特性:可以将多个方法赋给同一个委托,或者叫将多个方法绑定到同一个委托,但调用这个委托的时候,将依次调用其所绑定的方法。 HelloWorld.GreetingDelegate delegate1; delegate1 = HelloWorld.EnglishGreeting; delegate1 += HelloWorld.ChineseGreeting; hw.GreetingPeople(“立钻哥哥”, delegate1);
//E、可以绕过调用GreetingPeople(),通过委托来直接调用EnglishGreeting和ChineseGreeting HelloWorld.GreetingDelegate delegate1; delegate1 = HelloWorld.EnglishGreeting; delegate1(“立钻哥哥”);
//F、委托属于类,可以利用这一特性直接new出委托实例 //第二步:创建delegate对象(实例) HelloWorld.GreetingDelegate delegate1 = new HelloWorld.GreetingDelegate(HelloWorld.ChineseGreeting); delegate1 += HelloWorld.EnglishGreeting; delegate1(“立钻哥哥”); //第三步:调用delegate
//H、委托可以绑定一个方法,也可以取消方法的绑定:利用-=。 HelloWorld.GreetingDelegate delegate1 = new HelloWorld.GreetingDelegate(HelloWorld.ChineseGreeting); delegate1 += HelloWorld.EnglishGreeting; delegate1(“立钻哥哥”); delegate1 -= HelloWorld.ChineseGreeting; delegate1(“立钻哥哥”);
|
++委托实现一个按钮的点击事件
//立钻哥哥:利用委托实现一个按钮的点击事件 public delegate void ClickDelegate();
class Button{ public static void ClickFinished(){ Console.WriteLine(“立钻哥哥:按钮被点击了~~”); } } //立钻哥哥:class Button{}
ClickDelegate dele1; dele1 = Button.ClickFinished; dele1();
//利用匿名函数实现 ClickDelegate myClick = delegate(){ Console.WriteLine(“立钻哥哥:按钮被点击了~~匿名函数222~~”); }; myClick();
//立钻哥哥:匿名方法的出现在初始化时内敛声明的方法,使得委托的语法更加简洁
|
++C#中内置了三种委托方式
++++1、Func委托;(有参有返回值)
--delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
++++2、Action委托;(有参无返回值)
--delegate void Action<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
++++3、Predicate委托;
++++说明1:Func委托和Action委托唯一的区别就是在于代理的方法(函数)有没有返回值。(有返回值选择Func委托;没有返回值选择Action委托)
++项目应用中委托定义参考
//立钻哥哥:全局委托定义参考 public delegate void StateChangeEvent(Object sender, EnumObjectState newState, EnumobjectState oldState); public delegate void MessageEvent(Message message); public delegate void OnTouchEventHandle(GameObject _sender, object _args, params object[] _params); public delegate void PropertyChangedHandle(BaseActor actor, int id, object oldValue, object newValue);
|
#知识点0012:event事件
#知识点0012:event事件 |
++立钻哥哥推荐的拓展学习链接(Link_Url):
++++立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/
++++Unity知识点0001:https://blog.csdn.net/vrunsoftyanlz/article/details/80302012
++++Unity知识点0008:https://blog.csdn.net/VRunSoftYanlz/article/details/81153606
++++Unity引擎基础:https://blog.csdn.net/vrunsoftyanlz/article/details/78881685
++++Unity面向组件开发:https://blog.csdn.net/vrunsoftyanlz/article/details/78881752
++++Unity物理系统:https://blog.csdn.net/vrunsoftyanlz/article/details/78881879
++++Unity2D平台开发:https://blog.csdn.net/vrunsoftyanlz/article/details/78882034
++++UGUI基础:https://blog.csdn.net/vrunsoftyanlz/article/details/78884693
++++UGUI进阶:https://blog.csdn.net/vrunsoftyanlz/article/details/78884882
++++UGUI综合:https://blog.csdn.net/vrunsoftyanlz/article/details/78885013
++++Unity动画系统基础:https://blog.csdn.net/vrunsoftyanlz/article/details/78886068
++++Unity动画系统进阶:https://blog.csdn.net/vrunsoftyanlz/article/details/78886198
++++Navigation导航系统:https://blog.csdn.net/vrunsoftyanlz/article/details/78886281
++++Unity特效渲染:https://blog.csdn.net/vrunsoftyanlz/article/details/78886403
++++Unity数据存储:https://blog.csdn.net/vrunsoftyanlz/article/details/79251273
++++Unity中Sqlite数据库:https://blog.csdn.net/vrunsoftyanlz/article/details/79254162
++++WWW类和协程:https://blog.csdn.net/vrunsoftyanlz/article/details/79254559
++++Unity网络:https://blog.csdn.net/vrunsoftyanlz/article/details/79254902
++++C#事件:https://blog.csdn.net/vrunsoftyanlz/article/details/78631267
++++C#委托:https://blog.csdn.net/vrunsoftyanlz/article/details/78631183
++++C#集合:https://blog.csdn.net/vrunsoftyanlz/article/details/78631175
++++C#泛型:https://blog.csdn.net/vrunsoftyanlz/article/details/78631141
++++C#接口:https://blog.csdn.net/vrunsoftyanlz/article/details/78631122
++++C#静态类:https://blog.csdn.net/vrunsoftyanlz/article/details/78630979
++++C#中System.String类:https://blog.csdn.net/vrunsoftyanlz/article/details/78630945
++++C#数据类型:https://blog.csdn.net/vrunsoftyanlz/article/details/78630913
++++Unity3D默认的快捷键:https://blog.csdn.net/vrunsoftyanlz/article/details/78630838
++++游戏相关缩写:https://blog.csdn.net/vrunsoftyanlz/article/details/78630687
++++设计模式简单整理:https://blog.csdn.net/vrunsoftyanlz/article/details/79839641
++++U3D小项目参考:https://blog.csdn.net/vrunsoftyanlz/article/details/80141811
++++UML类图:https://blog.csdn.net/vrunsoftyanlz/article/details/80289461
++++U3D_Shader编程(第一篇:快速入门篇):https://blog.csdn.net/vrunsoftyanlz/article/details/80372071
++++U3D_Shader编程(第二篇:基础夯实篇):https://blog.csdn.net/vrunsoftyanlz/article/details/80372628
++++框架知识点:https://blog.csdn.net/VRunSoftYanlz/article/details/80862879
++++游戏框架(UI框架夯实篇):https://blog.csdn.net/vrunsoftyanlz/article/details/80781140
++++游戏框架(初探篇):https://blog.csdn.net/VRunSoftYanlz/article/details/80630325
++++Lua快速入门篇(基础概述):https://blog.csdn.net/VRunSoftYanlz/article/details/81041359
++++Lua快速入门篇(XLua教程):https://blog.csdn.net/VRunSoftYanlz/article/details/81141502
++++立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/
--_--VRunSoft:lovezuanzuan--_--