欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 幼教 > 【Unity拖拽物体】实现对点中的3D物体进行拖拽的功能

【Unity拖拽物体】实现对点中的3D物体进行拖拽的功能

2024/10/24 23:19:37 来源:https://blog.csdn.net/leoysq/article/details/139779213  浏览:    关键词:【Unity拖拽物体】实现对点中的3D物体进行拖拽的功能

场景结构,两个普通模型

第一种 脚本所挂载的物体才可以被拖拽 【PC鼠标版本】

using UnityEngine;// 这个脚本实现了,本脚本所在的游戏物体能够被拖拽
public class DragObjectT : MonoBehaviour
{private Vector3 screenPoint; // 存储物体在屏幕上的位置private Vector3 offset; // 存储鼠标点击位置与物体实际位置的偏移量private bool isDragging = false; // 标志位,表示物体是否正在被拖拽void Update(){// 检测鼠标左键是否按下if (Input.GetMouseButtonDown(0)){RaycastHit hit;Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // 从摄像机发射一条射线到鼠标位置// 使用射线检测是否击中了某个物体if (Physics.Raycast(ray, out hit)){// 检查被击中的物体是否是本脚本所附加的物体if (hit.collider.gameObject == gameObject){screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position); // 将物体的世界坐标转换为屏幕坐标offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z)); // 计算偏移量isDragging = true; // 设置拖拽标志位为真}}}// 检测鼠标左键是否持续按下并且物体正在被拖拽if (Input.GetMouseButton(0) && isDragging){Vector3 curScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z); // 获取当前鼠标位置的屏幕坐标Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + offset; // 将屏幕坐标转换为世界坐标并加上偏移量transform.position = curPosition; // 更新物体的位置}// 检测鼠标左键是否释放if (Input.GetMouseButtonUp(0)){isDragging = false; // 设置拖拽标志位为假}}
}

这个脚本通过检测鼠标输入来实现物体的拖拽功能。以下是详细的步骤解释:

  1. 变量声明

    • screenPoint:存储物体在屏幕上的位置。

    • offset:存储鼠标点击位置与物体实际位置的偏移量。

    • isDragging:标志位,表示物体是否正在被拖拽。

  2. Update方法

    • 检测鼠标左键是否按下(Input.GetMouseButtonDown(0))。

    • 如果按下,从摄像机发射一条射线到鼠标位置(Camera.main.ScreenPointToRay(Input.mousePosition))。

    • 使用射线检测是否击中了某个物体(Physics.Raycast(ray, out hit))。

    • 检查被击中的物体是否是本脚本所附加的物体(hit.collider.gameObject == gameObject)。

    • 如果是,将物体的世界坐标转换为屏幕坐标(Camera.main.WorldToScreenPoint(gameObject.transform.position)),并计算偏移量(offset)。

    • 设置拖拽标志位为真(isDragging = true)。

  3. 拖拽逻辑

    • 检测鼠标左键是否持续按下并且物体正在被拖拽(Input.GetMouseButton(0) && isDragging)。

    • 获取当前鼠标位置的屏幕坐标(curScreenPoint)。

    • 将屏幕坐标转换为世界坐标并加上偏移量(curPosition)。

    • 更新物体的位置(transform.position = curPosition)。

  4. 释放逻辑

    • 检测鼠标左键是否释放(Input.GetMouseButtonUp(0))。

    • 设置拖拽标志位为假(isDragging = false)。

 

以下是适用于移动端触摸屏的版本:

using UnityEngine;// 这个脚本实现了,本脚本所在的游戏物体能够被触摸拖拽
public class DragObjectT : MonoBehaviour
{private Vector3 screenPoint; // 存储物体在屏幕上的位置private Vector3 offset; // 存储触摸点击位置与物体实际位置的偏移量private bool isDragging = false; // 标志位,表示物体是否正在被拖拽void Update(){// 检测是否有触摸输入if (Input.touchCount > 0){Touch touch = Input.GetTouch(0); // 获取第一个触摸点// 检测触摸开始if (touch.phase == TouchPhase.Began){RaycastHit hit;Ray ray = Camera.main.ScreenPointToRay(touch.position); // 从摄像机发射一条射线到触摸位置// 使用射线检测是否击中了某个物体if (Physics.Raycast(ray, out hit)){// 检查被击中的物体是否是本脚本所附加的物体if (hit.collider.gameObject == gameObject){screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position); // 将物体的世界坐标转换为屏幕坐标offset = gameObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, screenPoint.z)); // 计算偏移量isDragging = true; // 设置拖拽标志位为真}}}// 检测触摸移动并且物体正在被拖拽if (touch.phase == TouchPhase.Moved && isDragging){Vector3 curScreenPoint = new Vector3(touch.position.x, touch.position.y, screenPoint.z); // 获取当前触摸位置的屏幕坐标Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + offset; // 将屏幕坐标转换为世界坐标并加上偏移量transform.position = curPosition; // 更新物体的位置}// 检测触摸结束if (touch.phase == TouchPhase.Ended){isDragging = false; // 设置拖拽标志位为假}}}
}

这个脚本通过检测触摸输入来实现物体的拖拽功能。以下是详细的步骤解释:

  1. 变量声明

    • screenPoint:存储物体在屏幕上的位置。

    • offset:存储触摸点击位置与物体实际位置的偏移量。

    • isDragging:标志位,表示物体是否正在被拖拽。

  2. Update方法

    • 检测是否有触摸输入(Input.touchCount > 0)。

    • 获取第一个触摸点(Touch touch = Input.GetTouch(0))。

    • 检测触摸开始(touch.phase == TouchPhase.Began)。

    • 如果触摸开始,从摄像机发射一条射线到触摸位置(Camera.main.ScreenPointToRay(touch.position))。

    • 使用射线检测是否击中了某个物体(Physics.Raycast(ray, out hit))。

    • 检查被击中的物体是否是本脚本所附加的物体(hit.collider.gameObject == gameObject)。

    • 如果是,将物体的世界坐标转换为屏幕坐标(Camera.main.WorldToScreenPoint(gameObject.transform.position)),并计算偏移量(offset)。

    • 设置拖拽标志位为真(isDragging = true)。

  3. 拖拽逻辑

    • 检测触摸移动并且物体正在被拖拽(touch.phase == TouchPhase.Moved && isDragging)。

    • 获取当前触摸位置的屏幕坐标(curScreenPoint)。

    • 将屏幕坐标转换为世界坐标并加上偏移量(curPosition)。

    • 更新物体的位置(transform.position = curPosition)。

  4. 释放逻辑

    • 检测触摸结束(touch.phase == TouchPhase.Ended)。

    • 设置拖拽标志位为假(isDragging = false)。

第二种 全局脚本,所有有碰撞器的物体都可以被拖拽

using UnityEngine;public class GlobalDragManager : MonoBehaviour
{private GameObject draggedObject;private Vector3 screenPoint;private Vector3 offset;void Update(){if (Input.GetMouseButtonDown(0)){RaycastHit hit;Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);if (Physics.Raycast(ray, out hit)){draggedObject = hit.collider.gameObject;screenPoint = Camera.main.WorldToScreenPoint(draggedObject.transform.position);offset = draggedObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));}}if (Input.GetMouseButton(0) && draggedObject != null){Vector3 curScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + offset;draggedObject.transform.position = curPosition;}if (Input.GetMouseButtonUp(0)){draggedObject = null;}}
}

 

这个脚本的工作原理如下:

  1. Update方法

    • 在每一帧中,检查是否按下了鼠标左键(Input.GetMouseButtonDown(0))。

    • 如果按下了鼠标左键,发射一条从主摄像机到鼠标位置的射线(Physics.Raycast(ray, out hit))。

    • 如果射线击中了某个物体(hit.collider.gameObject),则将该物体的引用存储在draggedObject变量中,并记录物体的屏幕位置和偏移量。

  2. 拖动逻辑

    • 如果鼠标左键保持按下并且draggedObject不为空,根据当前鼠标位置计算物体的新位置(curPosition),并将其应用到物体的变换位置上(draggedObject.transform.position = curPosition)。

  3. 释放物体

    • 当鼠标左键释放时(Input.GetMouseButtonUp(0)),将draggedObject设置为null,表示没有物体正在被拖动。

通过这种方式,你只需要挂载一个脚本到场景中的某个空游戏对象上,就可以实现对所有带有碰撞器的物体的拖拽功能,而不需要为每个物体单独挂载脚本。

适用于移动端触摸屏交互的版本

using UnityEngine;public class GlobalDragManager : MonoBehaviour
{private GameObject draggedObject;private Vector3 screenPoint;private Vector3 offset;void Update(){if (Input.touchCount > 0){Touch touch = Input.GetTouch(0);if (touch.phase == TouchPhase.Began){RaycastHit hit;Ray ray = Camera.main.ScreenPointToRay(touch.position);if (Physics.Raycast(ray, out hit)){draggedObject = hit.collider.gameObject;screenPoint = Camera.main.WorldToScreenPoint(draggedObject.transform.position);offset = draggedObject.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, screenPoint.z));}}if (touch.phase == TouchPhase.Moved && draggedObject != null){Vector3 curScreenPoint = new Vector3(touch.position.x, touch.position.y, screenPoint.z);Vector3 curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + offset;draggedObject.transform.position = curPosition;}if (touch.phase == TouchPhase.Ended){draggedObject = null;}}}
}

这个脚本的工作原理如下:

  1. Update方法

    • 在每一帧中,检查是否有触摸输入(Input.touchCount > 0)。

    • 如果有触摸输入,获取第一个触摸点(Touch touch = Input.GetTouch(0))。

  2. 触摸开始

    • 如果触摸开始(touch.phase == TouchPhase.Began),发射一条从主摄像机到触摸位置的射线(Physics.Raycast(ray, out hit))。

    • 如果射线击中了某个物体(hit.collider.gameObject),则将该物体的引用存储在draggedObject变量中,并记录物体的屏幕位置和偏移量。

  3. 触摸移动

    • 如果触摸移动(touch.phase == TouchPhase.Moved)并且draggedObject不为空,根据当前触摸位置计算物体的新位置(curPosition),并将其应用到物体的变换位置上(draggedObject.transform.position = curPosition)。

  4. 触摸结束

    • 当触摸结束(touch.phase == TouchPhase.Ended),将draggedObject设置为null,表示没有物体正在被拖动。

通过这种方式,你可以在移动端触摸屏上实现对所有带有碰撞器的物体的拖拽功能,而不需要为每个物体单独挂载脚本。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com