如何将滑动速度和位置转换为物体速度?

3
我正在开发一款“踢足球”类型的游戏,以此来学习Unity 3D技术。我已经拥有了所需的界面和功能,使得游戏看起来像这样: enter image description here 我在OnUpdate中使用了一些代码来检测鼠标按钮第一次按下(或触摸阶段开始)和释放(或触摸阶段结束),并计算滑动方向、距离和持续时间。我想将这些信息转化为初始速度,以“发射”足球,但是数学知识似乎超出了我的能力范围。
我最初尝试了以下代码:
rigidbody.velocity = new Vector3(
    Mathf.Min(15, swipeDelta.x * .13f),
    Mathf.Min(20, swipeDelta.y * yRatio),
    5 / swipeDuration);

当然,在我的初始分辨率和纵横比下,这个方法效果良好,但是一旦我更改任何一个参数,它就会变得相当糟糕。我希望代码可以更加适应各种不同的分辨率和纵横比,或者至少是相对的。上面代码中使用的数字完全是随意的,并且经过迭代测试发现在我的初始分辨率下产生了理想的结果。 有什么建议吗?

1
你有两个点A(第一次点击)和B(松开点击),然后B减去A可以给出方向,从而可以得到大小(又称长度、速度)。然后,您可以将此方向归一化,并乘以给定的(固定或可变)速度因子,以确保您的球以适当的速度沿着该方向飞出(否则速度可能太低或太高,因为鼠标坐标不能直接转换为物理速度)。 - CodeSmile
1个回答

3

这个想法是利用起点和终点之间的距离和持续时间来计算速度。

我使用ScreenToWorldPoint将鼠标位置从屏幕坐标转换为世界坐标,以便于计算世界距离,而不是屏幕像素密度或分辨率。

期望的最小/最大值是在进行任何调整之前获得的功率值。为了获得良好的值,您可以进行缓慢/短暂的滑动以获取最小值,进行快速长滑动以获取最大值。

所需的最小/最大值是您希望获得的任意值,以获得理想的结果。

根据游戏的方向,您可能需要旋转速度。现在,向上滑动会产生正y值,向右滑动会产生正x值。

Vector3 startPos;
float startTime;

void Update () 
{
    if (Input.GetMouseButtonDown(0))
    {
        //Store initial values
        startPos = Input.mousePosition;
        startTime = Time.time;
    }

    if (Input.GetMouseButtonUp(0))
    {
        //Get end values
        Vector3 endPos = Input.mousePosition;
        float endTime = Time.time;

        //Mouse positions distance from camera. Might be a better idea to use the cameras near plane
        startPos.z = 0.1f
        endPos.z = 0.1f

        //Makes the input pixel density independent
        startPos = Camera.main.ScreenToWorldPoint(startPos);
        endPos = Camera.main.ScreenToWorldPoint(endPos);

        //The duration of the swipe
        float duration = endTime - startTime;

        //The direction of the swipe
        Vector3 dir = endPos - startPos;

        //The distance of the swipe
        float distance = dir.magnitude;

        //Faster or longer swipes give higher power
        float power = distance / duration;

        //expected values are what power you get when you try 
        //desired values are what you want
        //you might want these as public values so they can be set from the inspector
        const float expectedMin = 50;
        const float expectedMax = 60;
        const float desiredMin = 15;
        const float desiredMax = 20;

        //Measure expected power here
        Debug.Log(power);

        //change power from the range 50...60 to 0...1
        power -= expectedMin;
        power /= expectedMax - expectedMin;

        //clamp value to between 0 and 1
        power = Mathf.Clamp01(power);

        //change power to the range 15...20
        power *= desiredMax - desiredMin;
        power += desiredMin;

        //take the direction from the swipe. length of the vector is the power
        Vector3 velocity = (transform.rotation * dir).normalized * power
    }

当我测试代码时,我没有遇到那个问题。也许我们使用的是不同版本的Unity。我已经更新了我的答案。 - Imapler
现在我已经旋转了相机和球对象以查看球门柱(因为想法是随机移动相机角度以模拟场地上的位置),但速度仍然相对于X角度为零应用。我如何将速度的X属性相对于球面对的方向进行转换? - Chris
我无法将浮点数(power)乘以四元数(rotation)。本质上,我的问题在于,如果球沿y轴向右旋转20度,则需要x速度的值表示该旋转。现在,速度的x值是相对于世界坐标系的(0.0表示直接朝着场地尽头而不是直接面对球的方向)。 - Chris
抱歉,我的意思是 ball.transform.rotation * dir。这将以球的旋转方式旋转速度方向。因此最终结果将是 Vector3 velocity = (ball.transform.rotation * dir).normalized * power - Imapler
我很抱歉自己太蠢了。我尝试了你说的方法,似乎解决了X方向的问题,但是Y和Z分量都出现了问题。你能否看一下这里的要点(https://gist.github.com/ripvannwinkler/800de7277914002c61d8),告诉我我做错了什么?关键函数是SetBallInMotion。 - Chris
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接