如何在Unity3D中使用透视相机移动对象并旋转相机?

时间:2020-04-19 20:08:34

标签: c# unity3d perspectivecamera

我正在尝试旋转相机(在X中旋转50度),并且还在触摸位置之后放置一个对象,这是我的脚本,可以旋转相机并移动对象,但是由于它是透视图,所以该对象没有移动正确地跟随手指,有关如何实现此目标的任何提示?

目标是实现本视频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 个答案:

答案 0 :(得分:2)

我前段时间创建了类似的东西。

您需要注意ScreenToWorldPoint()。单击位置基本上不是世界上的3D点,而是光线。空间中有一整行位置会全部出现在屏幕的同一位置。

Unity函数ScreenToWorldPoint()使用输入向量中的Z坐标作为距离。由于您只是从Input.GetTouch()捡起它​​,所以肯定不是您想要的距离。

文档:https://docs.unity3d.com/2020.1/Documentation/ScriptReference/Camera.ScreenToWorldPoint.html

最好使用Camera.ScreenPointToRay()。然后使用该射线确定要考虑单击的点。

在我的抓取实现中,我用它来调用Physics.Raycast()Physics.RaycastAll(),查看找到的匹配项,然后确定一个匹配点。

当玩家拖动时,您需要确定如何更改距离。如果像在示例视频链接中那样在地图上单击,则可以保持单击目标的Y坐标,然后对于每次鼠标移动,将新Ray与该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坐标恒定?