【问题标题】:Unity 2D Trajectory prediction for mobile适用于移动设备的 Unity 2D 轨迹预测
【发布时间】:2020-03-03 09:43:02
【问题描述】:

我需要有关移动设备轨迹预测方面的帮助。

我可以在 PC 上使用鼠标执行此操作,但我无法使用移动设备上的触摸功能执行此操作。

我有我在开始时复制的点,当我拖动球时,我想计算我的轨迹。

触摸结束后,我会破坏这些点。

正如我所说,我可以使用 Input.GetMouseButton/Up/Down 来做到这一点,但我无法使用触摸功能来做到这一点。

这是我的代码:

 private void Update()
{
    //if (Input.touchCount > 0)
    //{


        Touch touch = Input.GetTouch(0);

        if (touch.phase == TouchPhase.Began)
        {
            startPosition = Input.GetTouch(0).position;


            for (int i = 0; i < number; i++)
            {
                trajectoryDots[i] = Instantiate(trajectoryDot, gameObject.transform);

            } 

        }

        if (Input.touchCount > 0)
        {

            for (int i = 0; i < number; i++)
            {
                trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
            }
        }

        if (touch.phase == TouchPhase.Ended)
        {

            for (int i = 0; i < number; i++)
            {
                Destroy(trajectoryDots[i]);
            }

            endPoisiton = Input.GetTouch(0).position;
            force = startPosition - endPoisiton;
            ballRigid.gravityScale = 1;
            ballRigid.velocity = new Vector2(force.x * power, force.y * power);

        }

    //}
}

private Vector2 calculatePosition(float elapsedTime)
{

    return new Vector2(endPoisiton.x, endPoisiton.y) +
        new Vector2(force.x * power, force.y * power) * elapsedTime +
        0.5f * Physics2D.gravity * elapsedTime * elapsedTime;


}

我用于鼠标输入的代码

 if (Input.GetMouseButtonDown(0))
    { //click
        startPos = gameObject.transform.position;
        for (int i = 0; i < number; i++)
        {
            trajectoryDots[i] = Instantiate(trajectoryDot, gameObject.transform);
        }

    }
    if (Input.GetMouseButton(0))
    { //drag
        endPos = Camera.main.ScreenToWorldPoint(Input.mousePosition) + new Vector3(0, 0, 10);
        gameObject.transform.position = endPos;
        forceAtPlayer = endPos - startPos;
        for (int i = 0; i < number; i++)
        {
            trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
        }
    }
    if (Input.GetMouseButtonUp(0))
    { //leave
        rigidbody.gravityScale = 1;
        rigidbody.velocity = new Vector2(-forceAtPlayer.x * forceFactor, -forceAtPlayer.y * forceFactor);
        for (int i = 0; i < number; i++)
        {
            Destroy(trajectoryDots[i]);
        }
    }

所以经过一些小的改变之后,它会好得多,我越来越接近我想要的了,我猜仍然有一些小故障,因为 touch.moved 所以当我用手指展示并且只做一些小动作时,球在跳跃屏幕上 这是代码

    private void Update()
{
    if (Input.touchCount > 0)
    {
        var touch = Input.GetTouch(0);
        switch (touch.phase)
        {
            case TouchPhase.Began:
                initPosition = gameObject.transform.position;
                startPosition = cam.ScreenToWorldPoint(touch.position) + new Vector3(0, 0, 10);
                for (int i = 0; i < number; i++)
                {
                    trajectoryDots[i] = Instantiate(trajectoryDot, gameObject.transform);
                    trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
                }

                break;

            case TouchPhase.Moved:

                endPosition = Camera.main.ScreenToWorldPoint(touch.position) + new Vector3(0, 0, 10);
                gameObject.transform.position = initPosition;
                force = startPosition - endPosition;
                for (int i = 0; i < number; i++)
                {
                    trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
                }
                break;

            case TouchPhase.Ended:
                ballRigid.gravityScale = 1;
                ballRigid.velocity = new Vector2(force.x * power, force.y * power);

                for (int i = 0; i < number; i++)
                {
                    Destroy(trajectoryDots[i]);
                }
                break;
        }
    }
}

private Vector2 calculatePosition(float elapsedTime)
{
    return new Vector2(initPosition.x, initPosition.y) +
    new Vector2(force.x * power, force.y * power) * elapsedTime +
    0.5f * Physics2D.gravity * elapsedTime * elapsedTime;
}

好的,我有最终的解决方案,它工作正常

    private void Update()
{
    if (Input.touchCount > 0)
    {
        var touch = Input.GetTouch(0);
        switch (touch.phase)
        {
            case TouchPhase.Began:
                initPosition = gameObject.transform.position;
                startPosition = cam.ScreenToWorldPoint(touch.position) + new Vector3(0, 0, 10);
                for (int i = 0; i < number; i++)
                {
                    trajectoryDots[i] = Instantiate(trajectoryDot, gameObject.transform);
                    trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
                }
                break;

            case TouchPhase.Ended:
                ballRigid.gravityScale = 1;
                ballRigid.velocity = new Vector2(force.x * power, force.y * power);

                for (int i = 0; i < number; i++)
                {
                    Destroy(trajectoryDots[i]);
                }
                break;
        }

        endPosition = Camera.main.ScreenToWorldPoint(touch.position) + new Vector3(0, 0, 10);
        gameObject.transform.position = initPosition;
        force = startPosition - endPosition;
        for (int i = 0; i < number; i++)
        {
            trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
        }
    }
}

private Vector2 calculatePosition(float elapsedTime)
{
    return new Vector2(initPosition.x, initPosition.y) +
    new Vector2(force.x * power, force.y * power) * elapsedTime +
    0.5f * Physics2D.gravity * elapsedTime * elapsedTime;
}

【问题讨论】:

  • 你绝对应该保留if(Input.touchCount &gt; 0) 否则GetTouch(0) 在没有触摸的情况下抛出异常。然后宁可在触摸阶段使用switch - case!如果您声称它适用于鼠标..您可以添加用于鼠标输入的代码吗?
  • 那些 cmets 线是的,它只是实验性的,我也在考虑开关盒

标签: c# unity3d mobile game-engine


【解决方案1】:

所以只要把你的鼠标代码转换成触摸代码就可以了

if(Input.touchCount > 0)
{
    var touch = Input.GetTouch(0);
    switch(touch.phase)
    {
        case TouchPhase.Began:
            // Note: to be more accurate you actually probably would 
            // rather also here use ScreenToWorldPoint on the touch.position
            // same way as later. Otherwise you might allways get a force even if touch wasn't moved at all
            //startPos = transform.position;
            startPos = Camera.main.ScreenToWorldPoint(touch.position) + new Vector3(0, 0, 10);
            for (int i = 0; i < number; i++)
            {
                trajectoryDots[i] = Instantiate(trajectoryDot, gameObject.transform);
                trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
            }

           break;

        case TouchPhase.Moved:
            // These were missing in your touch version
            // You did it only in the end so there were no preview trajectory
            // And note that also touch is in pixel screenspace so if you
            // want to use world positions you need to convert them just the same as for mouse input!
            endPos = Camera.main.ScreenToWorldPoint(touch.position) + new Vector3(0, 0, 10);
            transform.position = endPos;
            force = endPos - startPos;
            for (int i = 0; i < number; i++)
            {
                 trajectoryDots[i].transform.position = calculatePosition(i * 0.1f);
            }
            break;

        case TouchPhase.Ended:
            rigidbody.gravityScale = 1;
            // Not sure why but in your mouse code you used a negative force here 
            // but in this case your trajectory would have been wrong since there you didn't use negative values...
            rigidbody.velocity = force * forceFactor;

            for (int i = 0; i < number; i++)
            {
                Destroy(trajectoryDots[i]);
            }
            break;
    }
}

顺便说一句,calculate 方法更易读

private Vector2 calculatePosition(float elapsedTime)
{  
    return endPoisiton 
        + force * power * elapsedTime 
        + Physics2D.gravity * 0.5f * elapsedTime * elapsedTime;
}

注意:在智能手机上输入,但我希望思路清晰

【讨论】:

  • 它无法正常工作 TouchPhase.Moved 有一些问题我猜,我也试过了,但它与 GetMouseButton 不一样,相当于 GetMouseButton for touch is TouchCount > 0
  • 是的,但是如果最后一帧没有任何变化,为什么要每帧更新轨迹呢?您只需要更新手指实际移动的轨迹。因此,我已经在 touchpahse.Began 中初始化了一次位置(只是将其添加为更新)
  • 还有一些问题,因为触摸的工作方式与 MouseButton 不同,好的,我会努力的,我会尝试改变它
  • 感谢您帮助我将最终解决方案添加到我的主题中
  • 您需要gameObject.transform.position = initPosition; 做什么?据我所知,它没有做任何事情。此外,这与我的答案有何不同 - 除了触​​摸没有移动时不必要的轨迹更新? ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-22
  • 1970-01-01
  • 2021-03-23
  • 1970-01-01
相关资源
最近更新 更多