Как переместить куб по траектории в Unity3D - PullRequest
1 голос
/ 14 мая 2019

Мне нужно перемещать куб по траектории движения, используя точки или символ типа стрелки, когда перетаскиваем мышь, чтобы переместиться в определенное положение мыши и ее силу перетаскивания.

Я использовал код, который использовался в 2D-проекте для перемещения шара по траектории движения, но он не работал.

Вот код, который я так пробовал для

void Start()
{
    cam = Camera.main;
    cubeClick = GameObject.Find("Cube Click Area");
    trajectoryDots = GameObject.Find("Trajectory Dots");
    rb = Player.GetComponent<Rigidbody>();
    trajectoryDots.transform.localScale = new Vector3(
        initialDotSize, 
        initialDotSize, 
        trajectoryDots.transform.localScale.z);
    for (int dotNumber = 0; dotNumber < 40; dotNumber++)
    {
        Dots[dotNumber] = GameObject.Find("Dot (" + dotNumber + ")");
        if (DotSprite !=null)
        {
            Dots[dotNumber].GetComponent<SpriteRenderer>().sprite = DotSprite;
        }
    }
    for (int dotNumber = NumberOfDots; dotNumber < 40; dotNumber++)
    {
        GameObject.Find("Dot (" + dotNumber + ")").SetActive(false);
    }
    trajectoryDots.SetActive(false);


}


void Update()
{
    Ray camRay = cam.ScreenPointToRay(Input.mousePosition);
    RaycastHit hit;
    //RaycastHit2D hit = Physics2D.Raycast(cam.(Input.mousePosition), Vector2.zero);
    if (Physics.Raycast(camRay, out hit, 100f) && !cubeisClicked2)
    {
        if (hit.collider.gameObject.name == Player.name)
        {
            cubeisClicked = true;
        }
        else
        {
            cubeisClicked = false;
        }
    }
    else
    {
        cubeisClicked = false;
    }

    if (cubeisClicked2)
    {
        cubeisClicked = true;
    }

    if ((rb.velocity.x * rb.velocity.x) + (rb.velocity.y * rb.velocity.y) <= 0.0085f)
    {
        rb.velocity = new Vector2(0f, 0f);
    }
    else
    {
        trajectoryDots.SetActive(false);
    }
    cubePosition = Player.transform.position;
    if ((Input.GetKey(KeyCode.Mouse0) && cubeisClicked) && ((rb.velocity.x == 0f && rb.velocity.y == 0f)))
    {
        cubeisClicked2 = true;
        fingerPosition = cam.ScreenToWorldPoint(Input.mousePosition);
        fingerPosition.z = 0f;
        cubeFingerDiff = cubePosition - fingerPosition;
        ShotForce = new Vector2(cubeFingerDiff.x * shootingPowerX , cubeFingerDiff.y * shootingPowerY);
        if (Mathf.Sqrt((cubeFingerDiff.x * cubeFingerDiff.x) + (cubeFingerDiff.y * cubeFingerDiff.y) )>0.4f)
        {
            trajectoryDots.SetActive(true);

        }
        else
        {
            trajectoryDots.SetActive(false);
        }

        for (int dotNumber = 0; dotNumber < NumberOfDots; dotNumber++)
        {
            x1 = cubePosition.x * ShotForce.x * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift);
            y1 = cubePosition.y * ShotForce.y * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift) - (-Physics.gravity.y / 2f * Time.fixedDeltaTime * Time.fixedDeltaTime * (DotSeparation * dotNumber + dotShift) * (DotSeparation * dotNumber + dotShift));
            Dots[dotNumber].transform.position = new Vector3(x1, -y1, 0);
        }

        if (Input.GetKeyUp(KeyCode.Mouse0))
        {
            cubeisClicked2 = false;
            trajectoryDots.SetActive(false);

            rb.velocity = new Vector2 (ShotForce.x, ShotForce.y);;

        }


    }



}

Это не работает, показывает точки, как показано на.

image

Он должен перемещать куб таким образом, чтобы пользователь перетаскивал и указывал на местоположение для перемещения.

1 Ответ

1 голос
/ 15 мая 2019

Основная проблема заключается в том, что при использовании cam.ScreenToWorldPoint(Input.mousePosition); с перспективной камерой всегда возвращается положение камеры (это очень распространенная ошибка), поэтому вместо работы с положением мыши относительно куба вы работаете с камера против куба.

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

Один из способов получить желаемое поведение - создать плоскость, проходящую через куб перпендикулярно направлению камеры, и посмотреть, где луч мыши пересекается с плоскостью. Кроме того, установите флаг cubeisClicked2 в значение false, установив его в значение true, пока мы фактически нажимаем на плоскость:

cubePosition = Player.transform.position;
if ((Input.GetKey(KeyCode.Mouse0) && cubeisClicked) && ((rb.velocity.x == 0f && rb.velocity.y == 0f)))
{
    cubeisClicked2 = false;

    Plane cubePlane = new Plane(cam.transform.position - cubePosition, cubePosition);

    // reusing camRay

    // Determine if we are even hitting the plane
    float enter = 0.0f;

    if (cubePlane.Raycast(camRay, out enter))
    {
        cubeisClicked2 = true;
        fingerPosition  = camRay.GetPoint(enter);

Кроме того, вам необходимо включить z-компоненты в ваши расчеты силы и траектории. Вероятно, вы можете просто использовать съемку PowerPowerX для питания компонента z. Также есть изменения, которые необходимо внести в расчеты траектории, о которых я упоминал в комментариях:

        cubeFingerDiff = cubePosition - fingerPosition;
        ShotForce = new Vector3(cubeFingerDiff.x * shootingPowerX , cubeFingerDiff.y * shootingPowerY, cubeFingerDiff.z * shootingPowerX );
        if (cubeFingerDiff.magnitude>0.4f)
        {
            trajectoryDots.SetActive(true);

        }
        else
        {
            trajectoryDots.SetActive(false);
        }

        for (int dotNumber = 0; dotNumber < NumberOfDots; dotNumber++)
        {
            x1 = cubePosition.x + ShotForce.x * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift);
            y1 = cubePosition.y + ShotForce.y * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift) + (Physics.gravity.y / 2f * Time.fixedDeltaTime * Time.fixedDeltaTime * (DotSeparation * dotNumber + dotShift) * (DotSeparation * dotNumber + dotShift));
            z1 = cubePosition.z + ShotForce.z * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift);
            Dots[dotNumber].transform.position = new Vector3(x1, y1, z1);

Затем вместо проверки GetKeyUp(KeyCode.Mouse0) в том же if, что и при определении траектории, он должен быть рядом с ним, а также проверить, была ли найдена траектория:

        }
    } 
}

if (Input.GetKeyUp(KeyCode.Mouse0) && cubeisClicked2)
{
    cubeisClicked2 = false;
    trajectoryDots.SetActive(false);

    rb.velocity = new Vector3 (ShotForce.x, ShotForce.y, ShotForce.z);;

}

В целом это может выглядеть так:

cubePosition = Player.transform.position;
if ((Input.GetKey(KeyCode.Mouse0) && cubeisClicked) && ((rb.velocity.x == 0f && rb.velocity.y == 0f)))
{
    cubeisClicked2 = false;
    Plane cubePlane = new Plane(cam.transform.position - cubePosition, cubePosition);

    // reusing camRay

    // Determine if we are even hitting the plane
    float enter = 0.0f;
    if (cubePlane.Raycast(camRay, out enter))
    {
        cubeisClicked2 = true;
        fingerPosition  = camRay.GetPoint(enter);

        cubeFingerDiff = cubePosition - fingerPosition;
        ShotForce = new Vector3(cubeFingerDiff.x * shootingPowerX , cubeFingerDiff.y * shootingPowerY, cubeFingerDiff.z * shootingPowerX );
        if (cubeFingerDiff.magnitude>0.4f)
        {
            trajectoryDots.SetActive(true);

        }
        else
        {
            trajectoryDots.SetActive(false);
        }

        for (int dotNumber = 0; dotNumber < NumberOfDots; dotNumber++)
        {
            x1 = cubePosition.x + ShotForce.x * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift);
            y1 = cubePosition.y + ShotForce.y * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift) + (Physics.gravity.y / 2f * Time.fixedDeltaTime * Time.fixedDeltaTime * (DotSeparation * dotNumber + dotShift) * (DotSeparation * dotNumber + dotShift));
            z1 = cubePosition.z + ShotForce.z * Time.fixedDeltaTime * (DotSeparation * dotNumber * dotShift);
            Dots[dotNumber].transform.position = new Vector3(x1, y1, z1);
        }
    }         
}

if (Input.GetKeyUp(KeyCode.Mouse0) && cubeisClicked2)
{
    cubeisClicked2 = false;
    trajectoryDots.SetActive(false);

    rb.velocity = new Vector3 (ShotForce.x, ShotForce.y, ShotForce.z);;

}

Так как это вычисляет мощность снимка на расстоянии, на которое вы указываете cubePlane, когда камера находится дальше, вы сможете снимать сильнее.

Вероятно, это не то поведение, которое вам нужно, но если камера всегда находится на одном и том же расстоянии от куба, это не должно быть проблемой.

Если это неприемлемое ограничение, вы, вероятно, можете сделать что-то вроде деления ShotForce на расстояние между кубом и камерой и увеличения shootingPowerX и shootingPowerY по мере необходимости. Если вы не можете найти хорошее решение самостоятельно, его лучше задать в отдельном вопросе.

...