如何使用新的输入系统访问点击(桌面)/点击(移动)位置?
c#
我创建了一个新的 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
// }
}
回答
要实现所需的结果,您将需要 2 个InputAction。一个用于点击,另一个用于位置。
您MonoBehaviour将收听与 Click 相关的performed事件InputAction并从与 Position 相关的事件中读取 Position。
在InputAction相关的目标位置是可选的; 因为您可以使用输入系统 API 捕获它。
Touchscreen.current.primaryTouch.position.ReadValue()Mouse.current.position.ReadValue()
对于您的用例,我建议:
- 序列化
InputAction直接在MonoBehaviour - 使用InputActionAsset并
InputAction从那里获取
选项 1 - 直接输入操作
InputAction为 Click设置一个,为 Position设置另一个。
然后您可能会听到 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 个绑定。
- 使用 + 按钮添加投标 => 将路径设置为:鼠标/位置
- 使用 + 按钮添加投标 => 将路径设置为:TouchScreen/Primary Touch/Position
您的组件将如下所示:
选项 2 - InputActionAsset
-
创建
InputMapAsset.
从编辑器:资产 -> 创建 -> InputActions。称之为“你的地图” -
删除所有操作,然后添加 2 个操作。
A.“点击”动作动作类型:Button
Binding Mouse => Mouse/LeftButton
Binding TouchScreen => TouchScreen/Primary Touch/Tap
B.“位置”动作动作类型:值
绑定鼠标=>鼠标/位置
绑定触摸屏=>触摸屏/主要触摸/位置
它看起来像这样:
您可以使用字符串名称(“ Click ”和“ Position ”)将“YourMap”作为InputActionAsset您的字段引用MonoBehaviour并InputAction使用FindAction方法捕获它。
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类完成所有工作,而无需编码。结果不会像上面提供的解决方案那样高效。
- 我设置鼠标/触摸以捕捉一键点击。您也可以按住、双击或滚动将交互添加到Bindings。
- 从理论上讲,你可能只用一个达到同样的效果
InputAction,使用触摸屏ReadOnlyArray<TouchControl>的触摸屏类,但在这种情况下,鼠标和触摸都将有不同的设置。阅读更多鼠标和触摸支持。