Qiita · Unity 开发社区· 来源· shin270080·· 2 小时前AI 评分15
Unity Input System 实现鼠标与触摸通用的拖拽操作
Unity Input Systemでマウス・タッチ共通のドラッグ操作を実装する
正文 · AI 翻译
转到点赞用户列表
0
在 X (Twitter) 上分享
在 Facebook 上分享
添加到 Hatena Bookmark
删除文章
已删除的文章无法恢复。
本文的草稿也会被删除。
您确定要删除这篇文章吗?
在Unity Input System中实现鼠标与触摸通用的拖拽操作
为了避免面向智能手机的游戏出现“在PC上可以拖拽,但在真机上操作不稳定”的问题,我们将Pointer输入统一为一种。在Unity 6中可以使用Input System 1.17。
方針
- 将鼠标和触摸作为Pointer进行处理
- 按下瞬间不开始拖拽
- 超过一定距离后进入拖拽状态
- 根据释放的位置进行吸附或还原
输入操作
将Point分配给<Pointer>/position,将Press分配给<Pointer>/press。
実装例
using UnityEngine;
using UnityEngine.InputSystem;
public sealed class PointerDragController : MonoBehaviour
{
[SerializeField] private InputActionReference pointAction;
[SerializeField] private InputActionReference pressAction;
[SerializeField] private Camera targetCamera;
[SerializeField] private float dragThreshold = 12f;
private Vector2 pressScreenPosition;
private Vector3 startWorldPosition;
private bool pressed;
private bool dragging;
private void OnEnable()
{
pointAction.action.Enable();
pressAction.action.Enable();
pressAction.action.performed += OnPress;
pressAction.action.canceled += OnRelease;
}
private void OnDisable()
{
pressAction.action.performed -= OnPress;
pressAction.action.canceled -= OnRelease;
pointAction.action.Disable();
pressAction.action.Disable();
}
private void Update()
{
if (!pressed) return;
Vector2 current = pointAction.action.ReadValue<Vector2>();
if (!dragging &&
Vector2.Distance(pressScreenPosition, current) >= dragThreshold)
{
dragging = true;
}
if (!dragging) return;
Vector3 world = ScreenToWorld(current);
transform.position = new Vector3(
world.x,
world.y,
startWorldPosition.z
);
}
private void OnPress(InputAction.CallbackContext context)
{
pressed = true;
dragging = false;
pressScreenPosition = pointAction.action.ReadValue<Vector2>();
startWorldPosition = transform.position;
}
private void OnRelease(InputAction.CallbackContext context)
{
if (dragging)
{
TrySnapOrReturn();
}
pressed = false;
dragging = false;
}
private Vector3 ScreenToWorld(Vector2 screen)
{
Vector3 p = new(screen.x, screen.y,
Mathf.Abs(targetCamera.transform.position.z -
transform.position.z));
return targetCamera.ScreenToWorldPoint(p);
}
private void TrySnapOrReturn()
{
Collider2D hit = Physics2D.OverlapPoint(transform.position);
if (hit != null && hit.TryGetComponent(out SnapTarget target))
{
transform.position = target.SnapPosition;
return;
}
transform.position = startWorldPosition;
}
}
吸附目标拆分为小型组件。
using UnityEngine;
public sealed class SnapTarget : MonoBehaviour
{
public Vector3 SnapPosition => transform.position;
}
减少误操作的要点
dragThreshold放入- 不将UI上的指针传递给游戏端
- 为吸附判定留出余量
- 成功时返回声音或小型动画
- 针对各设备确认安全区域与分辨率
总结
与按输入设备分别处理相比,以 Pointer 为单位构建状态转换会更易于管理。
明确“按下→移动一定距离→拖拽→释放”的流程,也能减少点击与拖拽的误判。
官方文档: https://docs.unity3d.com/ja/current/Manual/com.unity.inputsystem.html
长洲港町电气工事也在进行游戏和应用程序的制作。
查看点赞的用户列表
0
注册为新用户并更便捷地使用 Qiita
- 获取符合您需求的文章
- 您可以高效地读取有用信息
- 您可以使用深色主题
前往查看喜欢您的用户列表
0
删除文章
已删除的文章无法恢复。
本文的草稿也将被删除。
您确定要删除这篇文章吗?
来源:Qiita · Unity 开发社区 · qiita.com