摄像机模式:Orthographic/Perspective
也就是一个是投影(所有物体原尺寸投射到屏幕上)
透视也就是人眼视角,你看太阳是不是就和你的手指头一样大= =
首先我们的游戏分为2D与3D
如果是UI有实现的Drag接口,详见->https://blog.csdn.net/iceSony/article/details/82957793
但我们涉及的其实是GameObject的拖拽
PS:如果之后你想做得点击一些物体的某个进行拖拽,可以用到射线检测,这篇就不涉及了
如何获取鼠标位置
如果是2D游戏,摄像机设置为Perspective模式
这里我们介绍一下获取鼠标当前屏幕坐标位置:input.mousePosition
从屏幕左下角原点开始,根据你设置的屏幕大小,那么左下角就是(0,0),右上角就是(1080,1920)
这时候你可能想到方法,直接将鼠标位置赋值给物体坐标不就行了吗?
事实上,简单的update中的一句transform.position = input.mousePosition一定会让你大失所望!
很简单,因为你不会希望从左移动到右边移动到(1920,0,0)位置
你的物体早就飞出边界了
所以直接设置坐标的想法是错误的
我们要做一步转化成世界坐标,这样拖拽的时候距离才对
具体实现:Camera.main.ScreenToWorldPoint(Input.mousePosition)
这个函数将屏幕坐标转换为游戏中的世界坐标,实际效果就是文末的拖拽脚本
你的物体会跟着按下鼠标后移动方向移动正确的距离,你鼠标按住移动多少,物体就拖拽多少
但是3D游戏一般是采用Orthographic模式
这时候你会发现采用上述思路的物体的怎么拖拽都不能移动
怎么回事呢小老弟?
我们来思考一下问题肯定出在ScreenToWorldPoint函数上
在2D下,移动鼠标无论你的鼠标位于摄像机多远,你的移动都是一样的距离(这句话听不懂没问题继续看)
在3D下,移动鼠标距离你觉得是多少呢?
你将鼠标从界面坐标(0,0)移动到(1920,0),你以为转换之后是对应的长度
但事实上这个长度的转化和距离摄像机的距离有关
他是从摄像机的远近参数进行转化,也就是说这个时候的坐标转化
这时候我们需要从物体到摄像机的z轴差来做这件事
打个比方,你将鼠标放到摄像机左边缘
当鼠标位置+(0,0,10),即鼠标在距离10的时候的对应的Position.x 不再是0,而是10
当鼠标位置+(0,0,100),即鼠标在距离100的时候的对应的Position.x 不再是10,而是30
会有一个转化的过程,设置的距离越远对应的位置也越大
为了确定移动的距离我们在转化时候加上这个距离
也就是转化的时候加上posZ(posZ也就是摄像机与游戏对象在Z轴上的差值)
Camera.main.ScreenToWorldPoint(Input.mousePosition+new Vector3(0,0,posZ))
完美
这时候效果就和2D下面拖拽一样了
如果是移动端获取的是TouchPosition 原理是一样的
为了不考虑摄像机的模式,直接采用加上Posz的方式就行
Over
拖拽思路:先在点击事件触发之后记录之前一帧的位置——》记录触发这一帧的鼠标世界坐标位置——》移动鼠标之后每一帧的鼠标世界坐标 - 前一帧的鼠标坐标 ——》transform.Translate(插值)
这样就可以连续移动
物体拖拽的具体实现
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveController : MonoBehaviour
{
private bool moveFlag = false;
private Vector3 prePos, nowPos;
void MoveByTouch()
{
if (Input.GetMouseButton(0))
{
if (!moveFlag)
{
moveFlag = true;
prePos = Camera.main.ScreenToWorldPoint(Input.mousePosition+new
Vector3(0,0,-transform.position.y+Camera.main.transform.position.y));
}
nowPos = Camera.main.ScreenToWorldPoint(Input.mousePosition+ new Vector3(0,
0, -transform.position.y + Camera.main.transform.position.y));
Vector3 moveDis = nowPos - prePos;
prePos = nowPos;
transform.Translate(new Vector3(moveDis.x, 0, moveDis.z));
}
else
{
moveFlag = false;
}
}
void Update ()
{
MoveByTouch();
}
}