Unity物理系统脚本编程(下)

一、修改物理材质

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();

//设置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轴位移

 

你可能感兴趣的:(Unity脚本,unity,游戏引擎)