Unity----Panes, panels and windows(官方教程)

本文介绍如何使用Unity实现UI面板的拖拽功能、限制拖拽范围及调整面板大小。通过自定义脚本DragPanel、ResizePanel等,实现了鼠标点击拖动UI面板、限定拖动边界并调整面板尺寸等功能。

  • 通过panel创建一个窗口,实现拖拽,限制拖拽区域,改变窗口大小

原视频链接:https://unity3d.com/cn/learn/tutorials/modules/intermediate/live-training-archive/panels-panes-windows?playlist=17111


1,通过接口IPointerDownHandler, IDragHandler在函数OnPointerDown, OnDrag中实现panels本地坐标的移动,完成拖拽功能

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;

public class DragPanel : MonoBehaviour, IPointerDownHandler, IDragHandler
{

    private Vector2 pointerOffset;
    private RectTransform canvasRectTransform;
    private RectTransform panelRectTransform;

    void Awake()
    {
        Canvas canvas = GetComponentInParent<Canvas>();
        if (canvas != null)
        {
            canvasRectTransform = canvas.transform as RectTransform;
            panelRectTransform = transform as RectTransform;
        }
    }

    public void OnPointerDown(PointerEventData data)
    {
        panelRectTransform.SetAsLastSibling();
        RectTransformUtility.ScreenPointToLocalPointInRectangle(panelRectTransform, data.position, data.pressEventCamera, out pointerOffset);
    }



    public void OnDrag(PointerEventData data)
    {
        if (panelRectTransform == null)
            return;



        Vector2 localPointerPosition;
        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
            canvasRectTransform, data.position, data.pressEventCamera, out localPointerPosition
        ))
        {
            panelRectTransform.localPosition = localPointerPosition - pointerOffset;
        }
    }

}

相关:

eventSystem详解 : http://www.manew.com/blog-56596-2917.html

ScreenPointToLocalPointInRectangle : http://gad.qq.com/article/detail/41551


2,通过在panel组件下增加一个透明image用作darg区域,将脚本DragPanel附加到该组件上,并将

panelRectTransform = transform as RectTransform;改为panelRectTransform = transform.parent as RectTransform;

实现只拖拽部分区域。

3,实现函数ClampToWindow来限制传入OnDrag函数中传入ScreenPointToLocalPointInRectangle的screenpoint的区域,以避免panel被拖拽出屏幕

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;

public class DragPanel : MonoBehaviour, IPointerDownHandler, IDragHandler
{

    private Vector2 pointerOffset;
    private RectTransform canvasRectTransform;
    private RectTransform panelRectTransform;

    void Awake()
    {
        Canvas canvas = GetComponentInParent<Canvas>();
        if (canvas != null)
        {
            canvasRectTransform = canvas.transform as RectTransform;
            panelRectTransform = transform.parent as RectTransform;
        }
    }

    public void OnPointerDown(PointerEventData data)
    {
        panelRectTransform.SetAsLastSibling();
        RectTransformUtility.ScreenPointToLocalPointInRectangle(panelRectTransform, data.position, data.pressEventCamera, out pointerOffset);
    }

    public void OnDrag(PointerEventData data)
    {
        if (panelRectTransform == null)
            return;

        Vector2 pointerPostion = ClampToWindow(data);

        Vector2 localPointerPosition;
        if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
            canvasRectTransform, pointerPostion, data.pressEventCamera, out localPointerPosition
        ))
        {
            panelRectTransform.localPosition = localPointerPosition - pointerOffset;
        }
    }

    Vector2 ClampToWindow(PointerEventData data)
    {
        Vector2 rawPointerPosition = data.position;

        Vector3[] canvasCorners = new Vector3[4];
        canvasRectTransform.GetWorldCorners(canvasCorners);

        float clampedX = Mathf.Clamp(rawPointerPosition.x, canvasCorners[0].x, canvasCorners[2].x);
        float clampedY = Mathf.Clamp(rawPointerPosition.y, canvasCorners[0].y, canvasCorners[2].y);

        Vector2 newPointerPosition = new Vector2(clampedX, clampedY);
        return newPointerPosition;
    }
}

4,通过Button来控制panel的开关,注册到Button的OnClick事件上

using UnityEngine;
using System.Collections;

public class TogglePanelButton : MonoBehaviour {

    public void TogglePanel (GameObject panel) {
        panel.SetActive (!panel.activeSelf);
    }
}

5,通过更改panel的sizeDelta来更改窗口的大小

在panel上添加一透明image,附加以下脚本即可,由于这里是通过sizeDelta来更改,所以panel的锚点最好设置成聚在一起的一个点,不然放大缩小都会出现一些问题

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class ResizePanel : MonoBehaviour, IPointerDownHandler, IDragHandler {
    
    public Vector2 minSize;
    public Vector2 maxSize;
    
    private RectTransform rectTransform;
    private Vector2 currentPointerPosition;
    private Vector2 previousPointerPosition;
    
    void Awake () {
        rectTransform = transform.parent.GetComponent();
    }
    
    public void OnPointerDown (PointerEventData data) {
        rectTransform.SetAsLastSibling();
        RectTransformUtility.ScreenPointToLocalPointInRectangle (rectTransform, data.position, data.pressEventCamera, out previousPointerPosition);
    }
    
    public void OnDrag (PointerEventData data) {
        if (rectTransform == null)
            return;
        
        Vector2 sizeDelta = rectTransform.sizeDelta;
        
        RectTransformUtility.ScreenPointToLocalPointInRectangle (rectTransform, data.position, data.pressEventCamera, out currentPointerPosition);
        Vector2 resizeValue = currentPointerPosition - previousPointerPosition;
        
        sizeDelta += new Vector2 (resizeValue.x, -resizeValue.y);
        sizeDelta = new Vector2 (
            Mathf.Clamp (sizeDelta.x, minSize.x, maxSize.x),
            Mathf.Clamp (sizeDelta.y, minSize.y, maxSize.y)
            );
        
        rectTransform.sizeDelta = sizeDelta;
        
        previousPointerPosition = currentPointerPosition;
    }
}

6,在panel上附加以下脚本使得每次点击该窗口都能让它显示在最上面

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class FocusPanel : MonoBehaviour, IPointerDownHandler {

    private RectTransform panel;

    void Awake () {
        panel = GetComponent  ();   
    }

    public void OnPointerDown (PointerEventData data) {
        panel.SetAsLastSibling ();
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值