使用数学公式定义玩家速度 [英] Using a mathematical formula to define player speed

查看:121
本文介绍了使用数学公式定义玩家速度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一个简单的游戏,在该游戏中,通过加力来移动玩家.但是,我不希望他的加速度保持恒定-我希望它根据当前速度变化.我制作了简单的加速脚本来执行此操作,但是并没有达到预期的效果:

I'm making simple game in which the player is moved by adding force to him. However, I don't want his acceleration to be constant - I want it to vary depending on the current speed. I made simple acceleration script to do this but it doesn't achieve the desired effect:

float acceleration
{
    get { return speed/inversedAcceleration; }
}

void FixedUpdate () {
    rb.AddForce(transform.forward * speed);
    if (speed < maxSpeed)
        speed += acceleration * Time.deltaTime;    
}

我也尝试过的新方法:

float timer = 1.0f;

public float velocity { get { return Mathf.Sqrt(timer)*10; } }

void FixedUpdate()
{
    timer += Time.deltaTime;
    rb.AddForce(transform.forward * velocity);
}

该逻辑有点令人费解,因为我尝试了一段时间未成功.现在,我想我应该更改它,以使用数学公式f(x)=sqrt(x)作为速度的模型,而不是当前的有理函数形式.如何在仍然使用AddForce()的同时更改代码以执行此操作,以便播放器正确与其他对象进行物理交互?

The logic is a bit convoluted, because I have experimented unsuccessfully with it for a while. Now, I think I should change it to use the mathematical formula f(x)=sqrt(x) as a model for my velocity, rather than my current one which is some form of rational function. How can I change the code to do this, while still using AddForce() so the player will correctly interact physically with other objects?

推荐答案

如评论中所述,我的第一个建议是避免手动跟踪物体的速度-Unity的物理系统可通过Rigidbody.velocity.magnitude.您可以使用它与maxSpeed进行比较,以确定是否应添加附加力.

As mentioned in the comments, my first suggestion would be to avoid manually tracking the speed of an object - Unity's physics system makes this easy to access accurately, through Rigidbody.velocity.magnitude. You can use this to compare against maxSpeed, to determine whether additional force should be added or not.

关于您希望速度与f(x)=sqrt(x)的曲线相匹配的需求,您将需要为此做一些基本的演算.由于您不想人为地限制速度(因为您仍然希望发生物理相互作用),因此应该将加速度限制为一个函数.

Regarding your desire to have velocity match the curve of f(x)=sqrt(x), you're going to need to do some basic calculus for this. Since you don't want to constrain velocity artificially (because you still want physical interactions to occur), you should instead constrain acceleration to a function.

要确定定义玩家加速度的函数,您需要导出您希望速度(理想)匹配的函数.这将为您提供任何给定点的速度变化率-根据定义,这就是加速度.

To determine the function to define the player's acceleration, you'll need to derive the function you want velocity to (ideally) match. This will give you the rate of change of the velocity at any given point - which, by definition, is the acceleration.

因此,假设我们使用函数f(x)=sqrt(x)作为理想速度的模型. sqrt(x)的导数是1/(2 * sqrt(x))-因此这是定义加速度的函数.现在,我们需要能够确定任何给定速度的加速度,因为这是我们将在代码中使用的关系.这需要一些简单的代数-我们需要根据给定的y来求解x:

So let's say we use the function f(x)=sqrt(x) as a model for the ideal velocity. The derivative of sqrt(x) is 1/(2 * sqrt(x)) - so this is the function that defines our acceleration. Now, we need to be able to determine the acceleration for any given velocity, since this is the relationship we'll be using in the code. This takes a little simple algebra - we'll need to solve for x given y:

          y = 1/(2 * sqrt(x))
sqrt(x) * y = 1 / 2
    sqrt(x) = 1 / (2 * y)
          x = (1 / (2 * y))^2

现在,我们有了一个方程,可以为我们提供任何给定速度所需的加速度.现在,我们可以将其放入代码中-根据平方根函数加速,直到maxSpeed:

Now we have an equation that provides us with the required acceleration for any given speed. We can now put this into code - accelerating according to the square root function up to maxSpeed:

float maxAcceleration = 10;

// Basically x = (1 / (2 * y))^2, but in code
float CalculateAccGivenSpeed(float speed)
{
    // Early exit so we don't bother with undefined results from dividing by 0
    if (speed == 0)
    {
        return Mathf.Infinity;
    }

    float rootAcc = 1 / (2 * speed);
    return rootAcc * rootAcc;
}

void FixedUpdate()
{
    // Only accelerate if speed is lower than maximum allowed
    if (rb.velocity.magnitude < maxSpeed)
    {
        float allowableAcc = CalculateAccGivenSpeed(rb.velocity.magnitude);

        // Constrain acceleration here so rigidbody doesn't explode from stationary
        allowableAcc = Mathf.Min(maxAcceleration, allowableAcc);

        // Using ForceMode.Acceleration so we don't have to worry about mass
        rb.AddForce(transform.forward * allowableAcc, ForceMode.Acceleration);
    }
}

如果发现加速度过快/过慢,可以将CalculateAccGivenSpeed()的结果乘以标量值.在数学上,这将沿y轴缩放平方根函数,保留平方根关系,但会更改达到给定y值(速度)的速率.

If you find the acceleration goes too quickly/slowly, you can multiply the result of CalculateAccGivenSpeed() with a scalar value. Mathematically, this will scale the square root function along the y-axis, preserving the square root relationship, but changing the rate at which is reaches a given y-value (speed).

希望这会有所帮助!如果您有任何问题,请告诉我.

Hope this helps! Let me know if you have any questions.

这篇关于使用数学公式定义玩家速度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆