camera旋转+模型移动

    刚接触Unity不久,正处于用什么学什么的状态,遇到这个问题着实研究了一阵子,得到了一个比较笨的方法。

    想要完成的功能有两个,一是摄像机绕着整个场景中的所有模型旋转,旋转的中心点是世界坐标的原点;二是不管摄像机旋转到什么位置,模型都能跟随鼠标进行移动。

    单独的让摄像机绕世界坐标原点旋转可以使用transform.RotateAround(Vector3.zero, Vector3.down, mouseMovex * Time.deltaTime)。但是问题来了,如果只是进行水平方向或是垂直方向上的单方向的旋转,简单的使用transform.RotateAround(Vector3.zero, Vector3.down, mouseMovex * Time.deltaTime)是可以的;如果需要水平方向和垂直方向的混合旋转,就会出现问题,而这个问题就出在Vector3.down上。对于用户来说,在鼠标拖拽旋转的过程中,是以屏幕坐标为准的。也就是说这个Vector3.down对于用户来说是屏幕坐标的y轴,只有第一次旋转的时候屏幕坐标的x、y轴与世界坐标的x、y轴是重合的,只要摄像机进行过一次旋转,屏幕坐标与世界坐标就不再重合。所以当多次旋转时,就会出现混乱。不只是旋转,鼠标对模型的拖拽也会出现严重的偏差。这就需要在每一次旋转前对旋转轴进行修正。我的方法是在摄像机x方向加一和y方向加一各添加一个Empty GameObject与摄像机进行同步旋转,作为方向标志物。在每一次旋转前,获取摄像机与两个方向标志物的世界坐标,进而计算出屏幕坐标轴在世界坐标中的方向向量,来确定摄像机的旋转轴。代码如下:

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 public class scencerotate : MonoBehaviour {
 5 
 6     Vector2 mousePositionBefore, mousePositionAfter;     //用来记录鼠标的位置,以便计算旋转幅度
 7     private GameObject camera;      //保存摄像机信息
 8     private GameObject xflagGameObject;     //保存x方向标志物的信息
 9     private GameObject yflagGameObject;     //保存y方向标志物的信息
10     private Vector3 xdirVector;     //屏幕坐标x方向在世界坐标中的方向向量
11     private Vector3 ydirVector;     //屏幕坐标y方向在世界坐标中的方向向量
12 
13     // Use this for initialization
14     void Start () 
15     {        
16     }
17     
18     // Update is called once per frame
19     void Update () 
20     {
21         if (Input.GetMouseButtonDown(1))        //检测鼠标右键是否被按下
22         {
23             xflagGameObject = GameObject.Find("xFlag(Clone)");
24             yflagGameObject = GameObject.Find("yFlag(Clone)");
25             camera = GameObject.Find("Main Camera");
26             xdirVector = xflagGameObject.transform.position - camera.transform.position;        //得到屏幕坐标的x方向在世界坐标系下的方向向量
27             ydirVector = yflagGameObject.transform.position - camera.transform.position;        //得到屏幕坐标的y方向在世界坐标系下的方向向量
28             mousePositionBefore = new Vector2(Input.mousePosition.x, Input.mousePosition.y);        //鼠标右键按下时记录鼠标位置mousePositionBefore
29         }
30         if (Input.GetMouseButton(1))        //检测鼠标右键是否被按着
31         {
32             mousePositionAfter = new Vector2(Input.mousePosition.x, Input.mousePosition.y);     //鼠标右键拖动时记录鼠标位置mousePositionAfter
33             //下面开始旋转
34             float mouseMovex = (mousePositionAfter.x - mousePositionBefore.x) * 0.1f;
35             float mouseMovey = (mousePositionAfter.y - mousePositionBefore.y) * 0.1f;
36             transform.RotateAround(Vector3.zero, ydirVector, mouseMovex * Time.deltaTime);         //在屏幕坐标系水平方向上进行旋转
37             transform.RotateAround(Vector3.zero, -xdirVector, mouseMovey) * Time.deltaTime);         //在屏幕坐标系垂直方向上进行旋转
38          }
39     }
40 }

    把以上脚本放到摄像机上即可。模型移动是一样的方法

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 public class move : MonoBehaviour
 5 {
 6     private GameObject camera;      //保存摄像机信息
 7     private GameObject xflagGameObject;     //保存x方向标志物的信息
 8     private GameObject yflagGameObject;     //保存y方向标志物的信息
 9     private Vector3 xdirVector;     //屏幕坐标x方向在世界坐标中的方向向量
10     private Vector3 ydirVector;     //屏幕坐标y方向在世界坐标中的方向向量
11     private Vector3 moveModel;      //模型在世界坐标中的移动向量
12 
13     // Use this for initialization
14 
15     void Start()
16     {
17 
18     }
19 
20     // Update is called once per frame
21 
22     void Update()
23     {
24 
25     }
26 
27     //下面的函数是当鼠标触碰到碰撞体或者刚体时调用,我的碰撞体设置是mesh collider,然后别忘了,给这个collider添加物理材质
28     //值得注意的是世界坐标系转化为屏幕坐标系,Z轴是不变的
29     IEnumerator OnMouseDown()
30     {
31        Vector3 screenSpace = Camera.main.WorldToScreenPoint(transform.position);       //将物体由世界坐标系转化为屏幕坐标系 ,由vector3 结构体变量ScreenSpace存储,以用来明确屏幕坐标系Z轴的位置
32         Vector3 offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z));     //完成了两个步骤,1由于鼠标的坐标系是2维的,需要转化成3维的世界坐标系,2只有三维的情况下才能来计算鼠标位置与物体的距离,offset即是距离
33 
34         //当鼠标左键按下时
35         while (Input.GetMouseButton(0))
36         {
37             Vector3 curScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z);       //得到现在鼠标的2维坐标系位置
38             Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenSpace);       //将当前鼠标的2维位置转化成三维的位置
39 
40             //判断移动方向
41             xflagGameObject = GameObject.Find("xFlag(Clone)");
42             yflagGameObject = GameObject.Find("yFlag(Clone)");
43             camera = GameObject.Find("Main Camera");
44             xdirVector = xflagGameObject.transform.position - camera.transform.position;
45             ydirVector = yflagGameObject.transform.position - camera.transform.position;
46             moveModel.x = xdirVector.x * offset.x + ydirVector.x * offset.x;
47             moveModel.y = xdirVector.y * offset.y + ydirVector.y * offset.y;
48             moveModel.z = xdirVector.z * offset.z + ydirVector.z * offset.z;
49             transform.position = new Vector3(curPosition.x + moveModel.x, curPosition.y + moveModel.y, curPosition.z + moveModel.z);
50 
51             //这个很重要
52             yield return new WaitForFixedUpdate();
53         }
54     }
55 }

    以上只是一个初学者自己想出来的解决方法,应该还会有更好的方法,使用坐标转换或许能行且简单些(我没有弄出来)。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。