Unity物体拖拽系统(一)

        在游戏制作的过程中,我们经常会遇到拖拽物体到某个位置并做其他操作的需求,比如我们会把装备拖动到装备栏来使用这个装备,为了方便的解决这个问题,我制作了一套耦合性比较低的拖拽系统,这套拖拽会适配我们之前制作的按键系统,很简单的就可以添加上手柄的拖拽,先上代码。

        首先我们应该有一个类,我们叫它DragManager,他存储着一些公用的操作和参数,我们看一下他的代码。

        

public enum DragType
{
    NONE = 0,
    TOOL = 1
}

public delegate void OnDragItemParamFunction(OnDragItem param);
public class DragManager : MonoBehaviour
{
    public Image dragImage; // 拖拽时显示的图片
    public bool isDraging; // 是否正在被拖拽
    public bool lockDrag; // 锁定拖拽
    public OnDragItem curDragItem = null; // 当前拖拽的物体
    public DragType dragType;   // 如果需要配置A键点击的特殊操作,则需要配置上对应类型

    private PointerEventData eventData;
    private void Start()
    {
        eventData = new PointerEventData(EventSystem.current);
    }

    private void Update()
    {
        if (isDraging)
        {
            Cursor.visible = false;
        }
        else
        {
            Cursor.visible = GameController.manager.operatingMode == OperatingMode.Standalone;
        }

        if (GameController.manager.operatingMode == OperatingMode.Console)
        {
            if (isDraging && curDragItem != null)
            {
                curDragItem.OnDrag(eventData);
            }
        }
    }

    /// 
    ///  配置拖拽函数
    /// 
    /// 需要配置的物体 检测是否挂载了OnDragItem物体
    /// 开始拖拽
    /// 正在拖拽
    /// 结束拖拽
    /// 取消拖拽 此函数需要手动调用
    public void ConfigDrag(GameObject go, Util.OnDragItemParamFunction beginDragCallback, Util.OnDragItemParamFunction onDragCallback,
        Util.OnDragItemParamFunction endDragCallback, Util.OnDragItemParamFunction cancelDragCallback)
    {
        var onDragItem = go.GetComponent();
        if (onDragItem != null)
        {
            onDragItem.Config(beginDragCallback, onDragCallback, endDragCallback, cancelDragCallback);
        }
    }
}

        在这个类中,我们定义了一些基础的变量,并在Update中根据需求更新鼠标的显示,在我们的项目中,如果开始拖拽或当前不是PC端,就不需要显示鼠标,其他情况鼠标都会显示.我们需要建一个全局填充的Canvas,并把DragManager添加到这个Canvas上,最后再创建一个Image作为dragImage,如下图所示。

        Unity物体拖拽系统(一)_第1张图片

        我们可以看到,在代码的最下面,我们有一个函数,配置了几个回调函数,是给拖拽的不同阶段使用的,而且我们判断的当前配置拖拽功能的物体是不是拥有拖拽组件OnDragItem,如果拥有的话我们才会对其进行配置,下面我们来看一下拖拽组件的功能。

using UnityEngine;
using UnityEngine.EventSystems;

public class OnDragItem : BaseDrag
{

    private Vector2 originPos;
    private Util.OnDragItemParamFunction beginDragCallback;
    private Util.OnDragItemParamFunction onDragCallback;
    private Util.OnDragItemParamFunction endDragCallback;
    private Util.OnDragItemParamFunction cancelDragCallback;
    private bool hasConfiged;

    // warning : 使用QA.dragMan调用这个函数 不要直接调用
    public void Config(Util.OnDragItemParamFunction beginDragCallback, Util.OnDragItemParamFunction onDragCallback,
        Util.OnDragItemParamFunction endDragCallback, Util.OnDragItemParamFunction cancelDragCallback)
    {
        hasConfiged = true;
        this.beginDragCallback = (OnDragItem item) =>
        {
            beginDragCallback?.Invoke(item);
            QA.dragMan.curDragItem = this;
        };
        this.onDragCallback = onDragCallback;
        this.endDragCallback = (OnDragItem item) =>
        {
            endDragCallback?.Invoke(item);
            QA.dragMan.curDragItem = null;
            QA.dragMan.dragType = DragType.NONE;
        }; ;
        this.cancelDragCallback = (OnDragItem item) =>
        {
            cancelDragCallback?.Invoke(item);
            QA.dragMan.dragType = DragType.NONE;
        };
    }

    public override void OnBeginDrag(PointerEventData eventData)//开始拖动的那一帧
    {
        if (eventData.button == PointerEventData.InputButton.Left && hasConfiged)
        {
            if (QA.dragMan.isDraging || QA.dragMan.lockDrag)
            {
                return;
            }
            QA.dragMan.isDraging = true;
            originPos = QA.dragMan.dragImage.transform.localPosition;
            beginDragCallback?.Invoke(this);
        }
    }

    public override void OnDrag(PointerEventData eventData)
    {
        if (eventData.button == PointerEventData.InputButton.Left && hasConfiged)
        {
            if (!QA.dragMan.isDraging || QA.dragMan.lockDrag)
            {
                return;
            }
            QA.dragMan.dragImage.transform.localPosition = Util.GetUIPos(GameController.manager.uiCanvas.gameObject);
            onDragCallback?.Invoke(this);
        }
    }


    public override void OnEndDrag(PointerEventData eventData) //结束拖动时
    {
        if (eventData.button == PointerEventData.InputButton.Left && hasConfiged)
        {
            if (!QA.dragMan.isDraging || QA.dragMan.lockDrag)
            {
                return;
            }
            endDragCallback?.Invoke(this);
            QA.dragMan.dragImage.gameObject.SetActiveFast(false);
            QA.dragMan.dragImage.transform.localPosition = originPos;
            QA.dragMan.isDraging = false;
        }
    }

    public void ShowDragImage(string path)
    {
        QA.dragMan.dragImage.sprite = QA.resourceMan.GetResource(path);
        QA.dragMan.dragImage.transform.localPosition = Util.GetUIPos(GameController.manager.uiCanvas.gameObject);
        QA.dragMan.dragImage.gameObject.SetActiveFast(true);
        QA.dragMan.dragImage.SetNativeSize();
    }

    public void ShowDragImage(Sprite sprite)
    {
        QA.dragMan.dragImage.sprite = sprite;
        QA.dragMan.dragImage.transform.localPosition = Util.GetUIPos(GameController.manager.uiCanvas.gameObject);
        QA.dragMan.dragImage.gameObject.SetActiveFast(true);
        QA.dragMan.dragImage.SetNativeSize();
    }

    public void CancelDrag()
    {
        if (!QA.dragMan.isDraging || QA.dragMan.lockDrag)
        {
            return;
        }
        cancelDragCallback?.Invoke(this);
        QA.dragMan.dragImage.gameObject.SetActiveFast(false);
        QA.dragMan.dragImage.transform.localPosition = originPos;
        QA.dragMan.interactClickableUI = null;
        QA.dragMan.curDragItem = null;
        QA.dragMan.isDraging = false;
    }
}

这个类继承自BaseDrag,这个基类实现了Unity的拖拽接口,如下所示

Unity物体拖拽系统(一)_第2张图片

下一节我们再说一下这个类的具体使用方法

你可能感兴趣的:(拖拽系统,unity,游戏引擎)