如何使用新的输入系统访问点击(桌面)/点击(移动)位置?

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()

对于您的用例,我建议:

  1. 序列化InputAction直接在MonoBehaviour
  2. 使用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

  1. 创建InputMapAsset.
    从编辑器:资产 -> 创建 -> InputActions。称之为“你的地图”

  2. 删除所有操作,然后添加 2 个操作。

A.“点击”动作动作类型:Button
Binding Mouse => Mouse/LeftButton
Binding TouchScreen => TouchScreen/Primary Touch/Tap

B.“位置”动作动作类型:值
绑定鼠标=>鼠标/位置
绑定触摸屏=>触摸屏/主要触摸/位置

它看起来像这样:

您可以使用字符串名称(“ Click ”和“ Position ”)将“YourMap”作为InputActionAsset您的字段引用MonoBehaviourInputAction使用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>的触摸屏类,但在这种情况下,鼠标和触摸都将有不同的设置。阅读更多鼠标和触摸支持。

以上是如何使用新的输入系统访问点击(桌面)/点击(移动)位置?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>