Unity 2D прогнозирование траектории для мобильных устройств - PullRequest
0 голосов
/ 03 марта 2020

Мне нужна помощь с предсказанием траектории на мобильном телефоне.

Я могу сделать это на P C с помощью мыши, но я не могу сделать это с сенсорными функциями на мобильном телефоне.

У меня есть точка, которую я копирую в начале, и пока я перетаскиваю мяч, я хочу вычислить свою траекторию.

После того, как прикосновение закончится, я уничтожу эти точки.

Как я уже сказал, я могу сделать это, используя 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;
}

1 Ответ

0 голосов
/ 03 марта 2020

Так что, просто взяв код мыши и преобразовав его в сенсорный код, он может выглядеть так:

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;
    }
}

Кстати, метод вычисления становится лучше, читается как

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

Примечание: напечатано на смартфоне, но я надеюсь, что идея проясняется

...