Unity学习日记 #基础篇
查找物体
- 无父子关系查找
GameObject.Find(string objName)
GameObject.FindGameObjectWithTag(string tagName)
- 无法查找隐藏对象
- 允许查找同名物体,找到的是最新创建的游戏物体
- 有父子关系查找
- transform.Find(string objPath)
- 1.允许查找隐藏物体
- 2.可以指定完整路径
- transform.parent获取父节点
- 设置父子关系与调整同一父节点下的顺序
- transform.SetParent();设置父节点
- transform.parent = other(transform);
- transform.SetAsFirstSibling();设为该父节点下首位
- transform.SetAsLastSibling();设为该父节点下末位
- transform.SetSiblingIndex(int index);设为该父节点下第index位
坐标与转换
-
position即为世界坐标
-
localPosition是相对与父物体的坐标
- position = localPosition + 父节点position
-
屏幕坐标转世界坐标
-
Vector3 Camera.main.ScreenToWorldPoint(new
-
Vector3(screenPos.x,screenPos.y,zInfo))
-
直接用鼠标坐标转世界坐标,返回的坐标不正确,是因为没有正确的给到要点击屏幕的,转换为
屏幕坐标的z轴,假如我们要让player在xy屏幕点击瞬移
Vector3 playerDir = Camera.main.WorldToScreenPoint(transform.position); Vector3 mousePos = Camera.main.ScreenToWorldPoint( new Vector3(Input.mousePosition.x, Input.mousePosition.y,playerDir.z)); //先求出世界坐标转换为屏幕坐标的z轴(世界坐标z轴与屏幕坐标z轴截然不同) //再通过鼠标屏幕坐标x,屏幕坐标y,上面求的屏幕坐标z,即可让玩家在当前屏幕点击移动
-
-
世界坐标转屏幕坐标
- Vector3 Camera.main.WorldToScreenPoint(new
- Vector3(worldPos.x,worldPos.y,worldPos.x))
-
世界坐标转视口坐标
Vector3 Camera.main.WorldToViewportPoint(new Vector3(worldPos.x,worldPos.y,worldPos.x)) -
视口坐标转世界坐标
Vector3 Camera.main.ViewportToWorldPoint(new Vector3(viewPos.x,viewPos.y,zInfo)) -
视口坐标转屏幕坐标
Camera.main.ViewportToScreenPoint(); -
屏幕坐标转视口坐标
Camera.main.ScreenToViewportPoint();
方向
世界方向
Vector.left Vector.right Vector.up Vector.down Vector.forward Vector.back
自身方向
tramsform.left tramsform.right tramsform.up tramsform.down
tramsform.forward tramsform.back
光源
图形学四种光源
点光源
直射光
聚光灯
区域光
常用组件与其属性
Transform组件
该组件规定了游戏物体的位置(position),旋转(rotation),缩放(scale)
-
移动
-
直接赋值
transform.position = targetPosition;
-
朝某个方向移动
transform.Translate(direction.normalized * speed * Time.deltaTime);
-
-
旋转
transform.Rotate();
transform.RotateAround();
-
缩放
transform.localScale = targetScale;
// 相对于父物体的大小
-
transform.LookAt
是Unity引擎中用于设置物体朝向的一个方法。调用后物体会朝向你指定的物体
AudioClip:声音片段,可对其直接赋值声音文件
Output:音源输出
Mute:是否静音
Bypass Effects:音源滤波开关,是否打开音频特效
Bypass Listener Effe:监听滤波开关
Bypass Reverb Zone:回音混淆开关,当勾选时,不执行回音混淆
Play On Awake:开机自动播放
Loop:循环播放
Priority:播放优先级
Volume:音量大小,范围0到1。
Pitch:播放速度,范围-3到3。
Stereo Pan:声道占比
Spatial Blend:空间混合
Reverb Zone Mix:回音混合
3D Soungd Settings:3d声音设置,一般是不用
Rigidbody刚体组件
Mass:质量。数值越大物体下落越快
Drag:阻力,数值越大物体反向加速度越大
Angular Drag:角阻力,数值越大自身旋转的速度减慢的越快
Use Gravity:是否使用重力
Is Kenematic:是否受物理的影响
Interpolate:设置图像差值
-
默认为none,由于图形更新比物理更新要快,可能会导致物体跳跃式前进。
-
Interpolate模式:物体会根据上一帧物体的位置进行平滑运动。
-
Extrapolate模式:物体会根据下一帧物体的位置进行平滑运动
-
Collision Detection:碰撞检测
对于高速运动的物体来说,当Collision Detection为默认的Discrete时,有可能存在一种情况:前一帧时,物体在碰撞器的一边,下一帧时,物体也已经穿越了碰撞器达到了另一边,以致于检测不到碰撞。这时,我们就需要连续碰撞检测。- Discrete:非连续型检测模式(默认)
- Continuous:连续检测。
更加精细的碰撞检测,但是很耗资源;在这种状态下,当这个刚体与其他普通刚体碰撞时,仍将使Discrete的碰撞检测,但是与没有刚体的Mesh Collider碰撞时就会连续检测了。 - Continuous Dynamic:连续动态检测。
对没有刚体的Mesh Collider或是对处在Continuous或是Continuous Dynamic状态下的刚体使用连续碰撞检测,对其他的刚体使用普通的Discrete检测。
Continuous和Continuous Dynamic的区别在于对Continuous使用何种检测 ,Continuous使用Discrete,而Continuous Dynamic使用Continuous。但它们对物理性能都有很大影响。
-
刚体和刚体之间的连续碰撞检测,刚体的碰撞器必须是BoxCollider或SphereCollider或CapusleCollider.
-
刚体和非刚体(静态碰撞器)之间的连续碰撞检测,刚体的碰撞器必须是BoxCollider或SphereCollider或CapusleCollider,非刚体的碰撞器必须是Mesh
Constraints:冻结,停止某个轴向感应物理引擎的效果 -
Freeze Position:冻结x轴方向,y轴方向,z轴方向
-
Freeze Rotation:冻结x轴旋转,y轴旋转,z轴旋转
Mesh Collider组件
- Convex:凸起,勾选后,与其它基本碰撞体发生碰撞
- Inflate Mesh:网格膨胀,它有效地扩展了源数据的边缘宽度和斜切锋利的边缘,使所得网格适合物理更好,将此设置为true可以降低碰撞网格的精度
- Skin Width:皮肤厚度,一个合理的设定是使该值等于半径(Radius)的10%
Is Trigger:触发器
Material:材质,引用何种物理材质决定了和其他对象如何作用
Mesh:网格,获取对象的网格并将其作为碰撞体
Capsule Collider组件
- Edit Collider:点击之后可编辑碰撞范围
- Is Trigger:触发器
- Material:材质
- Center:碰撞体在对象局部坐标空间中的位置
- Radius:碰撞体局部坐标宽度的半径
- Height:碰撞体的总高度
- Direction:对象局部坐标空间中胶囊纵向方向的轴
Box Collider组件
-
Edit Collider:点击之后可编辑碰撞范围
-
Is Trigger:触发器
-
Material:材质
-
Center:碰撞体的中心
-
Size:碰撞体大小
Sphere Collider组件
-
Edit Collider:点击之后可编辑碰撞范围
-
Is Trigger:触发器
-
Material:材质
-
Center:碰撞体的中心
-
Radius:碰撞体半径
Camera组件
-
Camera.main 等价于 GameObject.FindGameObjectWithTag(“Main Camera”);即是标签查找
-
属性
-
Clear Flags:背景显示内容。
-
SkyBox: 默认是天空盒子,这个在设置中是可以修改的,lighting/Scene/skybox
-
Solid Color:纯色,选择此选项显示background颜色
-
Depth Only:仅深度,用于游戏对象不希望被裁减的情况
-
Don’t Clear:不清除,不清除任何颜色或深度缓存,其结果是,每一帧渲染的结果叠加在下一帧之上,一般与自定义的shader使用
-
Background:背景显示颜色。没有天空盒子将显示这个颜色。
-
Culling Mask:用于选择是否显示某些层,默认是Everything
-
Projection:摄像机的类型(投射方式)。
-
Perspective:透视,摄像机将用透视的方式来渲染游戏对象
-
Orthographic:正交,摄像机将用无透视的方式来渲染游戏对象
-
Size:大小,用于控制正交模式摄像机的视口大小
-
Field Of View:视野范围,用于控制摄像机的视角宽度以及纵向的角度尺寸
-
Clipping Planes:剪裁平面。摄像机的渲染范围,Near为最近的点,Far为 最远的点
-
Viewport Rect:视图矩形。用四个数值来控制摄像机的视图绘制在屏幕的位置和大小,使用的是屏幕坐标系,数值在0~1之间。坐标系原点在左下角。
-
Depth:深度。用于控制摄像机的渲染顺序,较大值的摄像机将被渲染在较小值的摄像机之上
-
Rendering Path:渲染路径。用于指定摄像机的渲染方法。
-
Use Graphics Settings:选择图形设置中的方法
-
Forward:快速渲染,传统的渲染路径,它支持每个像素的光照及平行光(directional light)的实时阴影
-
Deferred:延迟渲染,会准确如实地渲染光照和阴影。如果有许多实时光照,最适合它,需要一定程度的硬件支持,不支持移动设备
-
Legacy Vertex Lit:顶点光照,摄像机将对所有的游戏对象座位顶点光照对象来渲染
-
Legacy Deferred(light prepass):具有最低照明保真度和不支持实时阴影的渲染路径。它是前向渲染路径的子集。
在使用正投影时不支持延迟渲染。如果相机的投影模式被设置为正交,则这些值被重写,并且相机将总是使用快速渲染。 -
Target Texture:目标纹理,用于将摄像机视图输出并渲染到屏幕。
-
Occlusion Culling:遮挡剔除
-
HDR:高动态光照渲染,用于启用摄像机的高动态范围渲染功能,因为人眼对的范围的光照强度更为敏感,所有用高动态范围渲染能让场景变得更为真实,光照的变化不会显得太突兀。
-
Target Display:目标显示
Directional light组件
直射光
Type:光源类型,可选择不同光源
Baking:用于烘焙模式的,在Lighting面板下点击Bake进行烘焙光照贴图时,生成对应的反射贴图
Color:光照的颜色
Intensity:光照强度
Bounce Intensity:放射光的光照强度
Shadow Type:光源投射的阴影类型
Cookie:一个遮罩,使光线在不同的地方有不同的亮度。如果灯光是聚光灯或方向光,这必须是一个2D纹理。如果灯光是一个点光源,它必须是一个立方图(Cubemap)
Cookie Size:缩放Cookie投影。只用于方向光。
Draw Halo:是否在点光源中使用白雾效果
Flare:设置光源粒子效果
Render Mode:光源渲染模式
Culling Mask:通过层可设置某些地图层不受光照影响
Point light参数
点光源,和平行光没有太大的区别,唯一的就是多了一个Range参数,这个表示的是点光源照射的范围
Spot Light参数
聚光灯,和平行光没有太大的区别,唯一的就是多了一个Range参数和Spot Angle,这个表示的是手电筒照射的范围,后者表示手电筒照射的角度
Area Light参数
区域光,和平行光没有太大的区别,唯一的就是多了一个Height参数和Width,表示区域的高度和大小
MonoBehaviour
- 所有unity创建的脚本都必须继承
MonoBehaviour
- 所有挂载在游戏物体上的脚本都必须继承
MonoBehaviour
- 所有继承了
Monobehaviour
的类都无法使用new来创建对象
生命周期
Awake()
- 脚本实例倍创建时调用,只调用一次
OnEnable()
- 当游戏对象被激活时调用
Start()
- Awake() 和 OnEnable() 被调用,只调用一次
FixedUpdate()
- 固定时间调用 Time.fixedDeltaTime
- projectSetting -> Time ->可调间隔时间
- 与物理有关更新放FixedUpdate
Update()
- 每帧调用 Time.deltaTime
LateUpdate()
- Update()之后调用
OnGUI
- 渲染和处理GUI事件
OnDisable()
- 对象失活的时候调用
OnDestory()
- 当游戏对象被销毁的时候调用
- 同级别同一个物体上的脚本,后挂载的先调用
- 通过设置execution order可以自定义脚本执行顺序,点击任意脚本右上角
通过脚本创建物体
- 通过预制体prefab
- Hierarchy窗口蓝色游戏物体即是关联了预制体
GameObject.Instantiate()
通过游戏物体(包括预制体)创建物体实例
Unity拿到其他类实例或者资源方式
网上都教拖拽,但是一般尽量不用拖拽- 通过代码来加载
- 资源加载
Resourece.Load<T>
(Resource下的文件路径)
- 资源加载
Unity中的输入
- Edit->Project Setting -> Input Manager ->Axes 打开设置输入
- Input类
- name:轴的名称,用于游戏加载界面和脚本中
- descriptive name:描述名称,轴的正向按键的详细描述
- descriptive negative name:轴的反向按键的详细描述
- negative button:该按钮用于在负方向移动轴
- positive button:该按钮用于在正方向移动轴
- alt negative button:备用按钮,用于在负方向移动轴
- alt positive button:备用按钮,用于在正方向移动轴
- gravity:输入复位的速度
- dead:模拟死区大小,任何小于该值的输入值(不论正负值)都会被视为0,通常用于摇杆
- sensitivity:灵敏度,该值越大响应时间越快
- snap:捕获,当获取到相反信号时,轴的数值为立即置为0
- invert:反向,可以让正向按钮发送负值,负向按钮发送正值
- type:控制轴的输入设备类型
- 键盘输入
Input
GetKey
持续按下GetKeyDown
瞬间动作按下GetKeyUp
瞬间动作抬起anyKey
任意键持续按下anykeyDown
GetButton(string ButtonName)
GetButtonDown(string ButtonName)
GetButtonUp(string ButtonName)
- 鼠标输入
Input
GetMouseButton(int index)
0 1 2分别是鼠标左键 鼠标右键 鼠标中间GetMouseButtonDown(int index)
按下GetMouseButtonUp(int index)
抬起
- 鼠标API
Input.mousePosition
鼠标屏幕位置Input.mouseScrollDelta
:鼠标滚轮偏移量
- 通用
Input.GetAxis
渐变到-1 1Input.GetAxisRaw
直接到 -1 1
- 移动设备的触摸
- 触摸插件:EasyTouch
- Input TouchScreenKeyboard
- 触摸 重力加速度 虚拟键盘
multiTouchEnabled
:是否启用多点触摸simulateMouseWithTouches
:是否启用仿真鼠标的操作touchCount
:在当前帧中触摸的数量touches
:在上一帧中触摸点的信息touchSupported
:当前设备是否支持触摸GetTouch
:根据触摸点的索引获取触摸点的信息
射线Ray
-
射线定义:是3D世界中一个点向一个方向发射的一条无终点的线,在发射的过程中与其他物体产生碰撞,将停止发射。
-
鼠标点击屏幕获取射线,再通过射线检测
-
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
可以通过摄像机与鼠标位置,获取一条鼠标延伸至3D空间的射线
-
Debug.DrawLine(ray.origin, ray.direction, Color.red);
通过Debug我们可以画出射线(只在Scene窗口),可以更明显的观察射线
-
//通过获取的射线,检测射线上的所有物体 RaycastHit[] raycastHits = Physics.RaycastAll(ray, Mathf.Infinity,1<<LayerMask.NameToLayer("Plane")); if (raycastHits.Length>0) { foreach (RaycastHit item in raycastHits) { Debug.Log(item.collider.name); } }
-
//通过获取的射线,检测射线碰到的第一个物体 RaycastHit hitInfo; if (Physics.Raycast(ray, out hitInfo)) { Debug.Log("检测到物体"+hitInfo.collider.name); }
-
-
相交球向围绕自身的球发射射线,检测球体积内所有碰撞体
-
Collider[] colliders = Physics.OverlapSphere(transform.position, 3,1<<LayerMask.NameToLayer("Plane")); foreach (Collider item in colliders) { Debug.Log(item.name); }
-
纹理 贴图 材质
-
纹理Texture
-
将图片拉入unity就变成纹理,纹理即图片
-
注意:纹理类型,填充模式,采样模式
-
纹理类型 Texture Type
- Default 默认
- Sprite 精灵
- Cursor 鼠标
-
填充模式 WrapMode
- Clamp
- 取某个像素填充
- Repeat
- 重复
- Mirror
- 镜像
- Mirror once
- 镜像一次
- Per Axis
- X,Y选择不同的填充模式
- Clamp
-
采用模式 FilterMode
-
Point
- 点采集
-
Bilinear
- 双线采集
-
Trilinear
- 三线采集
-
清晰度 Trilinear > Bilinear > Point
-
-
-
贴图Texture Mapping
- 定义:将纹理通过uv坐标映射到3d物体表面。
-
材质Material
- 由贴图、颜色、Shader组成
-
材质包含了贴图,贴图包含了纹理
动画系统
-
老版本使用Animation,新版本使用的Animator
-
两者创建的动画不一样,不能混用
-
Animation动画系统
- 用于单个动画播放,多个动画播放需要代码
- Animation系统创建动画
- 点击具体的Gameobject在Animation窗口点击Create创建
-
Animator动画系统
-
用于播放动画,动画状态机,可以控制多个动画
-
一些属性设置
- controller:动画状态机
- avatar:骨骼模型
- apply root motion:应用动画本身的位置还是脚本控制角色位置
- update mode:更新模式
-
Animator系统创建Animation
- 在资源视图右击创建Animation
-
BlendTree混合树
- Animator窗口右击 CreateState -> From new BlendTree
- 双击BlendTree进入编辑
- 可以添加多个动作,设置播放比例
-
-
帧事件
- 当使用模型时,可以使用模型动画来触发方法,即帧事件
- 在动画播放到某一帧的时候执行事件
- Animation窗口,右击add event
-
可以设置Animator的Update Mode 为 unTimeScale 不受时间尺度影响
线性插值
-
线性插值 Lerp(a,b,t); 从a变化到b,按照t的百分比来变化
( ( b − a ) ∗ t ) + a ((b - a)*t)+a ((b−a)∗t)+a -
//利用线性插值颜色来回渐变 private Color startColor = Color.red; private Color endColor = Color.blue; private Renderer renderer; // Use this for initialization void Start () { renderer = this.GetComponent<Renderer>(); } // Update is called once per frame void Update () { renderer.material.color = Color.Lerp(startColor, endColor,Mathf.PingPong(Time.time, 1)); }
-
Lerp(start,end,t);
-
注意t的范围为0 - 1,所以给t的形参大于1的时候值时,
应该给百分比 t = Value/ValueMax
-
-
一些常见类的Lerp
- Vector3.Lerp
- Color.Lerp
- Math.Lerp
Mathf
- **Mathf.PingPong(t, length)**根据时间增量从0 - length,再从length - 0
- 比如t从 1- 2,增量为1,那么返回的值也比上次调用增多1
- 在Unity中,我们常常使用Time.time控制时间增量,Time.time记录了游戏到现在运行时间
- 在Update中调用,1秒中返回值增量为1
- Mathf.Lerp(start,end,t);
- 注意t的范围为0 - 1,所以t给值时,应该给百分比 t = Value/ValueMax
协程
在unity主线程运行的时候,开启另外一段逻辑来协助当前程序的执行,协程不是线程,unity不支持多线程
unity协程是一个能够暂停程序的执行,遇到中断指令,暂停立即返回主函数,执行主函数剩余的部分,直到中断指令完成后,从中断指令的下一行继续执行协程剩余的函数,函数体全部执行完成后,协程结束
-
定义协程关键字 IEnumerator
-
协程执行的顺序:
- 开始协程
- 执行协程
- 遇到中断指令,中断协程
- 返回上层函数,继续执行上层函数的下一行代码
- 中断指令结束,继续执行中断指令之后的代码
- 协程结束
-
协程调用方式
-
第一种调用
- StartCoroutine(函数名())
- StartCoroutine(函数名(参数列表))
-
第二种调用:
- StartCoroutine(“函数名”)
- StartCoroutine(“函数名”,参数列表)
-
怎么开的怎么关
- StopAllCoroutines():关闭当前脚本中的所有协程
- StopCoroutine(函数名())
- StopCoroutine(“函数名”)
-
-
协程内部
- yield null:协程将在下一帧所有脚本的update执行完后,再继续执行
- yield WaitForSeconds:协程在延迟指定时间,且当前帧所有脚本的update全部执行完后才会继续执行 当timescale=0,是不会执行
- yield WaitForFixedUpdate:协程在所有脚本的fixedupdate执行完后,再继续执行
- yield WWW:协程在www下载资源完成后,再继续执行
- yield StartCoroutine:协程在指定协程结束后,再继续执行
- yield WaitForSecondsRealtime:协程在延迟指定时间,且当前帧所有脚本的update全部执行完后才会继续执行,不受时间缩放影响的
-
协程会受其他因素影响:
- 1.时间缩放
- 2.实际等待的时间和中断指令的时间不一定相等
-
IEnumerator TestIenumerator() { Debug.Log("输出 语句 1 "); yield return new WaitForSecondsRealtime(3.0f); Debug.Log("输出 语句 2"); } void Start() { StartCoroutine(TestIenumerator()); Debug.Log("start函数执行"); }
碰撞 触发
-
发生碰撞的必要条件
- 碰撞体collider
- 双方带有collider,其中运动的一方带有rigidbody
-
发生触发的必要条件
- 触发器trigger
- collider勾选IsTrigger,就变成触发器
- 双方带有collider,一方要勾选IsTrigger,其中运动的一方带有rigidbody
-
触发器和碰撞体之间的关系
- 碰撞体是触发器的载体
- 触发器是碰撞体的属性
-
碰撞系统
OnCollisionEnter(Collision other);
(OnCollisionEnter2D(Collison other)处理2D碰撞)OnCollisionStay(Collision other);
OnCollisionExit(Collision other);
-
触发系统
OnTriggerEnter(Collider other);
OnTriggerStay(Collider other);
OnTriggerExit(Collider other);