首页 > 解决方案 > 如何使用透视相机移动物体并在 Unity3D 中旋转相机?

问题描述

我正在尝试旋转我的相机(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;
             }

         }
     }
 }

标签: c#unity3dperspectivecamera

解决方案


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

你需要小心ScreenToWorldPoint()。Click 位置基本上不是世界上的 3D 点,而是一条射线。空间中有一整行位置都将出现在屏幕上的同一个位置。

Unity 函数ScreenToWorldPoint()使用来自输入向量的 Z 坐标作为距离。既然你只是从 捡来的Input.GetTouch(),那肯定不是你想要的距离。

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

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

在我的抓取实现中,我用它来调用Physics.Raycast()or 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 坐标不变?


推荐阅读