按照正常情况游戏中角色在上坡爬坡的时候速度应该减慢,可是角色控制器组件没有帮我们做这个判断,刚好最近工作中需要做这个功能,我就用勾股定理的法则来解决这个问题。如下图所示,当角色在爬坡的时候,角色控制器默认行走的距离就是 “C” 。但是如果行走的距离是“C” 你会发现上坡的速度太快了。这里我们需要计算”b”,让角色在上坡时候一次移动的距离是”b”这样移动就很正常了。
按照勾股定理的法则, c二次方 = a二次方 + b二次方。已知 c 和 a 我们求的b的距离即可。
第一步:主角目前所在地形的3D坐标,以及主角面朝方向行走“一段距离”后的3D坐标。 “一段距离” 我这里使用他的行走速度也就是1秒行走的长度。
第二步:把部分代码添加入角色控制器组件。
默认角色控制器行走是走路,简单改一下让他跑步。找到UpdateSmoothedMovementDirection ()方法,加入“|isMoving” 这个判断条件。
1
|
if
(
Input
.
GetKey
(
KeyCode
.
LeftShift
)
|
Input
.
GetKey
(
KeyCode
.
RightShift
)
|
isMoving
)
|
然后找到Update()方法,(C#和js都可以编译通过下面这段代码)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
// Apply jumping logic
ApplyJumping
(
)
;
//-------------开始插入代码 -------------
//当主角处于移动状态时开始计算主角目前坐标以及1秒后坐标
if
(
IsMoving
(
)
)
{
//得到主角行走1秒后所在位置地形的坐标
var
newPos
=
transform
.
position
+
(
transform
.
rotation
*
Vector3
.
forward
*
moveSpeed
)
;
newPos
.
y
=
Terrain
.
activeTerrain
.
SampleHeight
(
newPos
)
;
//得到主角当前位置所在地形的坐标
var
heropos
=
transform
.
position
;
heropos
.
y
=
Terrain
.
activeTerrain
.
SampleHeight
(
transform
.
position
)
;
//绘制一条Debug的线段,在编辑器中看的更清楚。
Debug
.
DrawLine
(
heropos
,
newPos
,
Color
.
red
)
;
//斜边的长度
var
c
=
moveSpeed
;
//短直角边的长度
var
b
=
newPos
.
y
-
heropos
.
y
;
//b >0 标示主角在爬坡 b < 0 表示主角在下坡
if
(
b
>
0
)
{
// 根据公式计算 a = 根号下 c二次方 - b二次方
var
a
=
Mathf
.
Sqrt
(
Mathf
.
Pow
(
c
,
2
)
-
Mathf
.
Pow
(
b
,
2
)
)
;
moveSpeed
=
a
;
}
}
//-------------结束插入代码 -------------
// Calculate actual motion
Vector3
movement
=
moveDirection
*
moveSpeed
+
new
Vector3
(
0
,
verticalSpeed
,
0
)
+
inAirVelocity
;
movement
*=
Time
.
deltaTime
;
|
直接运行游戏,你会发现当你在爬坡的时候主角的移动速度会减少,下坡与平地的时候移动速度正常。
另外还有一个地方需要注意下。 使用角色控制器时如果你的坡度角度过于大,你会发现你的主角无法继续爬坡。如下图所示,默认坡度角度为45。如果你需要爬坡更高的角度,直接修改Slope Limit数值即可。
当然代码中我们也可以控制角色是否可以继续爬坡,根据上述代码两点Y坐标的插值也可以判断。
1
|
float
xx
=
newPos
.
y
-
heropos
.
y
;
|
接着,如果你的项目中没有使用地形元素,而是用美术建模形成的地形话,那么就需要通过射线来取得“地形”上的两个点。如下图所示。
白色射线:得到主角面朝方向一步以后的地形坐标。
蓝色线段:主角移动的起点和终点的线段。
红色射线:处理摄像机(与本章无关)
在地形之上,我们使用下面这个方法得到地形的高度。
1
|
Terrain
.
activeTerrain
.
SampleHeight
(
)
|
如果项目中的地形是美术做的话,需要用射线的方式来计算。代码比较简单我就不用注释了, 就是上图中的那个白色射线,从天上射向地面。参数是模型面前下一步的将要行走的坐标,然后通过射线换算成实际Y轴高度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public
static
float
SampleHeight
(
Vector3
point
)
{
var
sample
=
point
;
sample
.
y
+=
20
;
Ray
ray
=
new
Ray
(
sample
,
Vector3
.
down
)
;
RaycastHit
hit
;
if
(
Physics
.
Raycast
(
ray
,
out
hit
)
)
{
if
(
hit
.
collider
.
gameObject
.
tag
!=
"Terrain"
)
{
Debug
.
DrawLine
(
sample
,
hit
.
point
)
;
return
hit
.
point
.
y
;
}
}
return
-
1
;
}
|
剩下的地方就和上面的代码差不多了。如果你的项目中没有使用角色控制器,用别的方式来实现移动效果,也可以使用这样的方法,总是就是勾股定理了。
最后是本文的内容的下载地址,这样看起来原理就清晰很多。欢迎留言给我,大家互相学习与进步,哇咔咔。
http://vdisk.weibo.com/s/r1xrb