【Daily Games——开发篇】:U3D下物体拖拽(全网最详细)&Camera 模式Orthographic/Perspective

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/iceSony/article/details/83996698

摄像机模式: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();
    }
}

猜你喜欢

转载自blog.csdn.net/iceSony/article/details/83996698