在游戏制作的过程中,我们经常会遇到拖拽物体到某个位置并做其他操作的需求,比如我们会把装备拖动到装备栏来使用这个装备,为了方便的解决这个问题,我制作了一套耦合性比较低的拖拽系统,这套拖拽会适配我们之前制作的按键系统,很简单的就可以添加上手柄的拖拽,先上代码。
首先我们应该有一个类,我们叫它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);
}
}
}
/// <summary>
/// 配置拖拽函数
/// </summary>
/// <param name="go">需要配置的物体 检测是否挂载了OnDragItem物体</param>
/// <param name="beginDragCallback">开始拖拽</param>
/// <param name="onDragCallback">正在拖拽</param>
/// <param name="endDragCallback">结束拖拽</param>
/// <param name="cancelDragCallback">取消拖拽 此函数需要手动调用</param>
public void ConfigDrag(GameObject go, Util.OnDragItemParamFunction beginDragCallback, Util.OnDragItemParamFunction onDragCallback,
Util.OnDragItemParamFunction endDragCallback, Util.OnDragItemParamFunction cancelDragCallback)
{
var onDragItem = go.GetComponent<OnDragItem>();
if (onDragItem != null)
{
onDragItem.Config(beginDragCallback, onDragCallback, endDragCallback, cancelDragCallback);
}
}
}
在这个类中,我们定义了一些基础的变量,并在Update中根据需求更新鼠标的显示,在我们的项目中,如果开始拖拽或当前不是PC端,就不需要显示鼠标,其他情况鼠标都会显示.我们需要建一个全局填充的Canvas,并把DragManager添加到这个Canvas上,最后再创建一个Image作为dragImage,如下图所示。
我们可以看到,在代码的最下面,我们有一个函数,配置了几个回调函数,是给拖拽的不同阶段使用的,而且我们判断的当前配置拖拽功能的物体是不是拥有拖拽组件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<Sprite>(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的拖拽接口,如下所示
下一节我们再说一下这个类的具体使用方法