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

来源:互联网 发布:139 445端口 编辑:程序博客网 时间:2024/05/01 21:54

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

using UnityEngine;using System.Collections;//通过射线控制物体贴地面移动public class mouseDrag : MonoBehaviour {//声明从鼠标发出一条射线clickRayRay 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<Transform> ().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<Transform> ().localScale = new Vector3 (0,0,0);    }}}

以上是实现代码,具体问题可以看注释,场景运行截图如下:
移动前
移动后

阅读全文
0 0
原创粉丝点击