首先是实现拖拽对象,有两种方法
(1)当鼠标按下时从相机发射射线,从射线获取对象信息从而更新对象位置
(2)在对象脚本中使用OnMouseDrag函数
本文采用方法二进行实现
首先物品必须有Collider组件(没有Collider组件是没有办法接受射线的)
首先实现对象离摄像机固定距离拖拽
第一步需要记录从物体到摄像机的距离看如下代码
private float _depth;
private void OnMouseDown()
{
_depth = Camera.main.WorldToScreenPoint(this.transform.position).z;
}
这里使用了WorldToScreenPoint函数,该函数会返回一个三位向量,其中xy表示屏幕坐标,z表示深度(即对象到摄像机的距离)
第二步通过传入鼠标坐标来更新对象位置看如下代码
private void OnMouseDrag()
{
this.transform.position = Camera.main.ScreenToWorldPoint(
new Vector3(Input.mousePosition.x, Input.mousePosition.y, _depth);
}
如上代码将深度和鼠标位置信息作为参数获得对应世界坐标,将其值赋给对象即可实现离摄像机同距离拖拽游戏物体
只需要游戏对象在一个平面上移动,否则游戏对象可能会穿模,举个简单的例子:有一支铅笔在书桌上,我们想要鼠标拖拽铅笔,如果铅笔和摄像机的距离保持不变,那么当向下拖拽时,铅笔就会卡进桌子里。
那么为了解决这个问题,我们要保持铅笔在书桌这个平面上移动,接下来看看实现步骤
在实现之前先要有一点点初中数学的小知识 =>相似
如上图,是一个相似的简单表示,估计大家都能简单看懂,就不多做解释
实现思路
(1)获得摄像机的世界坐标
(2)通过写入对象深度获取鼠标点击屏幕位置对应的世界坐标
(3)通过代入想要的屏幕的高度来获取对象最后的位置
接下来是对思路进行逐步代码解释
private float _depthz;
private void OnMouseDrag()
{
_depthz = Camera.main.WorldToScreenPoint(this.transform.position).z;
Vector3 mouseToWorldPos = Camera.main.ScreenToWorldPoint
(new Vector3(Input.mousePosition.x, Input.mousePosition.y, _depthz));
Vector3 mainCameraPos = Camera.main.transform.position;
float proportion = (1.0f- mainCameraPos.y ) / (mouseToWorldPos.y-mainCameraPos.y );
Vector3 distance = (mouseToWorldPos-mainCameraPos) * proportion;
this.transform.position = mainCameraPos + distance;
}
第一段通过代入对象的位置获得了对应的屏幕深度
第二段通过带入屏幕坐标系下鼠标的xy值和之前获得的深度的到了鼠标点击位置(体现在世间空间下的)
第三段获得摄像机的世界空间位置
第四段通过想要对象在y轴上的最终坐标和鼠标位置坐标做相似比例(这里固定再xz平面上移动,高度为1,所以y轴的值固定为一,可以根据需要来调整对应的数值)
第五段通过比例获得到对象距离摄像机的距离
第六段通过摄像机的位置加上距离得到最终位置
如上便实现了在平面上拖拽
在本文基础上还可以引入offset(偏移值)来让对象被鼠标点中后不会突然有一小段位移,但本文不做衍射,对应知识比较简单本文只提供思路
如下为 offset思路
在点击物体对象时将鼠标在世界空间下的坐标和物体坐标做差值得到偏移值,在后续的位移中加上偏移值即可。