UGUI—变换模型(UITouchTransform)

作者:追风剑情 发布于:2019-11-20 11:01 分类:Unity3d

示例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
/// <summary>
/// 单指旋转模型,双指缩放模型
/// </summary>
public class UITouchTransform : MonoBehaviour
{
    public Transform target;
    public RectTransform rectTransform;
    public Camera uicamera;
    public float rotationSpeed = 1f;
    public float minScale = 0.1f;
    public float maxScale = 2f;
    public float mouseScaleSpeed = 0.0001f;//鼠标操作缩放速度
    public float touchScaleSpeed = 0.01f;  //触摸缩放速度
    public bool rotationX = true; //允许绕X轴旋转
    public bool rotationY = true; //允许绕Y轴旋转
    public bool allowScale = true; //是否允许缩放

    private Vector3 lastPosition;
    private float lastDistance = 0;

    void Awake()
    {
        if (target == null)
            target = transform;
        if (rectTransform == null)
            rectTransform = this.GetComponent<RectTransform>();
    }

    void Update()
    {
        if (Input.touchSupported) //设备是否支持触摸
        {
            int touchCount = Input.touchCount;
            if (touchCount <= 0)
                return;

            if (touchCount == 1)
            {
                TouchRotation();
            }
            else
            {
                TouchScale();
            }
        }
        else if (Input.mousePresent) //是否探测到鼠标
        {
            if (Input.GetKey(KeyCode.LeftControl))
                MouseScale();
            else
                MouseRotation();
        }
    }
    
    void MouseRotation()
    {
        if (Input.GetMouseButtonDown(0))
        {
            lastPosition = Input.mousePosition;
            return;
        }

        if (!Input.GetMouseButton(0))
            return;

        //判断鼠标是否在允许操作的区域内操作
        if (rectTransform != null && 
            !RectTransformUtility.RectangleContainsScreenPoint(rectTransform, Input.mousePosition, uicamera))
            return;

        if (rectTransform == null && IsPointerOverUI())
            return;

        Vector3 mousePosition = Input.mousePosition;
        Vector3 offset = mousePosition - lastPosition;
        float t = -offset.x;
        offset.x = offset.y;
        offset.y = t;
        if (!rotationX)
            offset.x = 0;
        if (!rotationY)
            offset.y = 0;
        target.Rotate(offset * rotationSpeed, Space.World);
        lastPosition = mousePosition;
    }

    void MouseScale()
    {
        if (!allowScale)
            return;

        if (Input.GetMouseButtonDown(0))
        {
            lastPosition = Input.mousePosition;
            return;
        }

        if (!Input.GetMouseButton(0))
            return;

        //判断鼠标是否在允许操作的区域内操作
        if (rectTransform != null &&
            !RectTransformUtility.RectangleContainsScreenPoint(rectTransform, Input.mousePosition, uicamera))
            return;

        if (rectTransform == null && IsPointerOverUI())
            return;

        float dir = Input.mousePosition.x - lastPosition.x;
        float lastDistance = Vector2.Distance(Input.mousePosition, lastPosition) * dir;
        float scale = Mathf.Clamp(target.localScale.x + lastDistance * mouseScaleSpeed, minScale, maxScale);
        target.localScale = new Vector3(scale, scale, scale);
        lastPosition = Input.mousePosition;
    }

    void TouchRotation()
    {
        //判断手指是否在允许操作的区域内操作
        if (rectTransform != null &&
            !RectTransformUtility.RectangleContainsScreenPoint(rectTransform, Input.touches[0].position, uicamera))
            return;

        if (rectTransform == null && IsPointerOverUI())
            return;

        Vector3 firstTouch = Input.touches[0].position;
        if (Input.touches[0].phase == TouchPhase.Began)
            lastPosition = firstTouch;

        Vector3 offset = firstTouch - lastPosition;
        float t = -offset.x;
        offset.x = offset.y;
        offset.y = t;
        if (!rotationX)
            offset.x = 0;
        if (!rotationY)
            offset.y = 0;
        target.Rotate(offset * rotationSpeed, Space.World);
        lastPosition = firstTouch;
    }

    void TouchScale()
    {
        if (!allowScale)
            return;

        //判断手指是否在允许操作的区域内操作
        if (rectTransform != null &&
            !RectTransformUtility.RectangleContainsScreenPoint(rectTransform, Input.touches[0].position, uicamera) &&
            !RectTransformUtility.RectangleContainsScreenPoint(rectTransform, Input.touches[1].position, uicamera))
            return;

        if (rectTransform == null && IsPointerOverUI())
            return;

        Vector3 firstTouch = Input.touches[0].position;
        Vector3 secondTouch = Input.touches[1].position;
        float twoTouchDistance = Vector2.Distance(firstTouch, secondTouch);
        if (Input.touches[1].phase == TouchPhase.Began) 
            lastDistance = twoTouchDistance;
        else if (Input.touches[1].phase == TouchPhase.Ended)
            //双指变单指的情况,不会触发touches[0]的Began阶段
            lastPosition = Input.touches[0].position;
        else if (Input.touches[0].phase == TouchPhase.Ended)
            //双指变单指的情况,不会触发touches[1]的Began阶段
            lastPosition = Input.touches[1].position;

        float scale = Mathf.Clamp(target.localScale.x + (twoTouchDistance - lastDistance) * touchScaleSpeed, minScale, maxScale);
        target.localScale = new Vector3(scale, scale, scale);
        lastDistance = twoTouchDistance;
    }

    public void SetTarget(Transform target)
    {
        this.target = target;
    }

    // 判断点击事件是否发生在UI上
    public static bool IsPointerOverUI()
    {
        bool over = false;
        if (Input.GetMouseButtonDown(0) || Input.GetMouseButton(0) || Input.touchCount > 0)
        {
#if UNITY_EDITOR || UNITY_STANDALONE_WIN
            if (EventSystem.current.IsPointerOverGameObject())
#elif UNITY_IPHONE || UNITY_ANDROID
            if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
#else
            if (EventSystem.current.IsPointerOverGameObject())
#endif
                over = true;

            else
                over = false;
        }
        return over;
    }
}


运行测试
555.gif

标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号