Unity(二) 更多API和物理引擎
Time
deltaTime: 完成上一帧所用的时间,即渲染帧的时间
fixedDeltaTime:执行物理和其他固定帧率更新(如 MonoBehaviour 的 FixedUpdate)的时间间隔
fixedTime:最近一次 FixedUpdate 已启动的时间。此为自游戏启动以来的时间
frameCount:已经过的总帧数
realtimeSinceStartup:游戏开始以来的实际时间
smoothDeltaTime:经过平滑处理的 Time.deltaTime
time:该帧开始的时间。此为自项目启动以来的时间,会受到时间缩放的影响
timeScale:时间流逝的缩放,可用于慢动作效果
timeSinceLevelLoad:该帧开始以来的时间。此为自加载上一个关卡以来的时间
unscaledTime:项目才开始到现在的运行时间,不会受到时间缩放的影响
若要实现每间隔某个固定时间执行某个操作,可以用InvokeRepeating()方法
InvokeRepeating("方法名", 2, 2);//第一个参数为执行方法的名称,第二个参数为开始执行的时间,第三个参数为执行间隔
CancelInvoke("方法名");//停止执行该方法
Input
鼠标输入
GetMouseButton():鼠标左键按下时,返回true,参数为0则是鼠标左键,参数为1则是鼠标右键,参数为2则是鼠标中键
GetMouseButtonDown():鼠标左键按下时的第一帧,返回true只有一瞬间
上述两种方法的区别在于:
GetMouseButton()是按键一直按着时触发;但是GetMouseButtonDown()是按键被按下的那一刻进行触发,下面的GetKey()和GetKeyDown()同理。
Input.GetMouseButtonUp():鼠标左键释放时的第一帧,返回true只有鼠标松开的一瞬间。
键盘输入
GetKey():指定键盘被按住时,返回true
GetKeyDown():指定键盘被按下的那一帧,返回true
GetKeyUp():指定键盘被松开的那一帧,返回true
Vector3相关知识
1、Vector3:即三维向量,表示3D的向量和点。包含位置、方向、欧拉角的信息,也包含做些普通向量运算的函数。
2、Quaternion:即四元数,用于表示旋转,Unity内使用Quaternion表示所有旋转。在电脑图形学中用于表示物体的旋转,在unity中由x,y,z,w 表示四个值。四元数不会产生万向节死锁并且能够很容易被插值。例如tranform组件有一个变量名为rotation,它的类型就是四元数。
3、欧拉角:用来确定定点转动刚体位置的3个一组独立角参量,用来表示旋转角度。
Vector3的一些常用方法:
1.float angle = Angle(Vector a, Vector b):返回a向量和b向量之间的夹角
2.Vector3 b = Vector3.ClampMagnitude(a, float length):返回一个和a向量同方向的b向量,模长为length
3.Vector3 c = Vector3.Cross(Vector a, Vector b):返回a与b的叉乘
4.float distance = Vector3.Distance(Vector a, Vector b:返回a与b坐标之间的直线距离
5.float c = Vector3.Dot(Vector a, Vector b):返回a与b之间的点乘结果
6.Vector3 c = Vector3.Lerp(Vector a, Vector b, float t):返回两个点之间的线性插值
7.Vector3 force = Vector3.Project(Vector3 a, Vector3 b):返回值为a在b上的投影向量
8.Vector3 force = Vector3.ProjectOnPlane(Vector3 a, Vector b):返回值为a在b对应过世界原点平面的投影
9.Vector3 result = Vector3.Reflect(Vector3 a, Vector3 b):返回值为a以b为法线反射出去的反射光线向量
Quaternion的一些常用方法:
1.Quaternion.Euler(Vector3 angle):以欧拉角构建四元数,使该四元数变化以该欧拉角旋转,该旋转以世界坐标为准旋转,返回该旋转
2.Quaternion.AngleAxis(float angle, Vector3 axis):该四元数变化绕着axis轴向旋转angle角度,返回该旋转
3.Quaternion.Angle(Quaternion a, Quaternion b):获得a和b两个四元数之间的角度
4.Quaternion.FromToRotation(Vector3 a, Vector3 b):返回从a旋转到b的相对旋转量
坐标系统
Unity中主要有四种坐标系:
1.全局坐标系: 即世界坐标系,整个场景的固定坐标,在游戏场景中表示每个物体的固定位置和方向;
**2.局部坐标系:**即物体坐标系,每个物体独立的坐标系,原点为模型轴心点,随着物体的旋转或者移动而改变,表现物体间的相对位置和方向;
**3.屏幕坐标系:**把屏幕看作一个坐标系,屏幕左下角是(0,0),右上角为屏幕的最大宽高。Z轴的坐标是相机的世界坐标中Z轴坐标的负值;
**4.视口坐标系:**视口坐标系跟屏幕坐标系相似,只不过将Game视图的屏幕坐标系单位化,左下角依旧是(0,0)。右上角变为(1,1),比较适合用比例来计算。
坐标系间也能相互转换,例如从局部坐标系到全局坐标系可以用transform.TransformPoint()方法,从全局坐标系到局部坐标系可以用transform.InverseTransformPoint()方法等。
虚拟轴
我们可以从Unity界面的Edit->Project Setting->Input Manager查看Unity已经设置好的虚拟轴
这里以Horizontal虚拟轴为例,其中Type值表示你的虚拟轴输入来源于什么,当前选项为Key or Mouse Button,即这个虚拟轴绑定的具体按键可以来源于鼠标按键或者键盘按键,Mouse Movement,则是指虚拟轴来源为鼠标移动。Axis则表示轴向,当前选项为X axis,意思是水平轴向。而每一个虚拟轴设置都是有正向和负向之分,其中Negative表示负向,Positive表示正向,Descriptive Name和Descriptive Negative Name分别是正负操作的语言描述,Positive Button和Alt Positive Button对应的就是正向的实际键盘对应键,负向同理。Sensitivity是变化速度,Gravity是复原速度,这个变化速度是指按钮值的变化速度,而复原速度即是指按钮值的复原速度,为了区别正向和负向,按钮都有一个值,在按钮不按的时候它为0,按下正向按键,它会逐渐变为1,负向则是-1,变化速度即是指从0到1或-1的变化速度,复原速度即是指从正向负向值变回为0的变化速度。Snap指正反按键都作用时,虚拟轴的值视为0,Invert指正反按钮发送的值取反。
虚拟轴获取
Input.GetButton(“虚拟轴名称”);
Input.GetButtonDown(“虚拟轴名称”);
Input.GetButtonUp(“虚拟轴名称”);
Input.GetAxis(“虚拟轴名称”);
Input.GetAxisRaw(“虚拟轴名称”);
前面三种方法可以通过虚拟轴名称获取虚拟轴并判断虚拟轴绑定的按键是否被按下,但无法判断正向和负向。后面两种方法获取虚拟轴,当你按下虚拟轴绑定的正向按键,他们会返回正值按下负向按键会返回负值,前者是会从0变化到1或-1,但不会瞬间变化,而后者会瞬间变化。
负向变化:
正向变化:
通过虚拟轴我们便可以实现一个简易的对象控制器了,其功能包括WASD控制对象移动以及鼠标控制对象朝向,具体实现代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
float alter_speed=1,move_speed=1;
// Start is called before the first frame update
void Start()
{
}
private void move()//鼠标控制镜头
{
float x,y;
x = Input.GetAxis("Mouse X");
y = Input.GetAxis("Mouse Y");//通过虚拟轴获得鼠标移动量
x *= alter_speed;
y *= alter_speed;
transform.Rotate(-y, 0, 0);//上下应该是自身坐标系
transform.Rotate(0, x, 0, Space.World);//左右必须是世界坐标系,因为当你抬头或者低头时,自身的Y轴就已经变了
}
private void MouseHide()//鼠标隐藏
{
if (!Input.GetKey(KeyCode.LeftCommand))
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
}
else
{
Cursor.visible = true;
Cursor.lockState = CursorLockMode.None;
}
}
private void MoveTest()//键盘WASD控制对象移动
{
//Debug.Log(Input.GetAxis("Horizontal"));
//Debug.Log(Input.GetAxis("Vertical"));
float x,y;
x = Input.GetAxis("Horizontal");//记录键盘的水平位移
y = Input.GetAxis("Vertical");//记录键盘的垂直位移
x *= move_speed*Time.fixedDeltaTime;
y *= move_speed*Time.fixedDeltaTime;
transform.Translate(x,0,y, Space.World);
}
void Update()
{
MouseHide();
move();
MoveTest();
}
}
这里我们以控制摄像头为例,为摄像头添加该脚本后,我们就可以实现第一人称移动和视角转换了,这里场景中有一个正方体和一个圆柱体,我们可以通过移动和视角变化实现不同视角的观察
但想要达到更为真实的效果,这个实例还是远远不够的,当摄像机靠近或远离时,物理并没有实现放大缩小;同时当摄像机移动到物体背面时,因为是以全局坐标系为准,WSAD不是相对意义上的上下左右运动了,该实例还存在一定的局限性。
预制件Prefab
如果为了在Unity中方便地添加实例,我们可以考虑使用预制件Prefab
预制件Prefab是一种资源类型,可以多次在场景进行实例,它有三个操作键。
优点:对预制件的修改,可以同步到所有实例,从而提高开发效率。
如果单独修改实例的属性值,则该值不再随预制件变化。
Select键:通过预制件实例选择对应预制件
Revert键:放弃实例属性值,还原预制件属性值
Apply键:将某实例的修改应用到所有实例
物理引擎
我们可以通过在Window->Package Manager里面下载ProBuilder工具来方便地构建几何物体和编辑
要认识unity的物理引擎,首先我们需要认识一下刚体
刚体Rigidbody
刚体是指在运动中和受力作用后,形状和大小不变,而且内部各点的相对位置不变的物体。
刚体组件有如下属性:
Mass (质量):设置物体的质量
Drag (阻力):设置物体移动时候受到的空气阻力
Angular Drag (角阻力):设置角阻力,旋转时受到的阻力
Use Gravity (使用重力):若激活,物体受重力影响
Is Kinematic (使用运动学):若激活,物体不再受物理引擎控制,而只能通过变换组件控制
Interpolate (插值):用于缓解刚体运动时的抖动
Collision Detection (碰撞检测):碰撞检测模式,快速移动的刚体在碰撞时有可能相互穿透,可以设置碰撞检测频率,但频率越大对物理引擎性能要求越大
Constraints (运动约束)
1.冻结位置 Freeze Position
:刚体在世界中沿X,Y,Z的移动将无效
2.冻结旋转 Freeze Rotation
:刚体在世界中沿X,Y,Z的旋转将无效
碰撞
两个物体对象产生碰撞需要满足以下条件:两个物体都带有碰撞器;运动的物体带有刚体。
碰撞的三个阶段:
当进入碰撞时(碰撞的第一帧)执行:OnCollisionEnter(Collision collOther)
当碰撞体与刚体接触时每帧执行:OnCollisionStay(Collision collOther)
当停止碰撞时(碰撞的最后一帧)执行:OnCollisionExit(Collision collOther)
触发器
带有碰撞器组件且Is Trigger被勾选的物体会成为触发器
触发器无碰撞效果,且触发器触发需要满足以下条件:两个物体都带有碰撞器;其中的一个物体带有刚体,另一个物体Is Trigger被勾选。
触发的三个阶段:
当物体进入触发器时执行`OnTriggerEnter(Collider collOther)
当物体与触发器接触时每帧执行:OnTriggerStay(Collider collOther)