Unity 切换UI坐标和世界坐标

PC全局:


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;
            }
        }
    }
}

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; // 设置拖拽标志位为假
        }
    }
}

移动版:


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; // 设置拖拽标志位为假
            }
        }
    }
}

 

posted @   多见多闻  阅读(97)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示