简单浮力的模拟:
主要思路:
-
物体要能检测在水下还是水上 (简单物体直接通过transform.position.y-waterHeight来判断,复杂物体或一些体积较大的物体,我们可以在设置几个floaters来较好地模拟各个部分的情况,比如船体,我们可以在船头,船尾,船左侧和船右侧分别设置4个floaters来判断各个部分不同的入水体积)
-
模拟浮力(通过上一步的检测,我们可以知道物体目前的状态,然后对在水下的物体通过AddForce来施加一个持续的力使其向上运动,物体来到水面上就不再施加力,然后物体又因为重力重新返回水下,不断循环,船体可以到达上下漂浮的效果)
-
物体在不同状态下受到不同影响 (比如在水下会受到更大的阻力,而水上阻力会小一些,所以会有一个切换状态的函数)
using
System
.
Collections
;
using
System
.
Collections
.
Generic
;
using
UnityEngine
;
[
RequireComponent
(
typeof
(
Rigidbody
)
)
]
public
class
Buoyancy
:
MonoBehaviour
{
public
Transform
[
]
floaters
;
//用于存储一个物体身上的floater,简单物体则为本身,复杂物体则添加几个空物体
public
float
underwaterDrag
=
3f
;
public
float
underwaterAugularDrag
=
1f
;
public
float
airDrag
=
0f
;
public
float
airAugularDrag
=
0.05f
;
public
float
floatingPower
=
20f
;
private
Rigidbody
m_rigidbody
;
public
Transform
waterHeight
;
//水面的高度
private
bool
underwater
;
//是否在水下
private
int
underwaterNumber
=
0
;
//在水下的floaters个数
// Start is called before the first frame update
void
Start
(
)
{
m_rigidbody
=
GetComponent
<
Rigidbody
>
(
)
;
}
private
void
FixedUpdate
(
)
{
for
(
int
i
=
0
;
i
<
floaters
.
Length
;
i
++
)
{
float
diff
=
floaters
[
i
]
.
position
.
y
-
waterHeight
.
position
.
y
;
if
(
diff
<
0
)
{
m_rigidbody
.
AddForceAtPosition
(
Vector3
.
up
*
floatingPower
*
Mathf
.
Abs
(
diff
)
,
floaters
[
i
]
.
position
,
ForceMode
.
Force
)
;
/*ForceMode有四个枚举量:
①:Force(给物体一个持续的力并使用其质量)
②:Acceleration(给物体一个持续的加速度,采用默认质量即Mass不管设置为多少都为1)
③:Impulse(给物体添加一个瞬间的力并使用其质量)
④:VelocityChange(给物体瞬时加速度,忽略其质量)*/
underwaterNumber
++
;
if
(
!
underwater
)
{
underwater
=
true
;
SwitchState
(
true
)
;
}
}
}
if
(
underwater
&&
underwaterNumber
==
0
)
{
underwater
=
false
;
SwitchState
(
false
)
;
}
}
void
SwitchState
(
bool
isUnderwater
)
//用于切换状态
{
if
(
isUnderwater
)
{
m_rigidbody
.
drag
=
underwaterDrag
;
m_rigidbody
.
angularDrag
=
underwaterAugularDrag
;
}
else
{
m_rigidbody
.
drag
=
airDrag
;
m_rigidbody
.
angularDrag
=
airAugularDrag
;
}
}
}
将此脚本挂载到需要漂浮的物体上,设置相关参数。下面是我的设置(仅做参考)

对Floaters数组的说明,像一个Cube是一个简单物体,将本身拖入Floaters数组即可,对于船体,较复杂,可以添加几个空物体来当做floaters,如下图:4个floaters,分别在船头,船尾,船的左侧和右侧

另外,floaters的位置即为船体在水面漂浮的位置,不宜设置过高或过低。
效果图:

可以看到,随着玩家的重量也会影响到船体的漂浮,较好地模拟的现实里的船体。