标签:
刚接触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 }
以上只是一个初学者自己想出来的解决方法,应该还会有更好的方法,使用坐标转换或许能行且简单些(我没有弄出来)。
标签:
原文地址:http://www.cnblogs.com/HelloWorld-5/p/4440978.html