Unity在3D空间里同时满足鼠标和触屏拖动物体移动

在3D空间里同时满足鼠标和触屏上拖动物体移动

下面展示一些 内联代码片

// An highlighted block
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using zSpace.Core;
//动态设置脚本执行顺序DefaultExecutionOrder
[DefaultExecutionOrder(ZCameraRig.ScriptPriority - 2)]
public class StylusDragable : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler,IPointerDownHandler,IPointerUpHandler
{
    private Vector3 _initialGrabOffset = Vector3.zero;
    private Quaternion _initialGrabRotation = Quaternion.identity;
    private bool _isKinematic = false;
    private enum Mode { None, Drag, Rotate }
    private enum Source { None, Stylus, Touch, Mouse }
    private Source m_souce = Source.None;
    private Mode m_mode = Mode.None;
    private float m_distance;
    private float m_rotateSpeed = 0.2f;
    private Camera m_eventCamera = null;
    private int m_currentPointerId = -1000;
    public event Action StartDragEvent;
    public event Action EndDragEvent;

    public Action<Collider> OnTriggerEnterListening;
    public Action<Collider> OnTriggerExitListening;

    private void OnTriggerEnter(Collider other)
    {
        OnTriggerEnterListening?.Invoke(other);
    }
    
    private void OnTriggerExit(Collider other)
    {
        OnTriggerExitListening?.Invoke(other);
    }
    public void OnBeginDrag(PointerEventData eventData)
    {
        if (m_currentPointerId > -10) return;

        if (eventData.pointerId < 0)
            MouseOnBeginDrag(eventData);
        else
            TouchOnBeginDrag(eventData);

        StartDragEvent?.Invoke();
        if (m_mode != Mode.None && m_currentPointerId > -10) RigidbodyFreeze();
    }
    public void OnDrag(PointerEventData eventData)
    {
        if (eventData.pointerId != m_currentPointerId) return;

        if (m_souce == Source.Touch)
            TouchOnDrag(eventData);
        else if (m_souce == Source.Mouse)
            MouseOnDrag(eventData);
        StartDragEvent?.Invoke();
    }
    public void OnEndDrag(PointerEventData eventData)
    {
        if (eventData.pointerId != m_currentPointerId) return;

        if (m_mode != Mode.None) RigidbodyRestore();

        if (m_souce == Source.Touch)
            TouchOnEndDrag(eventData);
        else if (m_souce == Source.Mouse)
            MouseOnEndDrag(eventData);
        EndDragEvent?.Invoke();
        m_mode = Mode.None;
        m_souce = Source.None;
        m_eventCamera = null;
        m_currentPointerId = -1000; 
    }
    #region Touch
    public void TouchOnBeginDrag(PointerEventData eventData)
    {
        m_souce = Source.Touch;
        m_mode = Mode.None;

        if (eventData.pointerId != 0) return;
        m_currentPointerId = eventData.pointerId;

        if (Input.touchCount == 1)
        {
            m_mode = Mode.Drag;
            RaycastResult rayRes = eventData.pointerCurrentRaycast;
            if (rayRes.module == null || rayRes.module.eventCamera == null) return;
            this.m_distance = (Camera.main.transform.position - rayRes.worldPosition).magnitude;
            this.m_eventCamera = Camera.main;
            this._initialGrabOffset = Quaternion.Inverse(this.transform.rotation) * (this.transform.position - rayRes.worldPosition);
            this._initialGrabRotation = Quaternion.Inverse(Quaternion.Euler(rayRes.worldNormal)) * this.transform.rotation;
        }
        else
        {
            m_mode = Mode.Rotate;
            this._initialGrabRotation = this.transform.rotation;
            this._initialGrabOffset = eventData.position;
        }
    }
    public void TouchOnDrag(PointerEventData eventData)
    {
        if (eventData.pointerId != 0) return;

        if (m_mode == Mode.Drag)
        {
            if (this.m_eventCamera == null) return;
            Ray ray = this.m_eventCamera.ScreenPointToRay(new Vector3(eventData.position.x, eventData.position.y, m_distance));
            this.transform.position = (this.m_eventCamera.transform.position + ray.direction * m_distance) + (this.transform.rotation * this._initialGrabOffset);
        }
        else if (m_mode == Mode.Rotate)
        {
            Vector2 delta = eventData.position - new Vector2(_initialGrabOffset.x, _initialGrabOffset.y);
            Quaternion q1 = Quaternion.AngleAxis(delta.x * m_rotateSpeed, Vector3.down);
            Quaternion q2 = Quaternion.AngleAxis(delta.y * m_rotateSpeed, Vector3.right);
            this.transform.rotation = q2 * q1 * this._initialGrabRotation;
        }
    }
    public void TouchOnEndDrag(PointerEventData eventData)
    {

    }
    #endregion
    #region Mouse
    public void MouseOnBeginDrag(PointerEventData eventData)
    {
        m_souce = Source.Mouse;
        m_mode = Mode.None;
        m_currentPointerId = eventData.pointerId;

        if (eventData.button == PointerEventData.InputButton.Left)
        {
            m_mode = Mode.Drag;
            RaycastResult rayRes = eventData.pointerCurrentRaycast;
            //if (rayRes.module == null || rayRes.module.eventCamera == null) return;
            this.m_distance = (Camera.main.transform.position - rayRes.worldPosition).magnitude;
            this.m_eventCamera = Camera.main;
            this._initialGrabOffset = Quaternion.Inverse(this.transform.rotation) * (this.transform.position - rayRes.worldPosition);
            this._initialGrabRotation = Quaternion.Inverse(Quaternion.Euler(rayRes.worldNormal)) * this.transform.rotation;
        }
        else if (eventData.button == PointerEventData.InputButton.Right)
        {
            m_mode = Mode.Rotate;
            this._initialGrabRotation = this.transform.rotation;
            this._initialGrabOffset = eventData.position;
        }
    }
    public void MouseOnDrag(PointerEventData eventData)
    {
        if (m_mode == Mode.Drag)
        {
            if (this.m_eventCamera == null) return;
            Ray ray = this.m_eventCamera.ScreenPointToRay(new Vector3(eventData.position.x, eventData.position.y, m_distance));
            this.transform.position = (this.m_eventCamera.transform.position + ray.direction * m_distance) + (this.transform.rotation * this._initialGrabOffset);
        }
        else if (m_mode == Mode.Rotate)
        {
            Vector2 delta = eventData.position - new Vector2(_initialGrabOffset.x, _initialGrabOffset.y);
            Quaternion q1 = Quaternion.AngleAxis(delta.x * m_rotateSpeed, Vector3.down);
            Quaternion q2 = Quaternion.AngleAxis(delta.y * m_rotateSpeed, Vector3.right);
            this.transform.rotation = q2 * q1 * this._initialGrabRotation;
        }
    }
    public void MouseOnEndDrag(PointerEventData eventData)
    {

    }
    #endregion

    private void RigidbodyFreeze()
    {
        var rigidbody = this.GetComponent<Rigidbody>();
        if (rigidbody != null)
        {
            this._isKinematic = rigidbody.isKinematic;
            rigidbody.isKinematic = true;
        }
    }
    private void RigidbodyRestore()
    {
        var rigidbody = this.GetComponent<Rigidbody>();
        if (rigidbody != null)
        {
            rigidbody.isKinematic = this._isKinematic;
        }
    }
    
    private void OnDisable()
    {
        EndDragEvent?.Invoke();
    }

    public void OnPointerDown(PointerEventData eventData)
    {

        StartDragEvent?.Invoke();
    }

    public void OnPointerUp(PointerEventData eventData)
    {

        EndDragEvent?.Invoke();
    }

在相机上添加射线笔
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity中,我们可以使用以下步骤来实现鼠标拖拽物体移动,并限制拖动范围: 1.创建一个空物体作为拖拽物体的父级,将需要拖拽的物体作为子级添加到其中。 2.在父级上添加一个Box Collider组件,将其设置为Is Trigger。 3.添加一个脚本来控制拖拽行为。在脚本中声明一个变量来存储拖拽物体的初始位置,一个变量来存储鼠标按下时的幕坐标,以及一个变量来存储拖拽物体的限制范围。 4.在Update()函数中检测鼠标是否按下。如果按下,记录下鼠标按下时的幕坐标,并将拖拽物体的初始位置设置为当前位置。 5.如果鼠标一直按下,计算鼠标移动的距离,并将拖拽物体的位置设置为初始位置加上鼠标移动的距离。同时,检测拖拽物体是否超出了限制范围,如果超出了,将其位置设置为限制范围内的最近位置。 6.最后,将脚本添加到父级物体上,运行游戏即可实现鼠标拖拽物体移动,并限制拖动范围。 下面是示例代码: ``` using UnityEngine; public class DragObject : MonoBehaviour { private Vector3 initialPosition; private Vector3 mousePosition; private Vector3 limitMin; private Vector3 limitMax; private void Start() { // 设置拖拽物体的限制范围 limitMin = gameObject.GetComponent<BoxCollider>().bounds.min; limitMax = gameObject.GetComponent<BoxCollider>().bounds.max; } private void OnMouseDown() { // 记录鼠标按下时的幕坐标和拖拽物体的初始位置 mousePosition = Input.mousePosition; initialPosition = transform.position; } private void OnMouseDrag() { // 计算鼠标移动的距离,并设置拖拽物体的位置 Vector3 offset = Input.mousePosition - mousePosition; Vector3 newPosition = initialPosition + offset; // 检测拖拽物体是否超出限制范围,如果超出了,将其位置设置为限制范围内的最近位置 newPosition.x = Mathf.Clamp(newPosition.x, limitMin.x, limitMax.x); newPosition.y = Mathf.Clamp(newPosition.y, limitMin.y, limitMax.y); newPosition.z = Mathf.Clamp(newPosition.z, limitMin.z, limitMax.z); transform.position = newPosition; } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值