unity Drag image 放置物体

 DragObject挂在预制件上,其中LayerMask 为设置的可拖动的层级

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DragObject : MonoBehaviour
{
    //只针对指定的层级进行拖动
    public LayerMask _dragLayerMask;
    //指定当前要拖动的对象
    public Transform currentTransform;
    //是否可以拖动当前对象
    public bool isDrag = false;
    //用于存储当前需要拖动的对象在屏幕空间中的坐标
    Vector3 screenPos = Vector3.zero;
    //当前需要拖动对象的坐标相对于鼠标在世界空间坐标中的偏移量
    Vector3 offset = Vector3.zero;
    void Update()
    {

        if (Input.GetMouseButtonDown(0))
        {
            //将鼠标输入点转化为一条射线
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitinfo;
            //如果当前对象与指定的层级发生碰撞,表示当前对象可以被拖动
            if (Physics.Raycast(ray, out hitinfo, 1000f, _dragLayerMask))
            {
                isDrag = true;
                //将当前需要拖动的对象赋值为射线碰撞到的对象
                currentTransform = hitinfo.transform;
                //将当前对象的世界坐标转化为屏幕坐标
                screenPos = Camera.main.WorldToScreenPoint(currentTransform.position);
                //将鼠标的屏幕坐标转换为世界空间坐标,再与当前要拖动的对象计算两者的偏移量
                offset = currentTransform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPos.z));
            }
            else
            {
                isDrag = false;
            }
        }
        if (Input.GetMouseButton(0))
        {
            if (isDrag == true)
            {

                var currentScreenPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPos.z);
                //鼠标的屏幕空间坐标转化为世界坐标,并加上偏移量
                var currentPos = Camera.main.ScreenToWorldPoint(currentScreenPos) + offset;
                currentTransform.position = currentPos;
            }
        }
        if (Input.GetMouseButtonUp(0))
        {
            isDrag = false;
            currentTransform = null;
        }
    }
}

SelectobjectManager为整个管理脚本,通常挂在Canvas上,其中 LayerMask为可放置物体对象的层级对象,如plane

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SelectObjManager : MonoBehaviour
{

    private static SelectObjManager _instance;
    public static SelectObjManager Instance
    {
        get { return _instance; }
    }
    //物体z轴距摄像机的长度
    public float _zDistance = 50f;
    //对象的缩放系数
    public float _scaleFactor = 1.2f;
    //地面层级
    public LayerMask _groundLayerMask;
    int touchID;
    bool isDragging = false;
    bool isTouchInput = false;
    //是否是有效的放置(如果放置在地面上返回True,否则为False)
    bool isPlaceSuccess = false;
    //当前要被放置的对象
    public GameObject currentPlaceObj = null;
    //坐标在Y轴上的偏移量
    public float _YOffset = 0.5F;

    void Awake()
    {
        _instance = this;
    }
    void Update()
    {
        if (currentPlaceObj == null) return;

        if (CheckUserInput())
        {
            MoveCurrentPlaceObj();
        }
        else if (isDragging)
        {
            CheckIfPlaceSuccess();
        }
    }
    /// <summary>
    ///检测用户当前输入
    /// </summary>
    /// <returns></returns>
    bool CheckUserInput()
    {
#if !UNITY_EDITOR && (UNITY_ANDROID || UNITY_IOS)
        if (Input.touches.Length > 0) {
            if (!isTouchInput) {
                isTouchInput = true;
                touchID = Input.touches[0].fingerId;
                return true;
            } else if (Input.GetTouch (touchID).phase == TouchPhase.Ended) {
                isTouchInput = false;
                return false;
            } else {
                return true;
            }
        }
        return false;
#else
        return Input.GetMouseButton(0);
#endif
    }
    /// <summary>
    ///让当前对象跟随鼠标移动
    /// </summary>
    void MoveCurrentPlaceObj()
    {
        isDragging = true;
        Vector3 point;
        Vector3 screenPosition;
#if !UNITY_EDITOR && (UNITY_ANDROID || UNITY_IOS)
        Touch touch = Input.GetTouch (touchID);
        screenPosition = new Vector3 (touch.position.x, touch.position.y, 0);
#else
        screenPosition = Input.mousePosition;
#endif
        Ray ray = Camera.main.ScreenPointToRay(screenPosition);
        RaycastHit hitInfo;
        if (Physics.Raycast(ray, out hitInfo, 1000, _groundLayerMask))
        {
            point = hitInfo.point;
            isPlaceSuccess = true;
        }
        else
        {
            point = ray.GetPoint(_zDistance);
            isPlaceSuccess = false;
        }
        currentPlaceObj.transform.position = point + new Vector3(0, _YOffset, 0);
        currentPlaceObj.transform.localEulerAngles = new Vector3(0, 60, 0);
    }
    /// <summary>
    ///在指定位置化一个对象
    /// </summary>
    void CreatePlaceObj()
    {
        GameObject obj = Instantiate(currentPlaceObj) as GameObject;

        obj.transform.position = currentPlaceObj.transform.position;
        obj.transform.localEulerAngles = currentPlaceObj.transform.localEulerAngles;
        obj.transform.localScale *= _scaleFactor;
        //改变这个对象的Layer为Drag,以便后续拖动检测
        obj.layer = LayerMask.NameToLayer("Ground");
    }
    /// <summary>
    ///检测是否放置成功
    /// </summary>
    void CheckIfPlaceSuccess()
    {
        if (isPlaceSuccess)
        {
            CreatePlaceObj();
        }
        isDragging = false;
        currentPlaceObj.SetActive(false);
        currentPlaceObj = null;
    }
    /// <summary>
    /// 将要创建的对象传递给当前对象管理器
    /// </summary>
    /// <param name="newObject"></param>
    public void AttachNewObject(GameObject newObject)
    {
        if (currentPlaceObj)
        {
            currentPlaceObj.SetActive(false);
        }
        currentPlaceObj = newObject;
    }
}

 SelectImage挂在可拖拽的UI上

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class SelectImage : MonoBehaviour,IPointerDownHandler{
    //需要被实例化的预制
    public GameObject inistatePrefab;
    //实例化后的对象
    private GameObject inistateObj;

    // Use this for initialization
    void Start () {
        if (inistatePrefab==null)return;
        //实例化预制
        inistateObj=Instantiate(inistatePrefab) as GameObject;
        inistateObj.SetActive(false);
    }
    //实现鼠标按下的接口
    public void OnPointerDown(PointerEventData eventData)
    {
        inistateObj.SetActive(true);

        //将当前需要被实例化的对象传递到管理器中
        SelectObjManager.Instance.AttachNewObject(inistateObj);
    }
}

 

简单易懂

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值