如何使用新的输入系统访问点击(桌面)/点击(移动)位置?
Posted
技术标签:
【中文标题】如何使用新的输入系统访问点击(桌面)/点击(移动)位置?【英文标题】:How to access the click (desktop) / tap (mobile) position using the new input system? 【发布时间】:2021-04-17 06:27:59 【问题描述】:我创建了一个新的 Unity 项目并为新的输入系统安装了包。基本上我只想存储点击(桌面)/点击(移动)的位置,就是这样。
我知道旧系统提供解决方案
https://docs.unity3d.com/ScriptReference/Input-mousePosition.html https://docs.unity3d.com/ScriptReference/Touch-position.html但我想用新的输入系统解决它。
我从这个输入映射配置开始(我将显示每个选定项的配置)
我创建了一个记录每个点击/点击位置的新脚本
public class FooBar : MonoBehaviour
public void Select(InputAction.CallbackContext context)
Vector2 selectPosition = context.ReadValue<Vector2>();
Debug.Log($"Select position is: selectPosition.x|selectPosition.y");
在场景中我创建了一个空的游戏对象并在检查器中配置它
不幸的是,在运行播放模式时,每次移动鼠标时都会出现这些错误
这是第一条错误信息的堆栈跟踪
这是第二条错误消息的堆栈跟踪
所以我假设我的输入地图配置是错误的。
有人介意帮我设置一个输入配置,将点击/点击位置传递给脚本吗?
因此,为了快速解决问题,我目前将此代码与旧输入系统一起使用,但我真的不喜欢它;)
public sealed class SelectedPositionStateController : MonoBehaviour
private void Update()
#if UNITY_android || UNITY_ios
if (UnityEngine.Input.touchCount > 0)
Touch touch = UnityEngine.Input.GetTouch(0);
// do things with touch.position
#elif UNITY_STANDALONE
if (UnityEngine.Input.GetMouseButtonDown(0))
// do things with Input.mousePosition
#endif
// !!! USE THIS CODE BECAUSE IT'S OBVIOUSLY BETTER !!!
//
// public void SelectPosition(InputAction.CallbackContext context)
//
// Vector2 selectedPosition = context.ReadValue<Vector2>();
//
// // do things with selectedPosition
//
【问题讨论】:
你删除your previous question但现在使用我给你的代码有什么特殊原因吗? .... @derHugo 是的,您提供的解决方案在一种情况下是正确的,但该解决方案与我发布的错误无关。因此,即使使用您的代码也可以重现此错误 你试过context.control.ReadValue<Vector2>()
或context.ReadValue()
吗?仍然,如果我的解决方案是正确的并帮助了你..你为什么要关闭这个问题呢?
对 question3r 公平地说,新的和“改进的”输入系统将使任何试图使用它的人达到理智的边缘。超越。 @derHugo
我不明白为什么那个老问题(实际上是答案)被关闭了
【参考方案1】:
不确定这是否适合您,但您可以尝试一下。所以我创建了两种方法:一种用于鼠标移动,一种用于鼠标单击。当鼠标移动时,我记录它的位置并在点击时 - Debug.Log
这个位置。
public class InputDebug : MonoBehaviour
Vector2 lastInput;
public void Move(InputAction.CallbackContext callbackContext)
lastInput = callbackContext.ReadValue<Vector2>();
public void Click(InputAction.CallbackContext callbackContext)
Debug.Log(lastInput);
输入映射如下所示:
OnMove
点击
UPD:它也适用于移动设备
【讨论】:
感谢您的帮助。问题在于手机没有“鼠标位置”或类似的东西。因此,当单击/点击时,我需要一种方法来检测点击/点击位置,而无需存储移动时的最后鼠标位置:) 谢谢但抱歉 @Question3r 我为移动支持添加了新绑定。它就像在 PC 上一样工作。看看吧。【参考方案2】:要达到预期的结果,您需要 2 个InputAction。一个用于点击,另一个用于位置。
您的MonoBehaviour
将侦听与单击相关的InputAction
的performed
事件,并从与位置相关的事件中读取位置。
Position 相关的InputAction
是可选的;因为您可以使用输入系统 API 捕捉到它。
Touchscreen.current.primaryTouch.position.ReadValue()
Mouse.current.position.ReadValue()
对于您的用例,我建议:
-
直接在
MonoBehaviour
中序列化InputAction
使用InputActionAsset 并从那里获取InputAction
选项 1 - 直接输入动作
为点击设置一个InputAction
,为位置设置另一个。
然后您可能会听到 Click 并从 Position 中捕获位置。
public class InputWithAction : MonoBehaviour
// --------------- FIELDS AND PROPERTIES --------------- //
[SerializeField] private InputAction _click;
[SerializeField] private InputAction _pos;
// --------------- INITIALIZATION --------------- //
private void Process(InputAction.CallbackContext callback)
//get the value from the position
Debug.Log($"Input action: _pos.ReadValue<Vector2>()");
//use the items below if you want to get the input directly
#if UNITY_ANDROID || UNITY_IOS
//gets the primary touch position using the new input system
Debug.Log(Touchscreen.current.primaryTouch.position.ReadValue());
#elif UNITY_STANDALONE
//gets the current mouse position using the new input system
Debug.Log(Mouse.current.position.ReadValue());
#endif
// --------------- LISTENER SETUP --------------- //
private void OnEnable()
_click.Enable();
_pos.Enable();
_click.performed += Process;
private void OnDisable()
_click.performed -= Process;
_click.Disable();
_pos.Disable();
Click 动作需要 2 个绑定。
使用 + 按钮添加投标 => 将路径设置为:鼠标/左键 使用 + 按钮添加投标 => 将路径设置为:TouchScreen/Primary Touch/Tap该职位需要 2 个绑定。
使用 + 按钮添加投标 => 将路径设置为:鼠标/位置 使用 + 按钮添加 Bidning => 将路径设置为:TouchScreen/Primary Touch/Position您的组件将如下所示:
选项 2 - InputActionAsset
创建InputMapAsset
。
从编辑器:Assets -> Create -> InputActions。称它为“YourMap”
删除所有动作,然后添加 2 个动作。
A. “点击”动作 动作类型:按钮 绑定鼠标 => 鼠标/左键 绑定 TouchScreen => TouchScreen/Primary Touch/Tap
B. “定位”动作 操作类型:值 绑定鼠标 => 鼠标/位置 绑定 TouchScreen => TouchScreen/Primary Touch/Position
看起来像这样:
您可以将“YourMap”作为InputActionAsset
引用为MonoBehaviour
的一个字段,并使用FindAction 方法捕获InputAction
,使用字符串名称(“Click”和“位置”)。
public class InputWithMap : MonoBehaviour
// --------------- FIELDS AND PROPERTIES --------------- //
[SerializeField] private InputActionAsset _inputMap;
private InputAction _click;
private InputAction _pos;
private void Start()
//enable is required only if you're not using PlayerInput anywhere else
_inputMap.Enable();
_click = _inputMap.FindAction("Click");
_pos = _inputMap.FindAction("Position");
//listen from clicks
_click.performed += Process;
// --------------- INITIALIZATION --------------- //
private void Process(InputAction.CallbackContext callback)
//get the value from the position
Debug.Log($"Input action: _pos.ReadValue<Vector2>()");
private void OnDestroy() _click.performed -= Process;
几个考虑
新的输入系统的设计使设计人员可以使用PlayerInput 类完成所有操作,而无需编码。结果不会像上面提供的解决方案那样高效。 我将鼠标/触摸设置为单击一次。您还可以按住、双击或滚动将Interactions 添加到Bindings。 理论上,您可以使用TouchScreen 类中的ReadOnlyArray<TouchControl>
对触摸屏使用一个InputAction
来获得相同的结果,但在这种情况下,鼠标和触摸将具有不同的设置。阅读更多关于 Mouse 和 Touch 支持的信息。
【讨论】:
嗯,这听起来有点像您也可以简单地使用Input.mousePosition
和Input.GetTouch(0).position
...那么这个新系统的全部目的是什么? ^^
这对我来说看起来不错。但是有没有办法将所有代码移到编辑器设计器中?因为目前没有优势……我希望有一个通用的平台解决方案。我丑陋的解决方法代码更小,但是是的,它在更新循环中运行。但是还是……
希望从callback
参数中简单地读取点击/点击位置,仅此而已
由于要求很高,我使用 InputActionAsset 添加了解决方案,而不是直接使用 InputAction。我不喜欢依赖字符串,但这是另一种解决方案。无论如何你想听按钮回调,所以它没有鼠标位置。您可以直接获取它,也可以使用地图中的另一个输入操作(我在代码中提供了这两个选项)。
我大大编辑了答案。现在只有 InputAction 的解决方案也不需要基于平台的分离。 @derHugo,您可以使用代码或 InputAction 获取位置,但您无法从按下鼠标按钮的回调中获取它,因为它只有按钮按下事件。您可能会使用触摸屏,但在这种情况下,您需要将实现与#if 分开。以上是关于如何使用新的输入系统访问点击(桌面)/点击(移动)位置?的主要内容,如果未能解决你的问题,请参考以下文章