Unity笔记-11-物理引擎
刚体(Rigidbody)
Mass (质量)
设置物体的质量
Drag (阻力)
设置物体移动时候受到的空气阻力
Angular Drag (角阻力)
设置角阻力,旋转时受到的阻力
Use Gravity (使用重力)
若激活,物体受重力影响
Is Kinematic (使用运动学)
若激活物体不再受物理引擎控制,而只能通过变换组件控制,也就是说虽然能被物理引擎检测到,但是不会受到反作用力的影响
这里注意理解,以下面的场景为例,三个球体
其中,第一个球体Is Kinematic勾选,第二个不勾选,第三个没有刚体但是有碰撞器,三个球体重力都不勾选
调试的时候会发现,第一个球体去碰撞第二个球体会将第二个球体撞出去,但是自身不动,同样,第二个球体去撞第一个球体是无法使其发生位移的。第二个球体去撞第三个球体,不会使其发生位移,因为第三个球体无刚体,只有碰撞器,第三个球体主动碰撞无效,发生穿模,因为它没有刚体,物理引擎无法检测它的主动碰撞
Interpolate (插值)
用于缓解刚体运动时的抖动
无(None )
内插值(Interpolate )-- 基于上一帧的变化来平滑本帧的变换
外插值(Extrapolate )-- 基于下一帧的预估变换来平滑本帧变换
Collision Detection (碰撞检测)
碰撞检测模式,快速移动的刚体在碰撞时有可能相互穿透,可以设置碰撞检测频率,但频率越大对物理引擎性能要求越大
不连续Discrete :不连续碰撞检测,适用于普通碰撞(默认)
连续Continuous :连续碰撞检测
动态连续 Continuous Dynamic :连续动态碰撞检测,适用于高速物体
Constraints (运动约束)
冻结位置 Freeze Position :刚体在世界中沿X,Y,Z的移动将无效
冻结旋转 Freeze Rotation :刚体世界中沿X,Y,Z的旋转将无效
碰撞器(Collider)
面数越少的碰撞器性能消耗越少,正方体碰撞器是性能消耗最少的,注意,Mesh Collider 碰撞器能根据物体本身创造一样的碰撞器,效果十分逼真,但是对性能消耗极大,不建议使用,勾选Convex属性会连接部分面使得面数减少,性能消耗降低
物体碰撞条件
- 两个物体都带有碰撞器
- 运动的物体带有刚体,也就是说不带刚体的物体主动运动,即使都有碰撞器也无法发生碰撞
碰撞的三个阶段
- 当进入碰撞时(碰撞的第一帧)执行:
OnCollisionEnter(Collision collOther) - 当碰撞体与刚体接触时每帧执行:
OnCollisionStay(Collision collOther) - 当停止碰撞时(碰撞的最后一帧)执行:
OnCollisionExit(Collision collOther)
请注意:通过这里的参数Collision collOther 可以获得碰撞组件,具体代码collOther.collier
也就是说,挂着这个脚本的物体碰撞到其他物体的时候,会通过碰撞其他物体拿到其他物体的碰撞组件,如此一来就能通过碰撞组件拿到这个物体的其他全部组件
这里需要展开说一下 collOther 可以获取接触点,具体代码: ContactPoint cp = collOther.contacts[index] 根据索引获得接触点,索引为0 也就是第一个接触点
cp.point 可以获得接触点的世界坐标
cp.normal 可以获得接触面的法线
触发器
带有碰撞器组件,且Is Trigger 属性被勾选的物体
现象:无碰撞效果
注意:如果被认定为触发器,那么这个物体就无法发成碰撞,一切与碰撞有关的功能都会失效
触发条件
两者具有碰撞器
其中之一带有刚体
其中之一勾选Is Trigger
注意这里是其一,也就是两个物体任意一个有就可以触发,和碰撞不一样,即使运动的物体没有刚体,但只要有勾选了
Is Trigger 的碰撞器也能达成触发条件,并不是和碰撞条件一样一定要运动的物体带刚体
触发的三个阶段
- 当物体进入触发器时执行:
OnTriggerEnter(Collider collOther) - 当物体与触发器接触时每帧执行:
OnTriggerStay(Collider collOther) - 当停止触发是执行:
OnTriggerExit(Collider collOther)
注意:这里的参数collOther 就是被触发物体的碰撞器组件,可以通过它拿到被触发物体的全部组件
注意点
触发和碰撞时可以同时存在的,也就是说一个物体可以有两个碰撞器组件,将其中一个碰撞器的Is Trigger 勾选,就能够同时有触发器和碰撞器,通过调整触发器或者碰撞器的范围可以达到:先触发后碰撞,反之同理。先后取决于触发器和碰撞器的大小,谁先接触被碰撞或被触发物体的碰撞器
其次,如果物体移动速度过快,那么碰撞器或是触发器将检测不到物体发生碰撞或者触发,碰撞检测失效
为了解决这个问题,于是采用射线检测
具体代码
private void Start()
{
RaycastHit hit;
//Raycast(起点,方向,受击物体信息,距离,层)
if (Physics.Raycast(this.transform.position,this.transform.up,out hit,100,mask))
{
//检测到了
targetPos = hit.point;
}
else
{
targetPos = transform.position + transform.up * 100;
}
}
private void Update()
{
this.transform.position = Vector3.MoveTowards(transform.position, targetPos, Time.deltaTime * speed);
if ((transform.position - targetPos).sqrMagnitude < 0.1f)
{
Debug.Log("Touch It");
Destroy(this.gameObject);
}
}
说明:Physics.Raycast方法会按照参数向此方向发射对应长度的射线,如果检测到物体,那么将该物体信息输出到参数hit 中,在让子弹直接飞往这个物体的坐标即可,如果没有检测到那么久飞一定距离消失。
这样就会避免因为速度过快导致无法触发或者碰撞的问题了
|