本篇文章来分享一下对ui元素的拖拽实现。
实现思路
1)按下记录偏移
鼠标按下时,记录“ui元素锚点” 与“鼠标点击点”的位置差(offset)
2)拖动更新位置
鼠标移动时,用“鼠标实时位置+偏移量” 更新ui位置,保证ui元素始终跟随鼠标的“抓取点”移动。
为什么要使用offset?
使用offset是为了让拖拽操作更自然(避免鼠标点击物体时,物体瞬间跳到鼠标位置)。
若不使用offset,直接把物体位置设为鼠标位置(recttransform.position = mousepos):当点击物体非中心点(比如左上角)时,物体会瞬间 “瞬移” 到鼠标指针正下方,拖拽手感非常生硬。因为鼠标点击的位置(mousepos)和物体锚点位置(recttransform.position)通常不在同一位置,直接赋值会导致物体跳位。
计算逻辑
recttransform.position:物体的锚点位置(默认是物体中心点);
mousepos:鼠标点击时,在世界空间中的指针位置;
offset:两者的差值 = 物体锚点位置 - 鼠标点击位置。
假设物体锚点在屏幕上的位置是 (100, 200)(recttransform.position);点击的是物体左上角,此时鼠标位置是 (80, 220)(mousepos);则offset = (100,200) - (80,220) = (20, -20)。此时offset代表:“鼠标点击点”相对于“物体锚点”的偏移量(即锚点在鼠标点击点的右侧20、下方20位置)。
注意offset只需在onpointerdown(鼠标按下时)计算一次,之后拖拽过程中保持不变。因为它只需要记录按下瞬间的偏移关系,拖动时复用即可。如果在ondrag中重复计算,反而会导致物体抖动。
简而言之,offset就是记住抓住物体的位置,让拖拽时物体跟着抓点走,而不是跳来跳去。
代码实现
using unityengine;
using unityengine.eventsystems;
public class drag : monobehaviour, idraghandler, ipointerdownhandler
{
private recttransform recttransform;
private vector3 offset;
private void awake()
{
recttransform = gameobject.getcomponent<recttransform>();
}
public void ondrag(pointereventdata eventdata)
{
if (eventdata.pointerpressraycast.gameobject == gameobject)
{
if (recttransformutility.screenpointtoworldpointinrectangle(recttransform, eventdata.position, eventdata.presseventcamera, out vector3 mousepos))
{
recttransform.position = mousepos + offset;
}
}
}
public void onpointerdown(pointereventdata eventdata)
{
recttransformutility.screenpointtoworldpointinrectangle(recttransform, eventdata.position, eventdata.presseventcamera, out vector3 mousepos);
offset = recttransform.position - mousepos;
}
}效果

unity常用ui交互接口
接口名称 | 核心方法 | 触发时机 | 使用场景 |
ipointerdownhandler | onpointerdown(pointereventdata eventdata) | 鼠标/触摸按下到ui元素时(触发一次) | 拖拽起始记录、长按检测起点、按钮按下反馈 |
ipointeruphandler | onpointerup(pointereventdata eventdata) | 鼠标/触摸在ui元素上抬起时(移出元素后抬起不触发) | 拖拽结束判定、按钮抬起反馈 |
ipointerclickhandler | onpointerclick(pointereventdata eventdata) | 按下 + 抬起都在同一ui元素上(完整点击,触发一次) | 普通按钮点击、ui元素选中 |
ipointerenterhandler | onpointerenter(pointereventdata eventdata) | 鼠标/触摸移入ui元素时(触发一次) | 悬停提示显示、按钮高亮 |
ipointerexithandler | onpointerexit(pointereventdata eventdata) | 鼠标/触摸移出ui元素时(触发一次) | 悬停提示关闭、按钮高亮取消 |
idraghandler | ondrag(pointereventdata eventdata) | 拖拽过程中每帧触发(需先按下ui元素) | ui拖拽移动、滑动条拖动、背包物品拖拽 |
ibegindraghandler | onbegindrag(pointereventdata eventdata) | 拖拽开始时(按下后首次移动,触发一次) | 记录拖拽初始位置、生成拖拽虚影 |
ienddraghandler | onenddrag(pointereventdata eventdata) | 拖拽结束时(抬起鼠标/触摸,触发一次) | 判定拖拽落点、恢复原ui状态 |
iscrollhandler | onscroll(pointereventdata eventdata) | 鼠标滚轮滚动或触摸滑动时(每帧触发) | 自定义滚动视图ui缩放、滚动文本框 |
iselecthandler | onselect(baseeventdata eventdata) | ui元素被选中时(如键tab切换) | 输入框选中高亮、菜单选项选中反馈 |
ideselecthandler | ondeselect(baseeventdata eventdata) | ui元素失去选中时(如切换到其他元素) | 输入框失去焦点保存内容、取消菜单选中状态 |
isubmithandler | onsubmit(baseeventdata eventdata) | 选中ui元素后提交(如按 enter 键) | 菜单确认、表单提交、按钮激活 |
icancelhandler | oncancel(baseeventdata eventdata) | 触发取消操作时(如按esc键) | 关闭弹窗、取消输入、退出当前界面 |
到此这篇关于c#实现对ui元素拖拽的实现示例的文章就介绍到这了,更多相关c# ui元素拖拽内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论