Unity3D三维坐标(X,Z轴)下物体拖动移动(贴地面移动)实现并实现物体碰撞检测

之前做过一个在Unity中实现二维(X,Z轴)拖动的效果,思路是直接获取鼠标坐标并且将其赋给GameObject。然而在三维(X,Y轴)的移动中,因为鼠标对于Scene中并没有Z轴的概念,因此无法使用直接赋值的方法来移动GameObject。所以在此引用了Unity中射线的概念来实现物体的三维移动,但是在物体的移动方面,因为物体也是通过射线碰撞位置去改变物体的坐标,因此会出现两个物体无法完成碰撞并且重叠的现象,因此想到了可以通过记录前一帧物体位置的方法,并结合碰撞器,当检测到碰撞时即返回上一帧的位置来解决碰撞的问题。具体代码如下所示:

using UnityEngine;
using System.Collections;
//通过射线控制物体贴地面移动
public class mouseDrag : MonoBehaviour {

//声明从鼠标发出一条射线clickRay
Ray clickRay;

//声明clickRay与游戏物体的碰撞
RaycastHit clickPoint;

//声明isCollided变量和canMove变量,记录是否碰撞和是否可以移动
private bool isCollided = false;
private bool canMove = true;

//声明clickRay与地面的碰撞
RaycastHit posPoint;

//设置地面层,我的地面层是第8层,所以是8。
LayerMask mask=1<<8;

//初始化父物体和速度变量
GameObject parent=null;
public float speed=10f;

//初始化位置信息
public Vector3 old;
void Start () {
}
void Update(){

    clickRay=Camera.main.ScreenPointToRay(Input.mousePosition);
    //记录上一帧GameObject位置
    if (!isCollided) {
        old = this.transform.position;
    }
}
void OnMouseDown()
{
    //如果射线与物体相碰,则调用OnMouseDrag()
    if(Physics.Raycast (clickRay,out clickPoint))
    {
        OnMouseDrag();
    }
}
void OnMouseUp(){
    //鼠标按下时才可移动物体
    canMove = true;
}
void OnMouseDrag()
{

    //取射线与地面相碰的坐标,赋给mouseMove,再把mouseMove的x坐标和z坐标赋给target,y坐标不变(因为是贴在地面上移动),并利用跟随鼠标移动的方式移动物体
    Physics.Raycast (clickRay ,out posPoint,Mathf.Infinity,mask.value);
    Vector3 mouseMove=posPoint.point;
    Vector3 target=(new Vector3(mouseMove.x,this.transform.position.y,mouseMove.z));
    float step=speed*Time.deltaTime;
    if (canMove) {
        transform.position=Vector3.MoveTowards(transform.position,target,step);
    }

    //判断物体是否还在原来区域,如果不在则返回到生成点
    if ((transform.position.x > 11) || (transform.position.x < -11) ||
        (transform.position.z > 10) || (transform.position.z < -11)) {
        transform.position =old;
    }
    return;
}
//利用三种碰撞检测来提示用户摆放物体重叠
void OnTriggerEnter(Collider e)  {
    //此处利用标签检测父物体是否发生碰撞,父物体标签为Device
    if (e.gameObject.tag.CompareTo("Device")==0)  
    {  
        isCollided = true;
        canMove = false;
    }  
}
void OnTriggerStay(Collider e){
    if (e.gameObject.tag.CompareTo ("Device") == 0) {
        isCollided = true;
        //显示提示框,具体提示框自行设计
        GameObject.Find("PromptCollisionText").GetComponent ().localScale = new Vector3 (2,2,1);
        //将物体位置返回为上一帧位置
        this.transform.position = old;
    }
}
void OnTriggerExit(Collider e){
    if (e.gameObject.tag.CompareTo ("Device") == 0) {
        isCollided = false;
        //隐藏提示框
        GameObject.Find("PromptCollisionText").GetComponent ().localScale = new Vector3 (0,0,0);
    }
}}

以上是实现代码,具体问题可以看注释,场景运行截图如下:
Unity3D三维坐标(X,Z轴)下物体拖动移动(贴地面移动)实现并实现物体碰撞检测_第1张图片
Unity3D三维坐标(X,Z轴)下物体拖动移动(贴地面移动)实现并实现物体碰撞检测_第2张图片

你可能感兴趣的:(程序猿之洞)