Unity笔记

unity

1.初始

1.1sence场景面板等

1.2materials
材质的本质是shader的实例,shader着色器可以使纹理以某种方式展现,一段嵌入渲染管线中的程序。

rendering mode 渲染模式:
Opaque 不透明模式,整个图片。
cutout 去掉透明通道(镂空),去掉图片的底色,eg.栅栏。
Transparent 完全透明,eg.玻璃.
注意与这里相关的还有颜色中的透明度的值,255是完全不透明。
Fade 淡入,淡出 eg.ppt

albedo 主要的贴图
metallic 设置金属光泽
specular 镜面反射
smoothness 设置表面光滑程度
normal Map 法线贴图 凹凸程度
emission 自发光 颜色+贴图
(none realtime backed)
tiling 平铺 沿着不同的轴 纹理平铺的个数
offset 滑动纹理

1.3 camera
添加camera组件的gameobject

1.3.1 组件:
transform 位置
camera 显示世界
flare layer 耀斑层 显示光源耀斑
GUI Layer 显示二维的GUI元素
audio listener 接受输入的音频源

1.3.2 camera组件属性
1.3.2.1 CLear Flags 决定空白区域的颜色(没有物体的部分):
skybox 天空盒
围绕整个场景的包装器,用于模拟天空的材质。
使用天空盒方法:
方式一:摄像机添加组件skybox
方式二:光照窗口 windows-lighting-environment lighting-里设置为skybox,将天空色反射到场景中的物体。

模式:
6-side 六张图片贴图
procedual 仿真环境
#sun 太阳模式 :none,simple,high quality
#atmosphere thickness 大气层厚度
#sky tint 天空的颜色
#ground地面的颜色

solid color 纯色 显示背景颜色
depth only 仅深度 画中画效果 小画面摄像机选择该项可清除屏幕只保留物体颜色信息。
don’t clear 不清楚 不清楚任何颜色或深色缓存

1.3.2.2 background 背景 没有天空盒的情况下,剩余屏幕的颜色

1.3.2.3 culling mask: 选择遮蔽层 选择要照射的层
每一个gameobject都有Tag 和 Layer,在这里用到layer(接受自定义),场景中这个层的物体依然存在,但是可以在camera中隐藏,并不渲染.

1.3.2.4 projection :这个是用于设置摄像头的模式
perspective 透视的 3D (field of view 可以拉进拉远镜头)
orthographic 正交的 2D (size 视野大小)

1.3.2.5 clipping plane 分割场景
确定物体的渲染范围,摄像机的建材面。

1.3.2.6 viewpoint rect 设置场景的长宽高度 以及对应的位置。例如:小地图

1.3.2.7 depth 设置摄像机的在屏幕上的显示顺序 小的摄像机应当在主摄像机之后显示,depth更高。

1.4 instantOC 第三方插件

1.4.1渲染管线

游戏 判断哪些物体需要显示
|
图形API

Drawcall (Batches)每次引擎准备数据并通知GPU的过程,每一帧调用显卡渲染物体的次数。不考虑光照一个物体一次,有光复杂。

|
CPU与GPU分界线
|

顶点处理
任何一个模型都是由无数个三角形组成的,在这一部中接受模型顶点数据并且进行坐标系的转换,从三维的坐标位置转换到屏幕上的二维坐标位置。

|
图元装配
组砖面:连接相邻的顶点,连成三角面

|
光栅化
确定三角面上的像素的位置,(扫描线之类的算法),并提供合理的插值参数。
|
像素处理
对每一像素区域进行着色,然后写进缓存中。

|
缓存:一个保存有像素数据的内存块。
缓存分为帧缓存以及深度缓存(Z-Buffer).
帧缓存存储每一个像素的颜色并且将之存储起来,最后按帧显示。
深度缓存按照深度存储对应的像素的颜色,并且在使用时判断深度,深度小的显示。

1.4.2 Occlusin culling 遮挡剔除
将摄像机看不到的对象去掉,减少渲染的量。
步骤:
(1)创建层
(2)为游戏物体指定层(将参与遮挡剔除)与标签(自动附加IOClod脚本)
(3)物体添加碰撞器Colider组件
(4)摄像机附加脚本IOCcam
原理:
获取摄像机视锥的范围内的所有物体。从摄像机位置随机发射射线打到物体上,没打到的物体就不渲染了(取消mesh render)。

IOC camera script属性:
layer mask 参与遮挡剔除的游戏对象层
IOC Tag:将为指定的游戏对象自动添加IOClod脚本对象。
Samples:每一帧摄像机发射的射线数目
Rays FOV:射线视野
View DIstance:视图距离 射线长度
Hide Delay:当物体被剔除的时候延迟的帧数,50-100之类。

1.4.3 LOD
levels of Details 多细节层次
根据物体模型的节点在场景中的位置,决定渲染物体的资源分配,降低非重要的物体的面数。

1.5 光照系统
GI global illumination
全局光照
能够计算直接光 间接光 环境光 以及反射光的光照系统。

1.5.1 直接光照
从光源直接发出的光,通过light组件实现
directional light 平行光 太阳光
point light 模拟灯泡
spot light 聚光灯 向圆锥体区域内发射光,只有这个区域内才有光 探照灯
area light 区域光 由一个面向一个方向发射光线,仅烘焙时有效。

属性
range 范围 光从中心物体发射的范围,仅适用于点光源以及聚光灯
spot angle 聚光角度 聚光灯的角度
color intensity强度 culling mask 选择遮蔽层

shadow type 阴影类型 hard,soft,
strength:阴影的黑暗程度
resolution 分辨率 bias 偏移 物体与影子的偏移
可以通过mesh renderer禁止阴影。

1.5.2 环境光照
作用于场景内全部的物体的光照
environment-lighting ambient

ambient source 环境光源
#skybox通过天空盒的颜色设置光照
#gradient 梯度颜色
sky 天空颜色 equator 地平线颜色 Ground 地面颜色
#ambient color纯色
ambient intensity 环境光强
ambient GI 环境光的GI模式
realtime backed

1.5.3 反射光照
根据天空盒或者是立方体贴图的计算作用于全部物体的反射效果
reflection source 反射源
#skybox resolution 分辨率 compression 是否压缩
#custom 自定义
reflection intensity 反射强度
reflection bounces 使用 reflection probe允许设置来回反弹的次数

1.5.4 间接光
物体表面接受光照后反射出来的光
受到bounce intensity反弹强度控制
只有标记为lightmaping static的物体才能产生间接反弹光照。

1.5.5 realtime GI
在运行期间任意修改光源,所有的变化可以立即更新。
(1)游戏对象设置为lightmaping static
(2)启用lighting面板 precomputed realtime GI
(3) build

1.5.6 烘焙 lightmap
将光线效果预渲染成贴图在作用到物体上模拟光阴,从而提高性能。
(1)游戏对象设置为lightmaping static
(2)设置light组件的baking属性
realtime 仅实时光照有用
baked仅烘焙时起作用
mixed混合
(3)启用lighting面板 Backed GI
(4) build

1.5.7 light probes 光源侦测
lightmapping只能作用于static物体,运动物体无法与光线融合在一起,light probes可以收集光影信息,插值后作用到物体上。

相当于在周围添加多个小球,计算在这些小球位置的光照信息,然后插值到物体上。

(1)添加游戏对象light probe group
(2)添加侦测小球 add probe
(3)点击build
(4)勾选侦测物体的meshrenderer组件的use light probes属性

2.C#
.net 是微软开发的跨平台开发framework.
unity的跨平台采取的是mono,底层是.net的framework
2.1 type
2.1.1 Console 控制台 本质上是一个类
方法
string a=Console.ReadLine();
Console.WriteLine();
属性
Console.Title();
2.1.2 Type
整型
1字节 sbyte 有符号 byte 无符号
2字节 short 有符号 ushort 无符号
4字节 int uint
8字节 long ulong

非整型
4字节 float 7位
8字节 double 15-16位
16字节 decimal 28-29

(1)非整型变量赋值要加后缀,不加默认为double.
(2)浮点型的运算会出现误差
bool number=1.0f-0.9f!=0.1f

2.1.3 标准数字字符串格式化
“{0(占位符):c}”,10 货币 10.00
“{0:d2}”,5 05补足两位
“{0:f1}”,1.26 1.3根据指示精度显示
“{0:p0}”,0.1 以百分数显示

2.1.4 流程
(1)源代码 .cs文件
(2)CLS 编译 目的:跨语言
CLS 公共语言规范
定义了.net平台上的语言必须支持的规范操作,实现语言的相互操作。
(3)通用中间语言(exe dll)
(4)CLR 编译 目的:优化 跨平台
CLR公共语言运行库
负责构建程序的运行环境,负责垃圾分配,垃圾收集,安全检查等。
(5)机器码

2.1.5 数据类型转换
(1)Parse转换 string转换为其他数据类型
string strnumber=“18.0”;
float num02=float.Parse(strnumber);
(2)ToString 转换 任意类型转换为string类型
int number=18;
string str=number.ToString();
(3)隐式转换
(4)显式转换
int i4=100;
byte b4 = (byte)i4;

2.2 方法
两个方法名称相同,但是参数列表不同。
用于在不同条件下解决同一类型的问题。
仅仅out与ref区别不可以构成重载。

2.3 数组
是从array类派生的数据结构,类似java,所有的类的继承顶端是object。
int[] a=new int[5];
数据类型[,] 数组名 = new 数据类型[行数,列数]
string[,] a=new string[3,2];

C#与java中类似,Array.Sort(arr);
Array.Copy(arr,arr2,2);

需要注意的是 Array.Clone()返回的是object类的实例。
Object obj=array.Clone();
int[] a=(int[])array.Clone();

foreach
foreach循环遍历数组中的元素
foreach(string item in array)
{
Console.WriteLine(item);
}

2.4 数据类型与内存
CTS 通用类型系统是.net框架中为所有语言定义数据类型的规则
值类型:存储数据的本身
#结构:基本数据类型
#枚举:
引用类型:存储数据的引用
#类 string Array 委托
#接口

分配
程序运行时,CLR将申请的内存空间从逻辑上进行划分。
栈区:
#空间小,读取速度快
#用于存储正在执行的方法,分配的空间叫做帧栈。帧栈中存储方法的参数以及变量等数据。等方法执行完之后,帧栈被清除。
堆区:
#空间大,读取数据慢
#用于存储应用类型的数据

局部变量
定义在方法内部的变量
特点:
#没有默认值,必须自行定义初始值,否则不能使用。
#方法被调用的时候,存在栈中,方法调用结束时从栈中清除。

重要实例:
值类型 是int bool char
因为在创建局部变量的时候,这些直接在帧栈中开辟空间,在对应的空间中存放的是对应的值。
int a=1;
a在栈中,1在栈中。

引用类型 string Array
这些创建类型在创建的时候,不仅在帧栈中开辟空间,又在堆中区开辟空间。数据存放在堆区中,栈区存放的是值对应的地址,获取值的时候,顺着地址找到对应的需要存放的值。
int[] arr=new int[]{1}
arr在栈中存储数组对象的应用 1在堆中。
int[] arr2=arr;
arr2在栈中开辟对应的空间,指向堆中与arr相同位置的一组数据。
//arr[0]=2;修改是堆中对应数据的值
//arr=new int[]{2};
这里修改了堆中的应用,重新在堆创建了一段空间用来存放对应的数据,arr指向这一段新创建的数据。

string与此同。
string s1=“男”;
string s2=s1;
帧栈中s1,s2指向的堆中的地址相同,都是指向的是“男”。
s1=“女”;
s2依然指向"男",s1指向一段新的开辟的空间,这段空间中存放的是新写入的“女”。
如果没有s2指向,这段写着“男”的内存就一直在对应的位置,直到被GC。

string[] arr02=new string[1];
arr02[0]=“assa”;
在栈中有一个arr02,放置的是对应的堆的地址,堆的地址中存放的是一个引用,指向字符串的值的存储位置。

static void main()
{
int a=1;
//int a;会报错
注意这里a是一个局部变量,如果没有赋值,是没有对应的值的。
int[] arr=new int[]{1};
Fun1(a,arr);
Console.WriteLine(a);
Console.WriteLine(arr[0]);
}
private static void Fun1(int a,int[] arr)
{
a=2;
#write的时候,会输出1.在为fun1分配空间的时候,会创建一片空间,这篇空间中存的是1,后来被改成2,main中输出的是在main栈中存放的对应的值。
arr[0]=2;
#write输出2,这里是两个栈中同为arr的应用指向堆中的同一个位置,这个位置被修改为2.
arr=new int[]{2};
#write输出1,这里fun1的arr指向想开的一段,为2.main指向原来的一段。

要修改对应的值要array.CopyTo();array.Copy();
}
int num1=1;
int num2=1;
bool r1= num1==num2;
true 比较的是对应的值。

int[] arr01=new int[]{1};
int[] arr02=new int[]{1};
bool r2= arr01==arr02; false
这里直接比较的是对应的索引。

以上是值传递,这里传递的是索引。
引用参数 传递索引
引用参数需求是修改对应的值。
void main()
{
int a2=1;
//int a2;如果这样,会报错
注意这里a是一个局部变量,如果没有赋值,是没有对应的值的。
fun2(ref a2);

int a3;
fun3(out,a3);
}
void fun2(ref int a)
{}

输出参数 传递索引
输出参数是对返回值的补充,可以返回多个值,赋值没有意义。
void fun3(out int a)
{
a=3;
}
区别:
(1)输出参数必须在调用之后,对其中的值进行修改。
(2) 输出参数传递之前可以不赋值。

2.5 垃圾回收器
GC是CLR中一种这对托管堆的自动回收释放内存的服务。
GC线程从栈中的应用开始追踪,从而判断哪些内存是正在使用的,若GC无法追踪,则回收。
int[] arr=new int[100];
arr=null;
可以将对应的内存标记位可以回收的部分。
int[] arr=new int[100];
arr=new int[100];
//会有大量垃圾产生。

2.6 拆装箱
static void main()
{
int a=1;
object 0=a;
//a中在栈中开辟空间,存放值1.在创建o之后,会在堆中创建空间,并存发对应的数值。
这个空间包括三块,第一块是存放值的空间,第二块是同步块索引,第三块是类型对象指针。
}
装箱
值类型隐式的转换为object类型或有此值类型实现的任何接扣类型的过程。
内部机制:
(1)在堆中开辟内存空间
(2)将值类型的数据复制到堆中
(3)返回堆中新分配对象的地址

object o=a;
int b=(int)o;
在栈上开辟对应的空间,放入对应的值。
拆箱操作
从object类型到值类型或从接扣类型实现该接口的值类型的显示转换。
内部机制:
(1)判断给定的类型是否是装箱时的类型。
(2)返回已装箱实例中属于原值类型字段的地址。

形参object类型,实参传递值类型,则装箱可以通过重载,泛型避免。
泛型:private static void fun1(object obj)

int num=100;
string str=num.ToString();
没有拆装箱
string str02=""+num;
有装箱,内部是string.Concat(object [] ).

2.7 字符串池
(1)创建的字符串常量会存放在字符串池子里,如果有重复的,会指向同一个对象,返回该对象的引用,如果不粗才能在,则另外开辟空间存储。
string s1=“bajie”;
string s2=“bajie”;
bool r1=object.ReferenceEquals(s1,s2);
True

string s3=new string(new char[]{‘ba’,‘jie’});
string s4=new string(new char[]{‘ba’,‘jie’});
bool r2=object.ReferenceEquals(s3,s4);
False
(2)字符串的不可变性。
字符串常量一旦进入内存,就不得再次改变。因为如果在原位置改变会使其他对象内存被破坏,导致内存泄露。当遇到字符串变量引用新值时,会在内存中创建一个新的字符串,将该字符串地址交给新变量使用。
string s1=“bajie”;
s1=“wukong”
重新开辟空间,储存新字符串,再替换新的。

//每次修改都是重新开辟新的空间存储数据,替换应用。同上。
object o1=1;
o1=2.0;
o1=“OK”;
for(int i=0;i<10;i++)
{
strNumber=strNumber+i.Tostring();
每次品鉴产生对应的字符串,产生垃圾。
}
//更好的解决方案 可变字符串
StringBuilder builder=new StringBuilder(10);
一次开辟可以容纳10个字符大小的空间,可以避免产生垃圾。
for(int i=0;i<10;i++)
{
builder.Append(i);
}
builder.Append(“1231231231”);
超过空间的最大上限,这里与vector类似,会开辟另外一块足够大的空间,把数据复制过去,并设置好对应的引用。但是,原来的位置会出现对应的垃圾。
string result=builder.ToString();

2.8 枚举
列出数据的所有值,本质是int类型的索引。
enum MoveDirection
{
Up=0,
Down=1,
Left=2,Right=4
}
使用时,MoveDirection.Up
选择多个枚举值
运算符|按位或
条件:
1.任意多个枚举值做|运算的时候的结果不能与其他的枚举值相同,2的n次方。
2.定义枚举时,是否包含对应的枚举值。

数据类型转换
int==>Enum
MoveDirection s01=(MoveDirection)2;
Enum==>int
int enumNumber=(int)(MoveDirection.Up|MoveDirection.Down);

string==>Enum
MoveDirection s02=(MoveDirection)Enum.Parse(typeof(MoveDirection),“Up”);
string strEnum=MoveDirection.Up.ToString();

2.9 类和对象
2.9.1.内存模型
Wife w=new Wife();
在栈里面有一个对应的应用,实例化的对象在堆面,里面包含数据对象,以及类型对象指针以及同步块索引。
this代表的是当前的实例化对象。

成员变量
(1)具有默认值
(2)所在类被实例化之后,存在堆中,对象被回收时,成员变量从堆中清除。
(3)可以与局部变量同名。

2.9.2 数据成员 重要的关键点是字段和属性。
字段是一个用于存储数据的变量。
属性是用来保护对象的,本质就是两个方法。
属性的本质是对字段的读取与写入方法。
Class A
{
//字段
Private string name;
//属性
public string Name//没有分号‘;’
{
get{
return name;
//不能写成return Name,这是一个死循环的递归,相当于再次调用Name.get()。
} //读取时保护,只有这个是只读。
set{
this.name=value;
} //写入时保护,只有这个是只写。
//value表示要设置的数据
}

}
static void main()
{
A a=new A();
a.Name=“aaa”;
}
在C#里面,字段首字母小写,属性首字母大写。
Class A
{
private int age;
public int Age
{
get{return this.age;}
set{
if(value<=19 && value>=18)
this.age=value;
else
throw new Exception(“我不要”);
}
}
}
属性可以提供只读只写的方法。
static void Main()
{
A b=new A();
b.Age=111;
}

2.9.3构造函数
构造函数:提供了创建对象的方法,常常用于初始化类的数据成员,一个类若没有构造函数,那么编译器会自动提供一个无参数构造函数。一个类若具有构造函数,不会提供。

特点:没有返回值 与类同名
如果不希望在类的外部创建对象,就将构造函数私有化。(单例模式)
public A(string name,int age)
{
this.name=name;
//构造函数如果为字段赋值,属性中的代码块不会执行。
this.Age=age;
}

Class A
{
public A()
{
Console.WriteLine(“create one”);
}
public A(string name):this()
{
//WIfe(); 调用无参构造函数,但是不能在这里调用,这么写。
this.name=name;
}
public A(string name,int age):this(name)
{
this.age=age;
}
}

this 关键字
表示当前对象的引用

2.9.4 字典
Dictionary<string,A> dic=new Dictionary<string,A>();
dic.Add(“lh”,new A(“lh”,“123”));
A a=dic[“lh”];

2.9.5 继承
class Person()
{
public string name;
}

class Student:Person
{
pubilc int score;
}
class Teacher:Person
{
public string name;
public int salary;
}
子类可以使用父类和自己的,父类只能使用父类的。
static void main()
{
//父类型的应用 转向子类的对象
Person person02 = new student();
这里只能使用父类的成员。

//显示转换
Student stu02=(Student)person02;

//这里不能将student转化为teacher,没有对应的属性。
//Teacher teacher02=(Teacher) person02;
//如果转换失败 不会抛出异常
//Teacher teacher02= person02 as Teacher;
}
2.9.6 静态
静态成员变量
(1)使用static关键字修饰的成员变量。
(2)静态成员变量属于类,类被加载时初始化,且全程只有一份。
(3)实例成员属于对象,每个对象被创建的时候初始化,每个对象一份。
(4)常驻内存。

静态构造函数
(1)初始化类的静态数据成员
(2)仅在类被加载的时候执行一次。
(3)不允许使用访问修饰符。

实例构造函数作用:提供创建对象的方式,初始化类的实例数据成员。
student(){}
静态构造函数作用,初始化静态数据成员。
static studnet{}

静态方法
通过类名调用静态方法的时候,因为没有具体的对象,所以在static方法中不能访问实例成员。

实例代码块,可以访问实例成员,也可以访问静态成员。静态代码块,只能访问静态成员。

静态类
使用static关键字修饰的类
不能实例化,只包含静态的成员
静态类不能被继承,但是静态方法,属性可以被继承。

适用性
利:单独空间存储,所有对象共享,可以被类名直接调用。
弊:静态商法中只能访问静态成员,共享数据被多个对象访问会出现并发。

适用场合:
(1)所有对象需要共享的数据
(2)在没有对象前就要访问成员
(3)工具类适合做静态类

2.9.7 结构体 struct
struct 用于封装小型的相关变量的值类型。但是,结构属于值类型,类属于引用类型。
并且,结构体不能包含无参数的构造函数,因为结构属于值类型,必须要初始化之后才能使用。在构造函数中,先为所有的字段赋值。

3.unity 脚本
脚本 附加在游戏物体上用于定义游戏对象行为的指令代码。
(1)文件名与类名必须一致。
(2)写好的脚本必须附加到物体上才能执行
(3)附加到物体上的类必须从MonoBehaviour继承。

编译运行过程
源代码–(CLS)->中间语言(.dll)–Mono Runtime(CLR)–机器码

3.1 脚本生命周期
必然事件== 消息 ==生命周期
消息:当满足某种条件unity引擎自动调用的函数。
[SerializeField]
//序列化字段 作用:在编辑器中显示私有变量。
[HideInInspector]
//作用:在编辑器中隐藏字段 public变量直接在编辑器中能够看见。
[Range(0,100)]
//滑动条
在脚本里面一般不包含属性,因为在编译器中根本看不见。
不要在脚本中写构造函数,不能在子线程(每一个物体)访问主线程(完整)。

3.1.1 初始阶段
作用:初始化 在函数外声明,初始化在下面两个函数中进行。

执行时机:创建游戏对象 立即执行 早于start 可以判断莫衷条件执行此脚本 this.enalbe=true.
Awake()

每当脚本对象启动时启用
OnEnable()

执行时机:创建游戏对象 脚本启动 才执行
Start()

3.1.2 物理阶段
FixedUpdate 固定更新
脚本启动时,固定时间被调动,适用于对游戏对象进行物理操作,不会受到渲染影响。

OnCollisionXXX 碰撞:
满足碰撞条件时调用

OnTriggerXXX 除法:
满足除法条件时调用

3.1.3 游戏逻辑阶段
执行时机:渲染帧执行,执行间隔不固定。
适用性:处理游戏逻辑,也可以放进物体的运动。
Update()

LateUpdate 延迟更新:
在Update函数被调用后执行,是用于跟随逻辑。比如,摄像头跟随物体运动,物体运动在update里面,摄像头跟随。

3.1.4 输入事件
OnMouseEnter
当进入当前Colider时调用
OnMouseOver
当鼠标经过当前Colider时调用
OnMouseExit OnMouuseDown OmMouseUp

3.1.5 场景渲染
OnBecameVisible 当看见:
当 Mesh Renderer 在任何摄像机上可见时调用

OnBecameInvisible 当不可见
当Mesh Rnderer 在任何摄像机上都不可见时调用

3.1.6 结束阶段
OnDisable 当对象编程不可用的时候,此函数被调用。

OnDestory
当脚本销毁或者附属的游戏对象被销毁时调用

OnApplicationQuit
应用程序退出时被调用

3.1.7 全程
Awake=>OnEnalbe=Start=>FixedUpdate=>yield WaitForFixedUpdate => OnTriggerXXX => OnCollisionXXX => OnMouseXXX => Update =>yield null
=> yield WaitForSeconds =>yield WWW
=> yield StartCoroutine =>LateUpdate
后面还有 rendering以及GUI rendering。

3.2 API
Component Transform GameObject Object Time

3.3 Time 类
这个类里面只有静态变量,就是简单的数据。
Time.time 以秒记录的时间
deltaTime 完成最后一帧消耗的时间
例子:旋转速度*每一帧消耗的时间,可以保证旋转速度不受到机器性能和渲染量影响。
timeScale减慢游戏速度,甚至停止,一开始是1,停止是0.
UNscaleDeltaTime个别物体不受暂停影响,不受缩放影响。

Invoke()适合每隔固定时间的启动。
CancelInvoke(“Timer”)取消调用

3.4 Perfab 预制件
一种资源类型,可以多次在场景中进行实例
对预制件的修改,可以同步到所有势力,从而提高开发效率。

3.5 AnimationView
通过动画视图可以直接创建和修改动画片段。
(1)为物体添加Animation组件
(2)在动画视图中创建片段

时间线
可以单击时间线上的任意位置预览或者修改动画片段,数字显示为秒数和帧数。

3.6 Input类
封装了输入功能的类,可以读取输入管理器中设置的按键。
建议在Update中检测用户的输入。
bool result=Input.GetMouseButton(0);

3.7 InputManager
即输入管理器
使用脚本通过虚拟轴名称获取自定义键的输入,玩家可以在游戏启动时根据个人喜好对虚拟轴进行修改。

4.3D 数学
4.1Vector3
一个数字列表,表示各个维度上的有向位移。
4.2 角的度量方式
4.3 三角函数
4.4 欧拉角和四元数
欧拉角 使用三个角度表示旋转位置。
对于一个方位,存在多个欧拉角度描述,因此无法判断多个欧拉角位移是否相同。x,z轴的旋转会按照自身坐标系进行,y轴的旋转回绕世界坐标系进行。

万向节死锁
物体沿x轴旋转±90度,自身坐标系的z轴将于世界坐标系的y轴重合,此时再沿y或z轴进行旋转的时候,会失去一个自由度。
在万向节死锁的情况下,规定研z轴完成竖直轴的全部旋转,即此时y轴旋转为0.

四元数
Quaternion在3D图形学中表述旋转,由一个三维向量和一个标量W组成。
旋转轴为V(任意vector3),旋转弧度为sita,使用四元数表示,则四个分量为:
x=sin(sita/2)*V.x
y=sin(sita/2)*V.y
z=sin(sita/2)*V.z
w=cos(sita/2)

两个四元数相乘可以组合旋转效果。
优点:避免万向节死锁。
缺点:存在不合法的四元数
4.5 坐标系统
world Space
世界坐标系:整个场景的固定坐标
作用:在游戏场景中表示每个游戏对象的位置和方向。

local Space
物体坐标系:每个物体独立的坐标系,原点为模型轴心点,随吾提移动或旋转而改变。
作用:表示物体相对位置与方向。

Screen Space
屏幕坐标系:以像素为单位,屏幕左下角为原点,右上角为屏幕宽w、高度h,z为到相机的距离。
作用:表示物体在屏幕中的位置。

Viewport SPace
视口坐标系 屏幕左下角为原点,右上角为(1,1),可以视为比例,z为到相机的距离。
作用:表示物体在摄像机中的位置。

local space ->world space
transform.TransformPoint
transform.TransformDirection
transform.TransformVector

world space ->local space
transform.InverseTransformPoint
transform.InverseTransformDirection
transform.InverseTransformVector

4.6 物理引擎
1.碰撞器
两者具有碰撞组件
运动的物体具有刚体组件

OnCollisionEnter 进入碰撞时执行
OnCollisionStay 与刚体接触式每一帧执行
OnCollisionExit 当停止碰撞时执行

2.触发器
带有碰撞器组件,且Is Trigger属性被勾选的物体
现象:无物理效果

触发条件
两者具有碰撞组件
其中之一带有刚体左键
其中之一勾选isTrigger

OnTriggerEnter 进入碰撞时执行
OnTriggerStay 与刚体接触式每一帧执行
OnTriggerExit 当停止碰撞时执行

放牛的星星
https://zhuanlan.zhihu.com/p/151238164
1.基础(旧版)

委托

一个简单的if-else块适用于两个函数,但是如果要支持更多的函数时,它会变得难以处理。但如果可以使用一个变量来存储想要调用的方法的引用,那岂不是就非常方便了。通过委托类型可以很容易达成。

public delegate float GraphFunction(float x,float y)

void Update()
{
	GraphFunction f;
	//这里需要对对应的委托赋予对应的函数的引用。
	if(function==0)
		f=sineFuction;
	else
		f=MultisineFuction;
	position.y=f(position.x,t);
}

当然这里如果我们想要彻底摆脱if-else,但是这里我们可以使用委托数组,彻底去掉if-else.

static GraphFunction[] functions={SineFunction, MultiSineFunction};

GrapFunction f = functions[function];

分形
https://mp.weixin.qq.com/s/uTCH2WfLG3Ow0iuSGdKbjA

public class Fractal:MonoBehaviour
{
	public Mesh mesh;
	public Material material;
	private void start()
	{
		gameObject.AddComponent<MeshFilter>().mesh=mesh;
		gameObject.AddComponent<MeshRenderer>().material=material;
	}
}

这是一个拥有mesh以及材质的gameobject。我们通过创建分形的方法,创建一个新的对象。

public class Fractal:MonoBehaviour
{
	public Mesh mesh;
	public Material material;
	private void start()
	{
		gameObject.AddComponent<MeshFilter>().mesh=mesh;
		gameObject.AddComponent<MeshRenderer>().material=material;
		new GameObject("Fractal Child").AddComponent<Fractal>();
		
	}
}

这里的new创建了一个新的对象实例。这个实例与Fractal完全相同,包括对应的script,所以这个会递归产生一模一样的gameobject。当然,我们可以通过设立深度的方法完成

public class Fractal:MonoBehaviour
{
	public Mesh mesh;
	public Material material;
	public int maxDepth;
	public int depth;
	private void start()
	{
		gameObject.AddComponent<MeshFilter>().mesh=mesh;
		gameObject.AddComponent<MeshRenderer>().material=material;
		if(depth<maxDepth)
			new GameObject("Fractal Child").AddComponent<Fractal>().Initialize(this);
		
	}
	private void Initialize(Fractal parent)
	{
		mesh = parent.mesh;
		material = parent.material;
		maxDepth = parent.MaxDepth;
		depth = parent.depth+1;
	}
}

这里的this关键字,代表的是正在调用其方法的当前对象或者是结构。

函数调用流程:
首先创建新的游戏对象,然后创建并田间一个新的分形组件,如果存在awake或者是OnEnable,然后通过AddComponent方法完成,在此之后,直接调用Initialization,start的调用需要再往后。

当然这里的创建过程会非正常迅速,所以我们可以使用协程来减缓相关的进度。

private void Start()
{
	gameObject.AddComponent<MeshFilter>().mesh=mesh;
	gameObject.AddComponent<MeshRenderer>().material = material;
	if(depth<maxDepth)
	{
		StartCoroutine(CreateChildren());
	}
}
private IEnumerator CreateChildren()
{
	yield return new WaitForSeconds(0.5f);
	new GameObject("Fractal Child").AddComponent<Fractal>.Initialize(this,Vector3.up);
	yeild return new WaitForSeconds(0.5f);
	new GameObject("Fractal Child").AddComponent<Fractal>.Initialize(this,Vector3.right);
}

enumerator(枚举器)或者是iterator(迭代器)是为了遍历而创建的接口。协程使用这个控制相关代码块的顺序。yield语句被迭代器用来控制协程的生命周期。要使用枚举,就需要跟踪它的进度。这涉及到一些基本相同的样模板码。你真正想要的是只编写类似于 return firstItem; return secondItem这样的代码,直到函数执行结束。yield语句允许你准确地做到这一点。因此,无论何时使用yield,都会在幕后创建枚举器对象,以处理繁琐的部分。协程怎么工作?

当你在Unity中创建协程时,真正做的其是创建一个迭代器。当你将它传递给StartCooutine方法时,它将被存储,并被要求每帧都要它的下一个Item,直到它完成为止。yield语句会产生Item。而这中间的部分就是你可以发挥的地方了。

什么是动态批处理?

动态批处理是由Unity执行的一种drawcall批处理形式。简而言之,它将共享相同材料的网格组合成更大的网格。这样做减少了CPU和GPU之间的通信量。

2.基础(新版)
Instantiate 实例化对象

创建表面着色器
表面着色器如何工作?
Unity提供了一个框架来快速生成执行默认照明计算的着色器,你可以通过调整某些值来影响该着色器。这种着色器称为表面着色器。不幸的是,它们仅适用于默认渲染管道。稍后我们将介绍通用渲染管道。

性能衡量
什么是线程?
在Unity应用程序的情况下,线程是子进程。可以有多个线程同时并行运行。统计信息显示在上一帧期间Unity的主线程和渲染线程运行了多长时间。

Compute Buffer
如果所有的内容全部存在cpu上的话,会出现反复读取的问题,直接将数据存放在GPU上可以有效的避免这个问题。

//使用这个方法可以支持热重载,在运行状态下可以直接更改。
OnEnable()
{
   positionBuffer=new ComputerBuffer(number,3*4);//数量 每一个单位的大小。
}

这里我们需要使用Compute Shader来计算处于GPU上的数据,完成渲染。

II.运动控制
(1)滑动小球

https://zhuanlan.zhihu.com/p/267837227

[SerializeField]
将一个变量显示在右面板上。
[SerializeField,Range(0f,100f)]
变量后附加一个滑块

Rect 矩形变量
Rect allowedArea=new Rect(-5f,-5f,10f,10f);
Vector3 newPosition =new Vector3(0,0,0);
判断一个点是否在一个范围内。
allowedArea.Contains(newPosition)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值