我正在尝试创建一个玩家可以移动的角色Body3D,我希望它能够像 F-zero-X 中那样围绕圆柱体旋转。有人已经在使用刚体时解决了这个问题,您可以在其中施加相对力,帮助旋转玩家:
我想使用 characterBody3D 来复制它并计算其旋转而不是使用力。因此,我按照上一篇文章中的建议,在我的角色身体周围添加了 3 个光线投射。
区别在于,由于我使用的是角色主体而不是刚体,所以我无法使用力来旋转它...因此我计算了 3 个光线投射碰撞的平均法线,并按到碰撞点的距离进行加权:
var distanceA = Raycast1.get_collision_point().distance_to(Raycast1.global_position)
var distanceB = Raycast2.get_collision_point().distance_to(Raycast2.global_position)
var distanceC = Raycast3.get_collision_point().distance_to(Raycast3.global_position)
var TargetNormal= (1/distanceA * Raycast1.get_collision_normal() + 1/distanceB *Raycast2.get_collision_normal() + 1/distanceC * Raycast3.get_collision_normal()).normalized()
问题是我不知道从这里该去哪里。如果我将characterBody的basis.y与TargetNormal进行比较,我应该知道每个刻度要旋转我的characterBody多少,对吧?但是,我不确定如何做到这一点,或者这是否可以解决问题。请帮忙?
所以我想出了怎么做。我在船的前部、后部、右侧和左侧使用了 4 个均匀分布的光线投射,而不是 3 个。
然后我根据碰撞距离计算了船舶在 x 轴(前后光线投射)和 z(左右光线投射)上的旋转。我还创建了一些“重力”来将船拉向轨道。考虑到我的船将以非常高的速度移动,所以我使用非常高的重力来使其保持在轨道上,对于正常重力,您可能希望它接近 9。这是重力的代码(仅使用前部和后部)光线投射):
var distanceFront = RaycastFront.get_collision_point().distance_to(RaycastFront.global_position)
var distanceBack = RaycastBack.get_collision_point().distance_to(RaycastBack.global_position)
var upwardsForce = -16
var alldistancesAccomplished : bool = true
if distanceFront < .8:
upwardsForce += 4 /distanceFront
else:
alldistancesAccomplished = false
#this is
upwardsForce -= 32
if distanceBack < .8:
upwardsForce += 4 /distanceBack
else:
alldistancesAccomplished = false
upwardsForce -= 8
if upwardsForce > 0 and alldistancesAccomplished:
upwardsForce = -velocity.dot(basis.y)/delta
velocity += (upwardsForce * delta * basis.y)
upwardsForce 变量充当轨道的引力/磁力,也有助于将身体悬浮在地面上,但如果你不添加最后一个 if,它会在你的磁场限制内永远上下摆动。如果这是您想要的,您可以删除该行。这里是沿 x 轴旋转的代码(使用前后光线投射),但 z 轴将使用相同的原理:
var angleAcrossX : float = 0
var rotation_stength = PI/8
if abs(distanceFront - distanceBack) > 0.001:
if distanceFront < 1:
angleAcrossX += (1-distanceFront) * rotation_stength
if distanceBack < 1:
angleAcrossX += (1-distanceBack) * (-rotation_stength)
angleAcrossX = angleAcrossX
transform.basis = transform.basis.rotated(basis.x,angleAcrossX)