中餐厅摆台 点击UI图片拖拽预制体到桌面并 实现预制体拖拽

📅 2026/7/1 1:46:55
中餐厅摆台 点击UI图片拖拽预制体到桌面并 实现预制体拖拽
1、准备桌面 和 酒杯先在Scene窗口中调好相对位置然后将酒杯拖拽到project目录中生成预制体。需要给预制体增加一个脚本就是 using UnityEngine;public class ItemHeight : MonoBehaviour{// 在预制体Inspector手动填好这个物品放在桌面需要的世界Ypublic float tableY 0.869f;}填好酒杯的位置因为拖拽到桌面的时候position中的xz都可以用鼠标的但是高度必须用自身的。不然容易穿模或者飞起。在写代码前需要给桌面一个box collisder 不然射线检测不到。using UnityEngine;using UnityEngine.UI;using UnityEngine.EventSystems;public class ItemDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler{// 酒杯预制体public GameObject wineGlassPrefab;// 拖拽时跟随鼠标的临时物体private GameObject dragTempObj;// UI原图初始位置固定不动private Vector2 uiOriginPos;void Awake(){uiOriginPos transform.position;}// 开始拖拽public void OnBeginDrag(PointerEventData eventData){// UI图标固定不动恢复原始位置transform.position uiOriginPos;// 生成临时3D酒杯跟随鼠标dragTempObj Instantiate(wineGlassPrefab);// 临时物体关闭碰撞避免射线干扰Collider col dragTempObj.GetComponentCollider();if (col ! null) col.enabled false;}// 拖拽过程临时酒杯跟随鼠标public void OnDrag(PointerEventData eventData){// UI始终固定原位transform.position uiOriginPos;if (dragTempObj ! null){Ray ray Camera.main.ScreenPointToRay(eventData.position);RaycastHit hit;// 地面空白处也更新位置高度抬高一点防止穿模if (Physics.Raycast(ray, out hit, 1000)){dragTempObj.transform.position hit.point Vector3.up * 0.02f;}else{// 没碰到物体鼠标远处显示dragTempObj.transform.position ray.GetPoint(5);}}}// 松开鼠标放置正式物体public void OnEndDrag(PointerEventData eventData){// 销毁跟随鼠标的临时酒杯if (dragTempObj ! null){Destroy(dragTempObj);dragTempObj null;}// 射线检测桌面生成正式酒杯Ray ray Camera.main.ScreenPointToRay(eventData.position);RaycastHit hit;if (Physics.Raycast(ray, out hit)){// 判定是桌子if (!hit.collider.CompareTag(Table)) return;GameObject newGlass Instantiate(wineGlassPrefab);// 读取预制体内部提前存好的Y值ItemHeight heightData newGlass.GetComponentItemHeight();float targetY heightData.tableY;// XZ用鼠标点击Y直接用预制体内存好的固定数值Vector3 placePos new Vector3(hit.point.x, targetY, hit.point.z);newGlass.transform.position placePos;newGlass.transform.SetParent(hit.transform);}}}给这个image加一个itemDrag的脚本并把酒杯预制体拖拽进去。using UnityEngine;using UnityEngine.UI;using UnityEngine.EventSystems;public class ItemDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler{// 酒杯预制体public GameObject wineGlassPrefab;// 拖拽时跟随鼠标的临时物体private GameObject dragTempObj;// UI原图初始位置固定不动private Vector2 uiOriginPos;void Awake(){uiOriginPos transform.position;}// 开始拖拽public void OnBeginDrag(PointerEventData eventData){// UI图标固定不动恢复原始位置transform.position uiOriginPos;// 生成临时3D酒杯跟随鼠标dragTempObj Instantiate(wineGlassPrefab);// 临时物体关闭碰撞避免射线干扰Collider col dragTempObj.GetComponentCollider();if (col ! null) col.enabled false;}// 拖拽过程临时酒杯跟随鼠标public void OnDrag(PointerEventData eventData){// UI始终固定原位transform.position uiOriginPos;if (dragTempObj ! null){Ray ray Camera.main.ScreenPointToRay(eventData.position);RaycastHit hit;// 地面空白处也更新位置高度抬高一点防止穿模if (Physics.Raycast(ray, out hit, 1000)){dragTempObj.transform.position hit.point Vector3.up * 0.02f;}else{// 没碰到物体鼠标远处显示dragTempObj.transform.position ray.GetPoint(5);}}}// 松开鼠标放置正式物体public void OnEndDrag(PointerEventData eventData){// 销毁跟随鼠标的临时酒杯if (dragTempObj ! null){Destroy(dragTempObj);dragTempObj null;}// 射线检测桌面生成正式酒杯Ray ray Camera.main.ScreenPointToRay(eventData.position);RaycastHit hit;if (Physics.Raycast(ray, out hit)){// 判定是桌子if (!hit.collider.CompareTag(Table)) return;GameObject newGlass Instantiate(wineGlassPrefab);// 读取预制体内部提前存好的Y值ItemHeight heightData newGlass.GetComponentItemHeight();float targetY heightData.tableY;// XZ用鼠标点击Y直接用预制体内存好的固定数值Vector3 placePos new Vector3(hit.point.x, targetY, hit.point.z);newGlass.transform.position placePos;newGlass.transform.SetParent(hit.transform);}}}这样就实现了拖拽如果还想拖拽已经生成的物体需要给预制体加上下面这个脚本并给预制体加上box collisder, 给主相机 加上 physics RayCaster和eventSystem。using UnityEngine;using UnityEngine.EventSystems;// 拖拽场景中已经生成好的桌面3D物品public class TableObjectDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler{// 鼠标点击点 和 物体坐标的偏移量防止拖拽时物体瞬移private Vector3 dragOffset;// 桌子基准高度private float tableStandardY;// 开始拖拽鼠标按下杯子瞬间执行public void OnBeginDrag(PointerEventData eventData){Ray ray Camera.main.ScreenPointToRay(eventData.position);RaycastHit hit;if (Physics.Raycast(ray, out hit)){// 记录桌子高度全程锁定Y不变化tableStandardY hit.transform.position.y;// 计算偏移保证鼠标点杯子任意位置都能平稳拖动dragOffset transform.position - hit.point;}}// 拖拽持续中鼠标移动实时更新杯子位置public void OnDrag(PointerEventData eventData){Ray ray Camera.main.ScreenPointToRay(eventData.position);RaycastHit hit;if (Physics.Raycast(ray, out hit)){// X、Z跟随鼠标Y固定桌面高度不会嵌入桌子、不会飘高Vector3 newPos new Vector3(hit.point.x dragOffset.x,tableStandardY,hit.point.z dragOffset.z);transform.position newPos;}}// 拖拽结束松开鼠标public void OnEndDrag(PointerEventData eventData){// 可选拓展拖到桌面外自动吸附回桌面这里留空你按需加逻辑}}