Godot 4 中类似 F-Zero-X 的运动,CharacterBody 位于圆柱体表面(3D)

问题描述 投票:0回答:1

我正在尝试创建一个玩家可以移动的角色Body3D,我希望它能够像 F-zero-X 中那样围绕圆柱体旋转。有人已经在使用刚体时解决了这个问题,您可以在其中施加相对力,帮助旋转玩家:

像 F-Zero GX 一样在管道内移动

我想使用 characterBody3D 来复制它并计算其旋转而不是使用力。因此,我按照上一篇文章中的建议,在我的角色身体周围添加了 3 个光线投射。

enter image description here

区别在于,由于我使用的是角色主体而不是刚体,所以我无法使用力来旋转它...因此我计算了 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多少,对吧?但是,我不确定如何做到这一点,或者这是否可以解决问题。请帮忙?

3d rotation game-physics godot godot4
1个回答
0
投票

所以我想出了怎么做。我在船的前部、后部、右侧和左侧使用了 4 个均匀分布的光线投射,而不是 3 个。

enter image description here然后我根据碰撞距离计算了船舶在 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)
© www.soinside.com 2019 - 2024. All rights reserved.