Как перемещать объекты с помощью перспективной камеры и вращать камеру в Unity3D? - PullRequest
1 голос
/ 19 апреля 2020

Я пытаюсь повернуть камеру (на 50 градусов по оси X), а также разместить объект, следуя положению касания, вот мой сценарий, он может вращать камеру и перемещать объект, но, поскольку он в перспективе, объект не движется правильно следуя пальцу, какие-нибудь советы, как мне этого добиться?

Цель - достичь чего-то подобного в этом видео https://www.youtube.com/watch?v=Ljnpp5ibfGQ

using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;

 public class CameraRotator : MonoBehaviour
 {
     private float initialX;
     public float offset = 10f;
     public float speed = 10f;
     public GameObject cube;
     public bool movingPlayer = false;

     void Update()
     {

         if (Input.touchCount > 0 && !movingPlayer)
         {
             Touch touch = Input.GetTouch(0);
             Vector3 touchPosition = Camera.main.ScreenToWorldPoint(touch.position);

             switch (touch.phase)
             {
                 case TouchPhase.Began:

                     initialX = touch.position.x;
                     break;
                 case TouchPhase.Moved:
                     if (touch.position.x + offset < initialX)
                         transform.rotation = Quaternion.Euler(0f, transform.rotation.eulerAngles.y - speed, 0f);
                     else if (touch.position.x - offset > initialX)
                         transform.rotation = Quaternion.Euler(0f, transform.rotation.eulerAngles.y + speed, 0f);

                     initialX = touch.position.x;
                     break;
             }
         }


         if (Input.touchCount > 0 && movingPlayer)
         {
             Touch touch = Input.GetTouch(0);
             Vector3 touchPosition = Camera.main.ScreenToWorldPoint(touch.position);

             Ray raycast = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);

             if (Input.GetTouch(0).phase == TouchPhase.Moved)
             {
                 Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
                 Vector3 xx = ray.GetPoint(10f);
                 xx.y = 1f;
                 xx.x = (int)xx.x;
                 xx.z = (int)xx.z;
                 cube.transform.position = xx;
             }

         }
     }
 }

1 Ответ

2 голосов
/ 20 апреля 2020

Я когда-то создал нечто подобное go.

Вы должны быть осторожны с ScreenToWorldPoint(). Положение щелчка - это никогда не трехмерная точка в мире, а луч. В пространстве есть целая линия местоположений, которые будут появляться в одном и том же месте экрана.

Функция Unity ScreenToWorldPoint() использует координату Z из входного вектора в качестве расстояния. Поскольку вы просто берете его с Input.GetTouch(), это, безусловно, не то расстояние, на которое вы хотите.

Делайте c на нем: https://docs.unity3d.com/2020.1/Documentation/ScriptReference/Camera.ScreenToWorldPoint.html

Предпочтительно использовать Camera.ScreenPointToRay(). Затем используйте этот луч, чтобы решить, какую точку вы хотите считать нажатой.

В моей реализации захвата я использовал это для вызова Physics.Raycast() или Physics.RaycastAll(), посмотрите на найденные хиты, и решите за точку попадания.

Когда игрок тянет, вам нужно решить, как изменить расстояние. Если вы щелкаете по карте, как в примере ссылки на видео, вы можете сохранить координату Y цели щелчка, а затем при каждом перемещении мыши пересекать новый луч с этой плоскостью Y.

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

Из моего образца, нажав, я делаю это:

    // try to grab something.
    Ray beam = new Ray(){origin=head.transform.position,direction=head.transform.forward};
    RaycastHit hit;
    if( ! Physics.Raycast(beam,out hit,15.0f) )
        return;
    grab_item = hit.rigidbody;
    if( grab_item==null || grab_item.isKinematic )
        return;
    grab_pos_on_item = grab_item.transform.InverseTransformPoint(hit.point);
    grab_distance = (hit.point-beam.origin).magnitude;

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

    if(grab_item!=null)
    {
        // p1: hand, p2: item
        Vector3 p1 = head.transform.position + head.transform.forward * grab_distance;
        Vector3 p2 = grab_item.transform.TransformPoint(grab_pos_on_item);
        Vector3 dist = p1-p2;
        // code to make the item move by 'dist'

Если я правильно понял, вам, возможно, будет интересно сохранить постоянную координаты Y?

...