球力学-这是最好的方法吗? [英] Ball Mechanics - Is this the best approach?

查看:120
本文介绍了球力学-这是最好的方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

美好的一天,

我想编写一个在两个固定物体(object1object2)之间传递的不断移动的球(object3),并能够动态设置传递轨迹的最大高度Y

I'd like to program a constantly moving ball (object3) being passed between two stationary objects (object1, object2), with the ability to set the max height Y of the pass trajectory dynamically.

您会争论为这个概念编程球物理的最佳方法是什么?

What would you argue is the best way to program the ball physics for this concept?

我看过在带有刚体的默认球体上使用addForce的情况.似乎应该存在一个方程,该表达式表示从object1的x到object2的x的object3的轨迹...在已知的情况下,给定speed,且已知的设置mass,以及已知的重力环境.

I've looked at using addForce on a default sphere w/ a rigidbody. It seems like there should be an equation that expresses the trajectory of a pass of object3 from object1's x to object2's x... at a known, given speed, with a known, set mass, and a known gravity environment.

但是,目前我有一个Vector3.Lerp插值球,每个FixedUpdate()的两个对象之间的球都以t表示:

However, currently I have a Vector3.Lerp interpolating the ball between the two objects on each FixedUpdate() with t expressed as:

`(Mathf.Sin(speed * Time.time) + 1.0f) / 2.0f;`

一切正常,但是使用这种方法,似乎没有明确的方法将height添加到球的轨迹中.我已经考虑过将height添加到object2中的Y值,直到球居中,然后将其设置回原始的Y位置...但是感觉很不对!有想法吗?

It works and all, but with this approach, it seems there's no clear way to add height to the trajectory of the ball path. I've considered adding the height to the Y value in object2 until the ball is half way there, and then setting it back to the original Y position... but it just feels wrong! Thoughts?

谢谢!

推荐答案

好的,如果我目前对您的理解正确,

Okey so if I understand you correctly currently you are doing

privte void FixedUpdate()
{
    var factor = (Mathf.Sin(speed * Time.time) + 1.0f) / 2.0f;
    object1.MovePosition(Vector3.Lerp(object2.position, object3.position, factor));
}

可以使乒乓球在object1object2位置之间移动,但只能是平面.

which moves the ball pingpong between object1 and object2 position but only planar.

假设目前这些对象将仅在XZ平面内移动,并且永不具有不同的Y位置,为了获得具有高度的曲线,您可以分别处理: -和以前一样在两个位置之间进行插值 -使用窦或任何其他数学曲线函数分别计算Y位置-对于现实物理学来说,实际上可能是抛物线

Assuming for now the objects will only be moving within the XZ plane and never have different Y position in order to rather get a curve with height you could treat the separatly: - Interpolate between both positions as before - Separately calculate the Y position with sinus or any other mathematical curve function - for realistic physics probably rather a parabola actually

看起来很像

public class Example : MonoBehaviour
{
    public Rigidbody object1;
    public Transform object2;
    public Transform object3;

    // adjust in the Inspector
    public float speed = 1;
    public float Amplitude = 0;

    // Just for debug
    [Range(0, 1)] [SerializeField] private float linearFactor;
    [SerializeField] private float yPosition;

    private void FixedUpdate()
    {
        // This always returns a value between 0 and 1 
        // and linearly pingpongs forth and back
        linearFactor = Mathf.PingPong(Time.time * speed, 1);
        // * Mathf.PI => gives now a value 0 - PI
        // so sinus returns correctly 0 - 1 (no need for +1 and /2 anymore)
        // then simply multiply by the desired amplitude
        var sinus = Mathf.Sin(linearFactor * Mathf.PI);
        yPosition = sinus * Amplitude;

        // As before interpolate between the positions
        // later we will ignore/replace the Y component
        var position = Vector3.Lerp(object2.position, object3.position, linearFactor);

        object1.MovePosition(new Vector3(position.x, yPosition, position.z));
    }
}

您还可以选择尝试在Y方向上添加一些转储,以使垂直运动更加逼真(达到峰值时变慢).我尝试使用像这样的倒置SmoothStep

You could optionally also try and add some dumping in the Y direction in order to make the vertical movement more realistic (slow down when reaching the peak). I tried a bit using inverted SmoothStep like

// just for debug
[Range(0, 1)] [SerializeField] private float dampedSinusFactor;
[Range(0, 1)] [SerializeField] private float linearFactor;
[SerializeField] private float yPosition;

private void FixedUpdate()
{
    // Use two different factros:
    // - a linear one for movement in XZ
    // - a smoothed one for movement in Y (in order to slow down when reaching the peak ;) )
    linearFactor = Mathf.PingPong(Time.time * speed, 1);
    dampedSinusFactor = InvertSmoothStep(linearFactor);

    // * Mathf.PI => gives now a value 0 - PI
    // so sinus returns correctly 0 - 1 ()
    // then simply multiply by the desired amplitude
    var sinus = Mathf.Sin(dampedSinusFactor * Mathf.PI);
    yPosition = sinus * Amplitude;

    // later we will ignore/replace the Y component
    var position = Vector3.Lerp(object2.position, object3.position, linearFactor);

    object1.position = new Vector3(position.x, yPosition, position.z);
}

// source: https://stackoverflow.com/a/34576808/7111561
private float InvertSmoothStep(float x)
{
    return x + (x - (x * x * (3.0f - 2.0f * x)));
}

但是对于慢速移动,这看起来有些奇怪.但是您可以提出任何其他数学曲线,从而得出x=[0,1];)

However for slow movements this looks a bit strange yet. But you can come up with any other maths curve that results in the expected behavior for x=[0,1] ;)

这篇关于球力学-这是最好的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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