通过代码创造图形
//创建顶点,创建序列,创建网格,然后把网格赋给网格序列器 //draw a triangle void Start () { Vector3[] vs = new Vector3[3]; vs[0] = new Vector3(0,0,0); vs[1] = new Vector3(1,0,0); vs[2] = new Vector3(0,1,0); int[ts] = new int[3]; ts[0] = 0; ts[1] = 1; ts[2] = 2; //要注意顺序,要用左手系,法线向外,拇指向外 Mesh mesh = new Mesh(); GetComponet<MeshFilter>().mesh = mesh; mesh.vertices = vs; // vertices至高点 mesh.triangles = ts; }
///* *///
//draw a triangle程序封装代码 public GameObject Create Triangle() { GameObject obj = new GameObject(“Triangle”); MeshFilter mf = obj.AddComponet<MeshFilter>(); obj.AddComponent<MeshRender>(); Mesh mesh = new Mesh(); mesh.vertices = nes[] { new Vector3(0,0,0); new Vector3(3,0,0); new Vector3(0,3,0); }; mesh.triangles = new[] { 0,2,1 //不用分号,初始化系,直接把初始值放进去 }; mf.mesh = mesh; return obj; }
Camera 的性质与使用
//Camera的实例性质
public CameraClearFlags clearFlags; //clearFlags是相机清除表识
public ColorbackgroundColor; //给定他的颜色,背景色,只有单色才起作用
public int cullingMask; //提出掩码
public class chapter6 : MonoBehaviour { public GameObject cube; void Start(){ cube.laber = 9; //把cube设置在第9层 Camera cam = this.GetComponet<Camera>()’ cam.clearFlags = CameraClearFlags.SolidColor; cam.backgroundColor = new Vector3(1,0,0,0); //表示设置颜色 cam.cullingMask = 9; //表示第9层的都不会被渲染出来,也就是说cube不会显示出来 } }
//CameraClearFlags是一个枚举类型,有以下四个成员:
solidColor 表示用backgroundColor所制定的填充背景
skybox 表示天空盒,模拟天空效果填充
Depth 只是清除深度缓存,保留上一帧所使用的颜色
Nothing 不进行背景清除,这种情况在游戏和模拟应用中比较少用
public bool orthographic;//用于读取和设定相机的投影方式,如果为true则表示是正交投影,否则为透视投影;正交投影可用于UI和2D开发
public float orthographicSize; //用以指定正交投影的视景体的垂直方向尺寸的一半
public Rect rect; //相机对应的视角口的位置和大小,rect以单位化形式制定相机视口在屏幕中的位置和大小,位置大小取值范围为0~1,满屏为1
Camera main = this.gameObject.GetComponet<Camera>(); this.gameObject.SetActive(false); Camera cam0 = camGO0.AddComponet<Camera>(); cam0.orthographic = true; cam0.transform.position = main.transform.position; cam0.transform.rotation = main.transform. rotation; cam0.orthographicSize = 2.0f; //指物体渲染后显示的大小远近,数值越大,相机视口越靠近该物体,从而该物体显示出来的更加大 cam0.rect = new Rect(0f,0f, 0.5f, 0.5f); //前两个参数是camera的位置,后面两个参数设置相机大小(0.5f,0.5f)表示占x轴的二分之一,y轴的二分之一,所以总共占渲染窗口的四分之一 Camera cam1 = camGO1.AddComponet<Camera>(); cam1.orthographic = true; cam1.transform.position = main.transform.position; cam1.transform.rotation = main.transform. rotation; cam1.orthographicSize = 7.0f; cam1.rect = new Rect(0.5f, 0.5f, 0.5f, 0.5f); }
Material,Shader,Texture(材质,着色器,纹理)
光照、纹理等让物体更加的真实。
材质在几何物质的基础下增加额外的东西,让物体显得更加真实。
着色器:核心最后的渲染过程。特殊的一串代码,用特殊语言所写,实现一定的算法。计算每个像素点的颜色。根据定点信息,光照,材质,计算顶点颜色,最后显示出来。Unity提供多种着色器提供选择。有专门一本书提供着色器的介绍。主流工具语言是Cg(C语言+graph)
纹理:图片,增加在物体表面,复制在材质上,材质再复制给物体。美工的过程。
程序开发人员主要处理的是材质。
Rendering Mode,渲染模式,进一步确定着色器类型,在Standard系列下,有四种类型:Opaque(不透明), Cutout(表示在透明和不透明区域之间具有尖锐边沿,没有不透明效果,比如说一些镂空边缘或者一些草的材质), Fade(渐变,用以表示材质的透明度逐渐改变), Transparent(处理透明的,比如说玻璃材质)
Albedo,反照率,表示一种材质对白光的反射能力,是材质的散射、反射、折射和半透明成分的总和,相关参数控制物体表面的基色,纯黑色「RGB=(0,0,0),Albedo=0」;白色「RGB=(1,1,1), Albedo=1」。alpha通道控制材质透明度,alpha值越小,Albedo的实现效果越微弱(因为alpha越透明度越高,当透明度极高的时候甚至不可以看到表面效果,所以有材质没材质,有调Albedo和没调也一样)。
Metallic,表示材质处于金属模拟工作流metalness workflow下。金属模拟工作流与镜面反射工作流specular workflow是两种处理光反射的不同模式。
光照于CG中十分重要。PBR(physical base render)基于物理渲染,可以模拟光线于现实的情况,实现光线追踪。
Smoothness,光滑度,最光滑相当于镜面反射。
MeshFilter&MeshRender
网格渲染器
Cast shadows,一个开关,该网格物体是否产生阴影
Receive Shadows,一个开关,是否接受其他物体投射到其上面
Motion Vectors, 运动适量,用于追踪一个物体从一帧到下一帧的空间位置,并可用于后期处理效果,比如说运动模糊处理和时域抗锯齿效果。
Coding for materials
Shader shader; Texture texture; Color color; void Start(){ Renderer rend = GetComponet<Renderer>(); rend.material = new Material(shader); //把着色器、材质、颜色复制给该物体 rend.material.mainTexture = texture; rend.material .color = color; }
Using colors
public class Example: MonoBehaviour{ Color colorStart = Color.red; Color colorEnd= Color.green; //颜色差值算法 float duration = 1.0f; Renderer rend; void Start(){ rend = GetComponent<Renderer>() } void Update(){ float lerp = Mathf.PingPong(Time.time, duration)/duration); //如果大于该值则截断,返回上一个值, 然后开始往回缩小值,类似打乒乓球一样 //该参数为,从0到1,在从1到0,如果是0则为纯粹的红色,如果为1则为纯粹的绿色,动态的改变,包括颜色、位置 rend.material.color = Color.Lerp(colorStart, coloredEnd, lerp); //lerp只能是在0~1之间,所以上面一定要除以duration } }
纹理大小要满足2的n次方(2、4、8、… 、1024、2048)等, Unity允许倒入的最大纹理为8k
Operating textures with codes
public class ExampleClass:MonoBehaviour{ public Texture[]texture; public float changeInteval = 0.33F; public Renderer rend; void Start( rend = GetComponet<Renderer>;) void Update(){ if (textures.Length == 0)return; int index = Methf.FloorTolnt(Time.time/changelntervla); index = index % textures.Length; rend.material.mainTexture = textures[index]; } }
物理组件(刚体组建)
Rigidbody:
Is Kinematic,勾选上物体运动将不会受物理引擎没有关系,只纯粹受transform影响,但是会受其他影响;虽然缸体自身不受力和碰撞的影响,但会通过力的碰撞传导给别的物体;
Interpolate,差值;
Collosion Detection, 用于检测与其他刚体的碰撞,其主要目的之一是防止物体之间的穿越 [默认为Discrete,表示每一帧做一次检查,缺点是快速移动游戏对象会有穿透现象];
Constraints,刚体约束,可以冻结游戏对象在某个方向限制的移动和旋转。eg.,如果选择了Freeze Position中的X,表示冻结游戏对象在X轴上的运动;如果选择Free Rotation下的X,表示冻结游戏对象在X轴上的旋转。[ 使用价值,比如说挂钩有时候只会在一个方向上乱动,所以冻结其他方向的数值,从而不让该物体受到力的影响后在其他方向上乱晃 ];
通过控制面板,Rigibody类的使用方法:
public class fvc_rigibody_falling: MonoBehaviour{ private Rigibody rg; //通过代码实现自由落体 void Start(){ rb = this. gameObject.AddComponent<Rigibody>(); rb.isKinematic = false; //受物理引擎影响,isKinematic不开启 rb.detectCollisions = ture; rb.useGravity = true; rb.mass = 0.1f; } void Update(){ rb.drag = Mathf.Repeat(Time.time*15f, 8.0f); } }
//模拟一个球平抛运动 public class fvc_rigibody_falling: MonoBehaviour{ private Rigibody rg; //通过代码实现自由落体 ///* [Range(0,20)] public int speed = 5; public GameObject humanbeing; */// privare Vector3 old_pos; void Start(){ rb = this. gameObject.AddComponent<Rigibody>(); rb.isKinematic = false; //受物理引擎影响,isKinematic不开启 rb.detectCollisions = ture; rb.useGravity = true; rb.mass = 0.1f; rb.velocity = 5.0f* Vector3.right; //给物体增加一个速度 old_pos = transform.position; //humanbeing.transform.Translate(0,0,speed*Time.deltaTime,Space.World); } void FixedUpdate(){ //把抛物线画出来 Debug.DrawLine(old_pos, transform.position, Color.red, 60,false); //把抛物线画出来 old_pos = transform.position; } void Update(){ rb.drag = Mathf.Repeat(Time.time*15f, 8.0f); } }
angularVelocity表示角速度
centerOfMass表示刚体质心
//让刚体旋转 public class fvc_rigibody_falling: MonoBehaviour{ private Rigibody rg; //通过代码实现自由落体 void Start(){ rb = this. gameObject.AddComponent<Rigibody>(); rb.angularVelcity = new Vector3(0,2.4f,0); //通过物理引擎来模拟旋转效果,底层驱动是物理引擎 rb.detectCollisions = false; re.angularDrag = 0.01f; } void Update(){ if(Input. GetKeyDown(KeyCode.Space)){ rb.freezeRotation = true; } if(Input. GetKeyDown(KeyCode.Z)){ rb.centerOfMass = new Vector3(-0.5f,0,0); } if(Input. GetKeyDown(KeyCode.X)){ rb.centerOfMass = new Vector3(0,0,0); } } }
force表示力的矢量,该矢量长度表示力的大小,参数mode表示模式
public void AddForce(Vector3 force, ForceMode mode = ForceMode.Force); //给物体加力效果,第一个force表示给刚体的加速度,该力是在世界坐标下,eg,.橙色坐标
public void AddForceAtPosition(Vector3 force, Vector3 position, ForceMode mode = FforceMode.Force);//围着质心的轴旋转,和上面的一样,不过多了个position参数
public void AddRelativeForce(Vector 3 force, ForceMode.mode = ForceMode.Force );//加相对力,相对于力的局部坐标下,eg,.绿色坐标
Impulse, 表示冲量,根据物理当中的动量定理更适用于模拟力作用的瞬间效果,比如冲击力和爆炸效果
VelocityChange, 函数的第一个参数force表示游戏对象的速度改变了,此时游戏对象的、础运动速度,与其质量无关
//添加一个力 public class fvc_rigibody_force: MonoBehaviour{ private Rigibody rg; //通过代码实现自由落体 void Start(){ rb = this. gameObject.AddComponent<Rigibody>(); rb.mass = 0.5f; rb.UseGracity = false; rb.AddForce(new Vector3(4,0,0), ForceMode.Force); print(fvx_tools.to_string(rb.velocity)); } void Update(){ print( fvc_tools.to_string(rb.velocity)); } //void FixedUpdate专门用于物理引擎中的模拟,越跑越快 } }
//给物体增加速度 public class fvc_rigibody_force: MonoBehaviour { private Rigibody rb; void Start(){ this.transform.Rotate(0,0,-20); rb = this.gameObject.AddComponent<rigibody>(); rb.useGravity = false; rb.AddRelativeForce(new Vector3(0,1,0) ForceMode.velocitychange); } }
public Vector3 inertiaTensor:
inertiaTensor表示刚体的惯性藏粮,惯性越大,力相同,旋转的越困难
//例子 public class fvc_rigibody_inertia: MonoBehaviour{ Rigibody rb; void start(){ rb = this.gameObject.AddComponent<Rigibody>()’ rb.inertiaTensor = new Vector(0.05f, 0.05f, 0.05f); rb.mass = 0.5f; rb.angularDrag = 0.0f; rb.useGravity = false; rb.AddForceAtPosition(new Vector3(0.0f, 0.0f, 6.0f), transform.position + new Vector3(0.5f,0,0)); } }
//例子
public void AddTorque(Vector3 torque, ForceMode mode = ForceMode.Force);//加个力矩,全局坐标下,让他旋转
public void AddTorque(float x , float y , float z, ,ForceMode mode = ForceMode.Force)//局部坐标下加力矩
//例子
public Vector3 position; //如果通过position改变刚体的位置,游戏对象的transform会在下一个物理模拟时刻被更新,通过这种方式改变游戏对象的位置比直接使用Transform的position要快,因为后者要重新计算游戏对象中的碰撞器(Collider)位置,同理,通过Rigidbody的rotation改变刚体的姿态进而可以更新游戏对象的Transform,同时,也比直接通过改变Transform的rotation要快
public Quaternion rotation;
//例子
public void MovePosition(Vector3 position);
public void MoveRotation(Quaternion rot); //通过函数调用可以用差值计算,如果不想用差值计算,两者是一样的,但如果要用到,这个和上面的函数两者之间有差别
只有当isKinematic设置为false,施加力矩,碰撞相关的函数才可以起作用
碰撞器
给物体施加碰撞器来检验碰撞效果。Unity中,2D和3D分为了两部份,本课主要讲3D碰撞器。场景复杂的时候计算量会很大。
简单碰撞器
指盒子碰撞器(Box Collider),球形碰撞器和胶囊碰撞器。
bounds类描述一个轴对齐的泪,主要用于游戏对象的碰撞检测中,其构造函数为:public Bounds(Vector3……)
把最小点和最大点定下来,就可以把碰撞器定下来。
is Trigger,该碰撞器是否用作触发器,勾选时成为触发器,触发器是碰撞器的组成部分,当碰撞器用做触发器时,会触发事件,但不受物理引擎控制,与其他对象进行碰撞,而是会发生穿透。不需要避规。
//盒子碰撞器代码 public class fvc_box_collider:MonoBehaviour{ void Stare(){ BoxCollider bc = this.gameObject.GetComponent<BoxCollider>(); print(bc.center); print(bc.bounds.center); } }
物理材质
用来模拟物体接触面的摩擦和弹性属性。
Assets面板点击右键/creat/Physic Material
dynamic Fiction 动摩擦系数(0~1)
static Fiction 静摩擦系数
Bounciness 弹性(0~1)
Friction Combine表示两个碰撞的物体间摩擦的组合(或互相影响)方式
Bounce Combine表示两个物体碰撞组合的方式
(可以用面板来使用该组件,同时也可以自己写代码来编写)
//模拟两个球体碰撞,给sphere1赋予速度,sphere2静止并接受碰撞 public class crash: MonoBehaviour{ public GameObject sphere1; //定义游戏对象的类,一个叫做sphere2,一个叫做sphere2 public GameObject sphere2; void Start(){ //对摄像机的定义 Camera cam = Camera.main; //创建一个摄像机 Vector3 pos = (sphere2.transform.position-shere1. transform.position)*0.5f+ shere1. transform.position; //计算sphere1的运动位置距离 cam.transform.position = pos+new Vector3(0,12,0); //把计算后的距离移动值赋给摄像机的定位值 cam.transform.LookAt(pos, Vector3.forward); //摄像机的看的方向 Vector3 dir = (sphere2.transform.position – shere1.transform.position).normalized; //给sphere1定义刚体组件数据 Rigidbody rb1 = shpere1.AddComponet<Rigidbody>(); //给sphere1赋予刚体组件 rb1.useGravity = false; //使用重力 rb1.mass = 1.0f; //定义质量 rb1.velocity = dir*3.0f; //定义速度 //给sphere2定义刚体组件数据 Rigidbody rb2 = shere2.AddComponent<Rigidbody>(); //给sphere2赋予刚体组件 rb2.useGravity = false; rb2.mass = 1.0f; //给sphere1定义物理材质数据 PhysicMaterial pm1 = new PhysicMaterial(); //定义一个物理材质的类,然后给他开辟新的空间存放 pm1.bounciness = 1.0f; //给sphere1定义摩擦 sphere1.GetComponent<SphereCollider>().material = pm1; //给sphere1定义已经创建的物理材质pm1,并且给该球体添加球形碰撞器 //给sphere2定义物理材质数据 PhysicMaterial pm2 = new PhysicMaterial(); pm2.bounciness = 1.0f; sphere2.GetComponent<SphereCollider>().material = pm2; } //更新数据并打印在测试板块处 void Update(){ print(sphere1.GetComponent<Rigidbody>().Velocity); print(sphere2.GetComponent<Rigidbody>().Velocity); } }