U1L13-5——物理系统之刚体加力

刚体加力

由于刚体组件会接管附加到的游戏对象的运动,因此不应试图借助脚本通过更改变换属性(如位置和旋转)来移动游戏对象。相反,应该施加__力__来推动游戏对象并让物理引擎计算结果

给刚体加力的目标就是:让其有一个速度 使其朝向某一个方向移动

本章代码关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
this.GetComponent<Rigidbody>()    //获取刚体组件
rigidBody.AddForce() //相对世界坐标 添加力
rigidBody.AddRelativeForce() //相对本地坐标 添加力
rigidBody.AddTorque() //相对世界坐标 添加扭矩力让其旋转
rigidBody.AddRelativeTorque() //相对本地坐标 添加扭矩力让其旋转
rigidBody.velocity //直接改变速度 速度方向是相对于世界坐标系
rigidBody.AddExplosionForce() //模拟爆炸效果 只对挂载的脚本有这句语句的对象才有用
rigidBody.AddForceAtPosition() //对物体特定的点施加力
ForceMode.Acceleration //给物体添加一个持续的加速度,忽略质量 默认为1
ForceMode.Force //给物体添加一个持续的力,与物体的质量有关
ForceMode.Impulse //给物体添加一个瞬间的力,与物体的质量有关 忽略时间 默认为1
ForceMode.VelocityCharge //给物体添加一个瞬时速度,忽略质量和时间都默认为1
rigidBody.IsSleeping() //判断刚体是否在休眠的方法
rigidBody.WakeUp() //唤醒刚体的方法

添加力

首先,添加力之前一定要获取刚体组件.GetComponent<>()​

1
rigidBody = this.GetComponent<Rigidbody>();

注意!加力过后 对象是否停止移动 是由阻力决定的,如果阻力为0 那给了一个力之后 对象始终不会停止运动

如果希望即使有阻力 对象也能一直动,那就一直给“推”它(加力)就行了

1
2
3
4
5
void Update()
{
//如果希望即使有阻力 对象也能一直动,那就一直给“推”它(加力)就行了
rigidBody.AddForce(Vector3.forward * 10);
}

相对世界坐标加力

1
2
3
4
5
//加力过后 对象是否停止移动 是由阻力决定的
//如果阻力为0 那给了一个力之后 始终 不会停止运动
rigidBody.AddForce(Vector3.forward * 10); //这是相对于世界坐标系坐标轴的移动!
//如果想要在 世界坐标系方法中 让对象 相对于自己的面朝向动
rigidBody.AddForce(this.transform.forward * 10);

相对于本地坐标加力

1
rigidBody.AddRelativeForce(Vector3.forward * 10);   //至少相对于自己的坐标系的移动!

添加扭矩力

添加扭矩力 让其旋转,加力过后 对象是否停止移动 是由扭矩阻力决定的

相对世界坐标

1
2
3
//相对世界坐标
//加力过后 对象是否停止移动 是由扭矩阻力决定的
rigidBody.AddTorque(Vector3.up * 10);

相对本地坐标

1
2
//相对本地坐标
rigidBody.AddRelativeTorque(Vector3.up * 10);

直接改变速度

注意!如果要直接通过改变速度,这个速度方向 是相对于 世界坐标系的!!!

1
rigidBody.velocity = Vector3.forward * 5;   //这个速度相对于世界坐标系!!!

模拟爆炸效果

模拟爆炸的里 一定是 所有希望受到爆炸效果影响的对象 都需要得到它们的刚体 来执行这个方法才能都有效果
也就是说每个希望受到爆炸影响的刚体都需要执行该方法才能看到爆炸效果!!!

1
2
rigidBody.AddExplosionForce(10, Vector3.zero, 10);  //第一个参数 爆炸的力,第二个参数 爆炸中心坐标,第三个 爆炸半径
//注意!!!这一句只对挂载的脚本有这句语句的对象才有用!!!没有这句语句的刚体不受影响

对物体特定的点施加力

一般对物体施加力都是对中心点加力,但是以下语句可以对物体特定的点位置施加力

1
rigidBody.AddForceAtPosition(Vector3.forward * 10, new Vector3(0, 0, 0));

力的几种模式

大部分加力的参数还重载了一个力的模式
主要的作用 就是 计算方式不同而已
由于4中计算方式的不同 最终的移动速度就会不同

1
rigidBody.AddForce(Vector3.forward * 10, ForceMode.Acceleration); //加速度模式

动量定理

Ft=mvFt=mv

v=Ftmv=\frac{Ft}{m}

FF:力、tt:时间、mm:质量、vv:速度

加速度(Acceleration)

给物体添加一个持续的加速度,而忽略其质量

v=Ftv=Ft

t:0.02s(取决于物理帧更新时间)
F:(0,0,10)
m:被忽略,默认为1
v=100.02=0.2m/sv = 10*0.02 = 0.2m/s
每物理帧移动0.2m/s*0.02 = 0.004m

1
rigidBody.AddForce(Vector3.forward * 10, ForceMode.Acceleration); //加速度模式

持续的力(Force)

给物体添加一个瞬间的力,与物体的质量有关

v=Ftmv=\frac{Ft}{m}

F:(0,0,10)
t:0.02s
m:2kg
v=100.022=0.1m/sv = 10 * \frac{0.02}{2} = 0.1m/s
每物理帧移动0.1m/s*0.02 = 0.002m

1
rigidBody.AddForce(Vector3.forward * 10, ForceMode.Force);    //持续力模式

瞬间的力(Impulse)

给物体添加一个瞬间的力,与物体的质量有关 忽略时间 默认为1

v=Fmv=\frac{F}{m}

F:(0,0,10)
t:被忽略,默认为1
m:2kg
v=1012=5m/sv = 10*\frac{1}{2} = 5m/s
每物理帧移动5m/s*0.02 = 0.1m

1
rigidBody.AddForce(Vector3.forward * 10, ForceMode.Impulse);    //瞬间力模式

瞬时速度(VelocityChange)

给物体添加一个瞬时速度,忽略质量与时间,全部默认为1

v=Fv=F

F:(0,0,10)
t:被忽略,默认为1
m:被忽略,默认为1
v=10v = 10
每物理帧移动10m/s*0.02 = 0.2m

1
rigidBody.AddForce(Vector3.forward * 10, ForceMode.VelocityChange);    //瞬时速度模式

力场脚本(Constant Force)

可以直接在该组件内给予该对象一个持续的力,而无需写代码,填写方法参考添加力的写法即可

image

注意!添加该脚本时,若没有rigidbody组件会自动添加rigidbody脚本

刚体的唤醒

Unity为了节约性能,有时会让刚体在一定情况下休眠,这可能会导致一些错误的现象(例如旋转一个方块刚体的所在的地面,但方块卡在原地)
详细原因参考刚体睡眠,可以通过脚本让刚体不会处于休眠状态

1
2
3
4
5
6
//判断刚体是否在休眠的方法
if (rigidBody.IsSleeping())
{
//唤醒刚体的方法
rigidBody.WakeUp();
}