一、修改物理材质
Unity对物体表面材料的性质做了件化处理,仅有5种常用属性:
- Dynamic Friction(动态摩擦系数)
- Static Friction(静态摩擦系数)
- Bounciness(弹性系数)
- Friction Combine(摩擦力系数算法)
- Bounce Combine(弹性系数算法)
物理材质是配合碰撞体使用的。碰撞体有一个Material属性,将创建好的物理材质拖拽到该属性上即可指定该属性。
不指定任何物理材质时,碰撞体具有默认的物理材质。
二、FixedUpdate
物理更新,保证稳定的时间间隔(默认0.02s,可以通过Edit->Project Settings->Time来修改)。
物理系统对于时间是非常敏感的。举一个例子:发射子弹,0.1秒后几种物体。假如更新频率不稳定,子弹接触物体时没有及时检测,再晚0.02秒,子弹已经穿过了物体。这样子弹就错过了碰撞的时机,导致后续结果完全不同。
按理说刷新频率应该是越高越好,但综合考虑机器负担和性能后,决定50帧是最合理的选择。
所有的物理系统处理都会在引擎循环中的一个专门环节上完成,从而保证更新频率的稳定。
特殊机制:
如果说设备卡了一下,物理更新还能保证更新频率吗?
答案是有办法间接保证这一点。简单来说,游戏世界的时间是一个虚拟的概念,一定程度上可以人为控制。如果在T时刻,卡了0.06秒,正好错过了三个周期,那么在下一次不卡的时候,FixedUpdate函数会补上之前错过的三次,连续执行4次,而且还会"假装"这4次的调用时间点分别是T+0.02,T+0.04,T+0.06T+0.08.通过这样的机制,就能保证无论硬件运行是否稳定,游戏都能保证"稳定"的物理更新,避免出现奇怪的结果。作为对比,Update就没有这个特性。
三、修改角速度
与修改刚体速度类似,代码如下
Rigid.angularVelocity=new Vector3(0,60,0);
刚体的angularVelocity属性的数据类型为Vector3,代表x、y、z轴的旋转速度,单位时弧度/s,也就是说3.14代表每秒半圈。
由于具有角阻尼(Angular Drag),因此即便没有接触其他物体,旋转也会慢慢停下来。
四、质心
拼接一个简单的模型,使用物理系统调整其重心就可以只做一个不倒翁。代码如下
Rigidbody rigid;
rigid=GetComponent<Rigidbody>();
//设置centerOfMass就可以指定重心了
rigid.centerOfMass=new Vector3(0,-1,0);
游戏物体的重心不受真实世界的限制,不但可以设置在物体的任意位置,而且还可以超出物体本身的范围。
对物体施加力时,力的位置不同,效果也就不同。严格来说,对一个不受任何力的物体(在Unity里就是去掉了重力,也不与其他物体接触的刚体),如果手里的方向通过了该物体的质心,物体就不会获得角速度。如果力的方向错过了质心,那么物体就会有旋转的趋势。质心到受力线的距离越远,旋转的趋势就越强
五、更多施加力的方式
力的位置很重要,但前文提到的AddForce却没有位置参数。可以猜想,AddForce函数施加力时,就是从物体的质心位置施加的。
如果要模拟更复杂的情况,可以使用以下函数:
void AddForceAtPosition(Vector3 force,Vector3 position);
void AddForceAtPosition(Vector3 force,Vector3 position,ForceMode mode);
第二个参数为施加力的位置,以世界坐标表示,因此使用时可能需要转换坐标。
第三个参数为力的模式,是一个枚举类型,定义如下:
public enum ForceMode
{
//默认方式为持续施加力
Force=0,
//设置为瞬间博发力,适合表现快速猛烈的力,如爆炸
//力的持续时间有区别
Impulse=1,
//瞬时改变刚体速度,不考虑质量
VelocityChange=2,
//直接改变加速度,不考虑质量
Acceleration=5
也就是说,施加力的时候,可以通过改变参数mode来让施加力的含义发生变化。前两种比较常用,第三种完全可以用直接修改刚体速度的velocity属性代替
六、刚体约束
在Rigidbody中,有一个Constraints,可以锁定xyz轴的移动与旋转。根据需要锁定一些自由度,可以让刚体的行为更加可控。
也可以用脚本控制冻结:
rigid.constraints=RigidbodyConstraints.FreezeAll;//冻结所有移动和旋转
rigid.constraints=RigidbodyConstraints.FreezePositionX;//冻结x轴的位移,取消所有其它约束
rigid.constraints=RigidbodyConstraints.FreezeRotation;//冻结所有旋转,取消位移约束
rigid.constraints=RigidbodyConstraints.FreezeRotationX|RigidbodyConstraints.FreezeRotationZ|RigidbodyConstraints.FreezePositionY;//冻结x和z轴旋转,冻结y轴位移