在没有角色控制器的 Unity 中跳球

发布于 2024-10-26 11:15:55 字数 75 浏览 11 评论 0原文

我想知道如何在 Unity 中不使用角色控制器使球跳跃。球需要有一个用于重力的刚体和一个脚本以使其沿着球的相对方向跳跃。有人可以帮忙吗?

I would like to know how to make a ball jump in Unity without using a character controller. The ball needs to have a rigidbody for the gravity and a script to make it jump in the relative orientation of the ball. Can somebody help please.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

╄→承喏 2024-11-02 11:15:55

正如 skovacs1 在 Unity Answers 中所述 :

简单的答案是调整 inAirControlAcceleration 的值并
它应该给你一些更像你想象的东西。为了更多
控制,您还可以替换复合赋值
movement.inAirVelocity

movement.inAirVelocity +=
    运动.方向 * 时间.deltaTime *
    运动.inAirControl加速度 

使该值按比例缩放
h的输入量。

如果这仍然没有让你得到你想要的,假设你是
使用链接的确切脚本(因为您没有发布其他任何内容),
这是更新中相关功能代码的作用:

//按照UpdateSmoothedMovementDirection *速度计算水平移动
//+垂直按ApplyGravity或ApplyJumping中计算的速度
//+水平+垂直由ApplyJumping中计算的inAirMovement
//+水平方向通过inAirMovement的调整来计算
//更新平滑运动方向 
var currentMovementOffset = 运动方向 * 运动速度
                            + Vector3(0,运动.垂直速度,0)
                            + 运动.inAirVelocity;
currentMovementOffset *= Time.deltaTime;
move.collisionFlags =controller.Move(currentMovementOffset);

你似乎只关心水平运动,所以唯一的
你真正需要关心的变量是movement.direction,
运动.速度和运动.inAirVelocity。

完成工作的部分:

function UpdateSmoothedMovementDirection() { // 由 Update 每帧调用
    //...不相关的东西
    //移动方向*始终*(canControl 在此脚本中从未更改)
    //绝对水平输入大于0.1时的水平输入
    if (movement.isMoving) Movement.direction = Vector3(h, 0, 0);

    //仅计算地面时的速度变化
    if (controller.isGrounded) {
        var curSmooth = moving.speedSmoothing * Time.deltaTime;
        var targetSpeed = Mathf.Min (Mathf.Abs(h), 1.0);
        if(Input.GetButton("Fire2") && canControl)
            目标速度 *= 运动.runSpeed;
        别的
            目标速度 *= 运动.walkSpeed;

        运动.速度 = Mathf.Lerp (运动.速度, targetSpeed, curSmooth);
        //...不相关的东西
    }
    //inAirVelocity将通过Time.deltaTime水平调整
    //水平输入方向
    别的 {
        //...不相关的东西
        if (运动.isMoving)
            move.inAirVelocity += Vector3(Mathf.Sign(h),0,0) * Time.deltaTime
                                      * 运动.inAirControl加速;
    }
}

设置初始inAirVelocity的部分:

function ApplyJumping() { //由每帧更新调用
    //...不相关的东西
    //当在地面上并且我们可以跳跃时,inAirVelocity将为 
    //我们所在平台的运动
    if (controller.isGrounded) {
        if (jump.enabled && Time.time < Jump.lastButtonTime + Jump.timeout) {
            //...不相关的东西
            move.inAirVelocity = lastPlatformVelocity;
            //...不相关的东西
        }
    }
}

可能出乎您意料的是您只是计算
在地面时的速度。

一旦在空中,你就会以一定的速度移动
当您在输入中最后一次到达地面时您正在移动
方向 (movement.direction) + 受输入影响的一些调整
方向(inAirVelocity)。

我认为这应该模拟
不知怎的,惯性,但它确实不是那样工作的,因为你可以
仍然改变方向并且没有减速。

为了获得正确的惯性方向,您需要移动
将 move.direction 更改为 if(Controller.isGrounded)
接下来。要获得实际的惯性减速度,您可以
以某种平滑率从 else 语句中的速度中减去,直到
它是 0 并将 lastPlatformVelocityinAirVelocity 分开,
将其添加为一个单独的术语并使其减速。

为了在空中进行全速控制,我建议您移动
加快 if 块的速度(在这种情况下,inAirVelocity 可能不会
需要在 UpdateSmoothedMovementDirection 中进行更改)。

或者,
您可以更改跳跃时用于计算移动的内容
做类似的事情

if(!controller.isGrounded) Movement.speed = inAirSpeed;

但这会导致一些不自然的行为,并且你
可能需要在空中进行一些调整。

As skovacs1 states on Unity Answers:

The simple answer is to tune the value of inAirControlAcceleration and
it should give you something more like what you imagine. For even more
control, you could also replace the compound assignment of
movement.inAirVelocity with

movement.inAirVelocity +=
    movement.direction * Time.deltaTime *
    movement.inAirControlAcceleration 

so that the value is scaled by the
amount of input of h.

If that still doesn't get you what you want, assuming that you are
using the exact script linked (because you didn't post anything else),
here's what the relevant functional code in Update here does:

//move horizontally as calculated in UpdateSmoothedMovementDirection * speed
//+ vertically by the speed calculated in ApplyGravity or ApplyJumping
//+ horizontally + vertically by the inAirMovement calculated in ApplyJumping
//+ horizontally by the adjustment to inAirMovement calculated in
//UpdateSmoothedMovementDirection 
var currentMovementOffset = movement.direction * movement.speed
                            + Vector3(0,movement.verticalSpeed,0)
                            + movement.inAirVelocity;
currentMovementOffset *= Time.deltaTime;
movement.collisionFlags = controller.Move (currentMovementOffset);

All you seem to care about is the horizontal movement, so the only
variables you actually need to care about are movement.direction,
movement.speed and movement.inAirVelocity.

The part that does the work:

function UpdateSmoothedMovementDirection() { //called by Update every frame
    //...irrelevant stuff
    //move direction is *always* (canControl is never changed in this script)
    //the horizontal input when the absolute horizontal input is greater than 0.1
    if (movement.isMoving) movement.direction = Vector3 (h, 0, 0);

    //calculate the speed change only when on the ground
    if (controller.isGrounded) {
        var curSmooth = movement.speedSmoothing * Time.deltaTime;
        var targetSpeed = Mathf.Min (Mathf.Abs(h), 1.0);
        if(Input.GetButton("Fire2") && canControl)
            targetSpeed *= movement.runSpeed;
        else
            targetSpeed *= movement.walkSpeed;

        movement.speed = Mathf.Lerp (movement.speed, targetSpeed, curSmooth);
        //...irrelevant stuff
    }
    //inAirVelocity is going to be adjusted horizontally by Time.deltaTime
    //in the direction of horizontal input
    else {
        //...irrelevant stuff
        if (movement.isMoving)
            movement.inAirVelocity += Vector3(Mathf.Sign(h),0,0) * Time.deltaTime
                                      * movement.inAirControlAcceleration;
    }
}

The part that sets initial inAirVelocity:

function ApplyJumping() { //called by Update every frame
    //...irrelevant stuff
    //When on the ground and we can jump, the inAirVelocity will be 
    //the motion of the platform we're on
    if (controller.isGrounded) {
        if (jump.enabled && Time.time < jump.lastButtonTime + jump.timeout) {
            //...irrelevant stuff
            movement.inAirVelocity = lastPlatformVelocity;
            //...irrelevant stuff
        }
    }
}

What's probably not what you expect is that you only ever calculate
the speed when on the ground.

Once in the air, you move at the speed
you were moving when you were last on the ground in the input
direction (movement.direction) + some adjustment affected by the input
direction (inAirVelocity).

I assume this is supposed to simulate
inertia somehow, but it really doesn't work that way because you can
change direction still and there's no deceleration.

To get proper direction on the inertia, you would need to move the
change to movement.direction into the if(Controller.isGrounded) block
which follows. To get the actual inertial deceleration, you would
subtract from speed in the else statement at some smoothing rate until
it is 0 and keep the lastPlatformVelocity separate from inAirVelocity,
add that as a separate term and decelerate it as well.

To give full speed control while in the air, I recommend you move the
speed stuff out of that if block (in which case, inAirVelocity may not
need to be changed in UpdateSmoothedMovementDirection).

Alternatively,
you can change what you use to calculate movement when jumping by
doing something like

if(!controller.isGrounded) movement.speed = inAirSpeed;

but this will result in some unnatural behaviour and you
will likely need to do some tuning in the air.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文