unity input system 使用记录(实例版)

目录

  • 前情提要
  • 基本概念
    • Control Schemes
    • Action Maps
      • Action Maps 用来干什么呢?
      • 什么时候使用多个Action Maps
      • 切换Action Maps
    • Actions
      • 添加Actions
    • Bindings
      • 添加bindings
      • 1D Axis Composite
      • 2D Axis Composite,提供一个Vector2值
      • 如何一次性识别两个按钮被按下?
      • 如何避免两个动作的同时触发
      • Interactions and Processors
        • Interactions
        • Processors
  • 使用方法
    • 如何使用Player Input Component
    • Behaviour 设置
      • Send Message
        • 获取输入时的数据
      • Broadcast Messages
      • Invoke Unity Events
      • Invoke C Sharp Events
    • 直接使用
      • 预备知识
      • 直接读取设备的状态
      • 直接读取输入
      • 检查空格是否在当前帧按压
      • 查找所有的已连接设备
      • 何时有新设备加入
      • 创建简单的开火动作
      • 在触发一个动作之前,要求一个按钮保持0.4秒
      • 要求按住左键,然后按下A键,并保持0.4秒
      • 等待任何设备上的任何按钮被按下
      • 鼠标键盘例子
      • 键盘上下左右控制例子
      • 鼠标使用例子
      • 鼠标单击长按例子
      • 鼠标左键点击例子

如果已经了解过基本概念了,请当我前面没写,直接跳至使用方法

前情提要

在unity中除了传统的通过Input来获取按键输入的方式外
还有一种新的控制输入方法,那就是Input system

但网上的记录感觉还是太少了,感觉不太能满足需求,所以自己就做了一点总结,来防止自己忘记

input system 主要完成的工作是作为一个中间层
将按键响应包装为事件响应,从而方便自己进行管理

易于使用和快速设置,从而方便快速添加基本控件。

当然,并不是说旧的不好,如果能够满足使用,完全没必要再刻意去替换,当然如果想支持新的设备,可以考虑使用input system

unity input system 使用记录(实例版)_第1张图片

安装的过程就省略了,网上太多且简单

基本概念

input system文件可以直接通过create进行创建( Assets > Create > Input Actions),其内部如下
unity input system 使用记录(实例版)_第2张图片

Control Schemes

用于定义用户控制游戏时使用的不同类型的设备或一组设备

比如:

  • 键盘鼠标
  • 游戏手柄
  • 方向盘等

可以通过设置多种类型的Control Schemes保持不同类型的控制系统分离
当然也可以不用,只用添加不同的Action,然后绑定好控制

使用多个Control Schemes的目的是,方便游戏切换设备操作模式,比如单人/双人模式
又或者不同设备的控制

Action Maps

包含一系列的相关Action
unity input system 使用记录(实例版)_第3张图片

Action Maps 用来干什么呢?

Action Maps 包含特定类型行为的所有动作。

比如:你可以把所有角色的通用动作放在一起,像移动,跳跃,开火等
一个Action Maps 可以取名为Player 或者 Gameplay 只要你喜欢

那么就带来一个问题,似乎我只需要一个Action Maps就够了,那为什么要多个呢?

什么时候使用多个Action Maps

比如,你做了一个第一人称的游戏,包含射击和驾驶的功能

这时,你需要一个Action Maps去控制人物的移动和射击,但同时你又需要另一个Action Maps 用于驾驶控制

玩游戏多的人都知道,这两种操作之间很可能会发生按键间的冲突,开车的时候的跳跃键和射击时的肯定不一样

所以你可以在不同的模式下切换Action Maps从而做到满足两种游戏需求

切换Action Maps

在游戏中想要进行切换,可以通过脚本的

playerInput.SwitchCurrentActionMap("Menu");
Debug.Log(playerInput.currentActionMap);

Actions

在input system 中,Actions 连接了控制设备的物理输入和游戏内部的事件
Actions 是 Action maps的具体表现

添加Actions

unity input system 使用记录(实例版)_第4张图片
通过点击+号即可添加
有三种不同类型的Action

  • Button 默认设置,包括按钮或者按键触发的一次性动作
  • Value 提供一种连续状态变化事件,如果设置了多个输入,就会切换到最主要的一个。用它进行模拟控制,比如移动。
  • Pass Through 和Value很相似,但它不会像Value一样(如果有多个输入时,不会只选择最主要的那个,而把其他的输入忽略)

对于Values和Pass Through的选择上,要看自己的设计需求

Values会优先考虑最大的输入值,而Pass Through会优先考虑最近的输入值,而不管它有多大。

input system 中的 Get Key 和 Get Key Down
如果使用老的input Manager, 判断一个键是按了一次还是按下了(例如移动),通过检查对按住按钮的Get key或对单次按下的Get key down来完成。
在 input system 中 Button Action Type 代表只触发一次,等价于 Get Key Down
Value Action Type 等价于 Get Key

GetKey 当通过名称指定的按键被用户按住时返回true
GetKeyDown 当用户按下指定名称的按键时的那一帧返回true。
GetKeyUp 在用户释放给定名字的按键的那一帧返回true。

在使用Value或者Pass Through Types时,你会看到一个额外的选项 Control Type

这允许您指定期望从输入中获得什么类型的输入,并影响哪些Bindings可用。unity input system 使用记录(实例版)_第5张图片
在完成上述的设置后,就可以添加Binding了

Bindings

简单来说就是将物理输入与事件进行绑定

添加bindings

unity input system 使用记录(实例版)_第6张图片
unity input system 使用记录(实例版)_第7张图片
除了通过界面绑定外,也可以直接通过代码在运行时绑定

using UnityEngine;
using UnityEngine.InputSystem;
public class BasicRebinding : MonoBehaviour
{
    public InputActionReference triggerAction;
    void ChangeBinding()
    {
        InputBinding binding = triggerAction.action.bindings[0];
        binding.overridePath = "/#(g)";
        triggerAction.action.ApplyBindingOverride(0, binding);
    }
}

1D Axis Composite

unity input system 使用记录(实例版)_第8张图片

2D Axis Composite,提供一个Vector2值

unity input system 使用记录(实例版)_第9张图片
unity input system 使用记录(实例版)_第10张图片
在2D Axis Composite中,从两个axes中获取了值信息
然而这两个值会因为Composite mode 的不同而影响彼此

  • Digital

unity input system 使用记录(实例版)_第11张图片
比如你推动上和右,那么得到的Vector2 就是 (1,1),一般用于两个不相关的控制
在人物移动时,往往会需要上下左右组合按,但如果同时按上右,这样得到的速度就会很大,与正常的逻辑相违背,这时就要使用Digital Normalized

  • Digital Normalized

unity input system 使用记录(实例版)_第12张图片
默认使用,返回一个归一化的向量,这时如果按上右,那么得到的就是(0.7, 0.7)
限制大家应该也看出来了,那就是digital只能给两个方向的输入使用,如果是更多方向呢
比如遥杆控制、控制器的左右操纵杆,那么就需要新的方式

  • The Analogue Mode

unity input system 使用记录(实例版)_第13张图片

如何一次性识别两个按钮被按下?

这种场景很常见,比如经常会有CTRL+Z等快捷组合键需要实现
在inputsystem中,可以创建Button with One Modifier Composite 或者 Button with Two Modifiers Composite
unity input system 使用记录(实例版)_第14张图片
但是要注意的是,input system 并不能屏蔽其他的输入
举个例子,如果你绑定jump动作和B键,而另一个动作Dive绑定的是Left Trigger + B
那么两个动作都会触发,那么应该如何避免呢?

如何避免两个动作的同时触发

就是在触发时,做一个检测判断,看另一个按键有没有被触发,再决定下一个动作。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class InputTester : MonoBehaviour
{
    bool modifierPressed;
    void OnModifier(InputValue value)
    {
        modifierPressed = value.isPressed;
    }
    void OnTrigger()
    {
        if(modifierPressed)
        {
            // Do one thing...
        }
        else 
        {
            // Do a different thing...
        }
    }
}

Interactions and Processors

当设置你的游戏控制器时,可以使用Interactions 和 Processors 改变输入的解释方法

比如,轻点和长按,就是对按钮行为的不同解释

Interactions

用户在按压按钮时,可以有多种方法
可以快速的轻按,或者长时间的重按
也可以在按下和释放时,触发不同的Action
也可以快速双击

unity input system 使用记录(实例版)_第15张图片

  • Hold
    之后按压一段时间后,才会触发事件
  • Multi Tap
    重复使用tap, 可以用这个方式实现双击操作
  • Press
    按压或者释放时触发事件
  • Slow Tap
    只是和Tap相比较而言具有更长的时间周期
  • Tap
    快速按压和释放
Processors

unity input system 使用记录(实例版)_第16张图片
//挖坑,有时间继续补

使用方法

input system 为了方便用户使用,具有灵活性和可扩展性,提供了多种方式使用
其中最简单的使用方法是使用Player Input Component
unity input system 使用记录(实例版)_第17张图片

如何使用Player Input Component

切换 Action Maps

playerInput.SwitchCurrentActionMap("Menu");

Behaviour 设置

Behaviour 有四种选项
unity input system 使用记录(实例版)_第18张图片

Send Message

使用Send Message时,每次的触发会盗用一个对应的函数
比如Input Action 名为 Jump,那么对应的函数即为 OnJump

就是在前面加个On-

获取输入时的数据

可以通过Get 获取设置的对应类型的数据

using UnityEngine;
using UnityEngine.InputSystem;
public class MovePlayer : MonoBehaviour
{
    public Vector2 moveVal;
    public float moveSpeed;
    void OnMove(InputValue value)
    {
        moveVal = value.Get<Vector2>();
    }
    void Update()
    {
        transform.Translate(new Vector3(moveVal.x, moveVal.y, 0) * moveSpeed * Time.deltaTime);
    }
    void OnFire(InputValue value) 
    { 
        float triggerVal = value.Get<float>(); 
    }
    bool modifierPressed;
    void OnModifier(InputValue value)
    {
         modifierPressed = value.isPressed;
     }
}

这种方式很适合对于单个游戏对象操控,对于多个对象可以使用

Broadcast Messages

Broadcast Messages 与 send Message 很相似,只是broadcast 会通过object hierarchy 向下传递

Invoke Unity Events

public void Move(InputAction.CallbackContext value)
    {
        moveVal = value.ReadValue<Vector2>();
        transform.Translate(new Vector3(moveVal.x, moveVal.y, 0));
    }

Invoke C Sharp Events

using UnityEngine;
using UnityEngine.InputSystem;
public class CSharpEvent : MonoBehaviour
{
    public PlayerInput playerInput;
    void OnEnable()
    {
        playerInput.onActionTriggered += MyEventFunction;
    }
    void OnDisable()
    {
        playerInput.onActionTriggered -= MyEventFunction;
    }
    void MyEventFunction(InputAction.CallbackContext value)
    {
        Debug.Log(value.action.name + (" was triggered"));
    }
}

直接使用

预备知识

unity input system 使用记录(实例版)_第19张图片
鼠标主要有四个属性
Delta代表鼠标相对运动的坐标改变值,与上一帧的偏移

The current window-space motion delta of the pointer.

Postion代表鼠标当前绝对位置, 在空间中的坐标

The current pointer coordinates in window space.

Radius代表与屏幕的接触半径

Window-space radius of the pointer contact with the surface.
Usually, only touch input has radius detection

Sroll 代表滚轮

引用
context.phase中的内容,其中包含了按键信息的详细情况,
对应的case有

  • Disabled 禁用
  • Waiting 等待输入
  • Started 开始输入
  • Performed 完成输入事件(例如hold了足够的时间)
  • Canceled 未完成输入事件(例如hold的时间不够)

InputAction包括
wasPressedThisFrame,
wasReleasedThisFrame,
isPressed

if (keyboard.wKey.wasPressedThisFrame)
    Debug.Log("w键按下(一直按住w键的话,也只执行一次)");
if (keyboard.wKey.wasReleasedThisFrame)
    Debug.Log("w键松开");
Debug.Log("是否按住w键:" + keyboard.wKey.isPressed);

直接读取设备的状态

在使用方法上,可以和老的输入方式类似,直接读取设备的状态

void Update()
{
    Vector2 mousePosition = Mouse.current.position.ReadValue();
    if(Keyboard.current.anyKey.wasPressedThisFrame)
    {
        Debug.Log("A key was pressed");
    }
    if (Gamepad.current.aButton.wasPressedThisFrame)
    {
        Debug.Log("A button was pressed");
    }
}
Keyboard keyboard;

keyboard = InputSystem.GetDevice<Keyboard>(); 

if (keyboard.wKey.isPressed)
{
    direction = new Vector2(0, 1);
    Vector3 delta = new Vector3(direction.x, direction.y, 0) * Time.deltaTime * 5f;
    transform.position = transform.position + delta;
}

// 按键按下
Keyboard.current.spaceKey.isPressed
// 按键按住
Keyboard.current.spaceKey.wasPressedThisFrame

直接读取输入

在使用时,有时并不用各种Get,也可以直接使用,button就是bool
unity input system 使用记录(实例版)_第20张图片
pitch是围绕X轴旋转,也叫做俯仰角
yaw是围绕Y轴旋转,也叫偏航角
roll是围绕Z轴旋转,也叫翻滚角

 private void CameraRotation()
        {
            // if there is an input and camera position is not fixed
            if (_input.look.sqrMagnitude >= _threshold && !LockCameraPosition)
            {
                //Don't multiply mouse input by Time.deltaTime;
                float deltaTimeMultiplier = IsCurrentDeviceMouse ? 1.0f : Time.deltaTime;

                _cinemachineTargetYaw += _input.look.x * deltaTimeMultiplier;
                _cinemachineTargetPitch += _input.look.y * deltaTimeMultiplier;
            }

            // clamp our rotations so our values are limited 360 degrees
            _cinemachineTargetYaw = ClampAngle(_cinemachineTargetYaw, float.MinValue, float.MaxValue);
            _cinemachineTargetPitch = ClampAngle(_cinemachineTargetPitch, BottomClamp, TopClamp);

            // Cinemachine will follow this target
            CinemachineCameraTarget.transform.rotation = Quaternion.Euler(_cinemachineTargetPitch + CameraAngleOverride,
                _cinemachineTargetYaw, 0.0f);
        }

private void Move()
        {
            // set target speed based on move speed, sprint speed and if sprint is pressed
            float targetSpeed = _input.sprint ? SprintSpeed : MoveSpeed;

            // a simplistic acceleration and deceleration designed to be easy to remove, replace, or iterate upon

            // note: Vector2's == operator uses approximation so is not floating point error prone, and is cheaper than magnitude
            // if there is no input, set the target speed to 0
            if (_input.move == Vector2.zero) targetSpeed = 0.0f;

            // a reference to the players current horizontal velocity
            float currentHorizontalSpeed = new Vector3(_controller.velocity.x, 0.0f, _controller.velocity.z).magnitude;

            float speedOffset = 0.1f;
            float inputMagnitude = _input.analogMovement ? _input.move.magnitude : 1f;

            // accelerate or decelerate to target speed
            if (currentHorizontalSpeed < targetSpeed - speedOffset ||
                currentHorizontalSpeed > targetSpeed + speedOffset)
            {
                // creates curved result rather than a linear one giving a more organic speed change
                // note T in Lerp is clamped, so we don't need to clamp our speed
                _speed = Mathf.Lerp(currentHorizontalSpeed, targetSpeed * inputMagnitude,
                    Time.deltaTime * SpeedChangeRate);

                // round speed to 3 decimal places
                _speed = Mathf.Round(_speed * 1000f) / 1000f;
            }
            else
            {
                _speed = targetSpeed;
            }

            _animationBlend = Mathf.Lerp(_animationBlend, targetSpeed, Time.deltaTime * SpeedChangeRate);
            if (_animationBlend < 0.01f) _animationBlend = 0f;

            // normalise input direction
            Vector3 inputDirection = new Vector3(_input.move.x, 0.0f, _input.move.y).normalized;

            // note: Vector2's != operator uses approximation so is not floating point error prone, and is cheaper than magnitude
            // if there is a move input rotate player when the player is moving
            if (_input.move != Vector2.zero)
            {
                _targetRotation = Mathf.Atan2(inputDirection.x, inputDirection.z) * Mathf.Rad2Deg +
                                  _mainCamera.transform.eulerAngles.y;
                float rotation = Mathf.SmoothDampAngle(transform.eulerAngles.y, _targetRotation, ref _rotationVelocity,
                    RotationSmoothTime);

                // rotate to face input direction relative to camera position
                transform.rotation = Quaternion.Euler(0.0f, rotation, 0.0f);
            }


            Vector3 targetDirection = Quaternion.Euler(0.0f, _targetRotation, 0.0f) * Vector3.forward;

            // move the player
            _controller.Move(targetDirection.normalized * (_speed * Time.deltaTime) +
                             new Vector3(0.0f, _verticalVelocity, 0.0f) * Time.deltaTime);

            // update animator if using character
            if (_hasAnimator)
            {
                _animator.SetFloat(_animIDSpeed, _animationBlend);
                _animator.SetFloat(_animIDMotionSpeed, inputMagnitude);
            }
        }

private void JumpAndGravity()
        {
            if (Grounded)
            {
                // reset the fall timeout timer
                _fallTimeoutDelta = FallTimeout;

                // update animator if using character
                if (_hasAnimator)
                {
                    _animator.SetBool(_animIDJump, false);
                    _animator.SetBool(_animIDFreeFall, false);
                }

                // stop our velocity dropping infinitely when grounded
                if (_verticalVelocity < 0.0f)
                {
                    _verticalVelocity = -2f;
                }

                // Jump
                if (_input.jump && _jumpTimeoutDelta <= 0.0f)
                {
                    // the square root of H * -2 * G = how much velocity needed to reach desired height
                    _verticalVelocity = Mathf.Sqrt(JumpHeight * -2f * Gravity);

                    // update animator if using character
                    if (_hasAnimator)
                    {
                        _animator.SetBool(_animIDJump, true);
                    }
                }

                // jump timeout
                if (_jumpTimeoutDelta >= 0.0f)
                {
                    _jumpTimeoutDelta -= Time.deltaTime;
                }
            }
            else
            {
                // reset the jump timeout timer
                _jumpTimeoutDelta = JumpTimeout;

                // fall timeout
                if (_fallTimeoutDelta >= 0.0f)
                {
                    _fallTimeoutDelta -= Time.deltaTime;
                }
                else
                {
                    // update animator if using character
                    if (_hasAnimator)
                    {
                        _animator.SetBool(_animIDFreeFall, true);
                    }
                }

                // if we are not grounded, do not jump
                _input.jump = false;
            }

            // apply gravity over time if under terminal (multiply by delta time twice to linearly speed up over time)
            if (_verticalVelocity < _terminalVelocity)
            {
                _verticalVelocity += Gravity * Time.deltaTime;
            }
        }

检查空格是否在当前帧按压

检查游戏手柄的a键是否被按压

Keyboard.current.space.wasPressedThisFrame;
Gamepad.current.aButton.wasPressedThisFrame

查找所有的已连接设备

var allGamepads = Gamepad.all;

// Go through all devices and select gamepads.
InputSystem.devices.Select(x => x is Gamepad);

// Query everything that is using the gamepad template or based on that template.
InputSystem.GetControls("/");

// Fetch all devices with "gamepad" in their names (not a good idea; no guarantee
// a gamepad is actually named that way).
InputSystem.GetControls("/gamepad*");

何时有新设备加入

InputSystem.onDeviceChange +=
        (device, change) =>
        {
            if (change == InputDeviceChange.Added)
                /* New Device */;
            else if (change == InputDeviceChange.Disconnected)
                /* Device got unplugged */;
            else if (change == InputDeviceChange.Connected)
                /* Plugged back in */;
            else if (change == InputDeviceChange.Removed)
                /* Remove from input system entirely; by default, devices stay in the system once discovered */;
        }

创建简单的开火动作

// Create action that binds to the primary action control on all devices.
var action = new InputAction(binding: "*/{primaryAction}");

// Have it run your code when action is triggered.
action.performed += _ => Fire();

// Start listening for control changes.
action.Enable();

第二种方式
首先

public class MyControllerComponent : MonoBehaviour
{
    public InputAction fireAction;
    public InputAction walkAction;
}

之后可以在编辑器的Inspector中进行绑定,之后响应绑定为

    void Awake()
    {
        fireAction.performed += _ => Fire;
        walkAction.performed += _ => Walk;
    }

    void OnEnable()
    {
        fireAction.Enable();
        walkAction.Enable();
    }

    void OnDisable()
    {
        fireAction.Disable();
        walkAction.Disable();
    }

    void Fire(InputAction action, InputControl control)
    {
        //...
    }

    void Walk(InputAction action, InputControl control)
    {
        //...
    }

或者

 void OnEnable()
    {
        fireAction.Enable();
        walkAction.Enable();
    }

    void OnDisable()
    {
        fireAction.Disable();
        walkAction.Disable();
    }

    void Update()
    {
        if (fireAction.hasBeenPerformedThisFrame)
            Fire();
        if (walkAction.hasBeenPerformedThisFrame)
            Walk();
    }

    void Fire()
    {
        //...
    }

    void Walk(InputAction action, InputControl control)
    {
        //...
    }

在触发一个动作之前,要求一个按钮保持0.4秒

var action = new InputAction(binding: "*/{PrimaryAction}",
        modifiers: "hold(duration=0.4)");

action.started += _ => ShowGunChargeUI();
action.performed += _ => FinishGunChargingAndHideChargeUI();
action.cancelled += _ => HideChargeUI()

要求按住左键,然后按下A键,并保持0.4秒

var action = new InputAction();
    action.AddBinding("//leftTrigger")
        .CombinedWith("//buttonSouth", modifiers: "hold(duration=0.4)");

等待任何设备上的任何按钮被按下

 var myAction = new InputAction(binding: "/*/

鼠标键盘例子

var gamepad = Gamepad.current;//手柄
var keyboard = Keyboard.current;//键盘
var mouse = Mouse.current;//鼠标
var pointer = Pointer.current;//指针
 
if (gamepad != null)
{
    Debug.Log(gamepad.leftStick.ReadValue());//手柄遥感的偏移
    if (gamepad.bButton.wasPressedThisFrame)
        Debug.Log("按下B键");
}
if (keyboard != null)
{
    //执行顺序 isPressed = false -> 按下:wasPressedThisFrame = true -> 中途:isPressed = true -> 松开:wasReleasedThisFrame = true -> isPressed = false
    if (keyboard.wKey.wasPressedThisFrame)
        Debug.Log("w键按下(一直按住w键的话,也只执行一次)");
    if (keyboard.wKey.wasReleasedThisFrame)
        Debug.Log("w键松开");
    Debug.Log("是否按住w键:" + keyboard.wKey.isPressed);
}
if (mouse != null)
{
    Debug.Log(mouse.scroll.ReadValue());//滚轮的滚动值,向前滚Y的值为正,向后滚为负
 
    if (mouse.leftButton.wasPressedThisFrame)
        Debug.Log("按鼠标左键");
    if (mouse.rightButton.wasPressedThisFrame)
        Debug.Log("按鼠标右键");
    if (mouse.middleButton.wasPressedThisFrame)
        Debug.Log("按滚轮键");
}
if (pointer != null)
{
    Debug.Log(pointer.delta.ReadValue());//与上一帧的偏移
    Debug.Log(pointer.position.ReadValue());//在空间中的坐标
}

键盘上下左右控制例子

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyInputSmallTest : MonoBehaviour
{
    // MyInputActions为自己的Action名字
    public MyInputActions inputActions;
    private void Awake()
    {
        inputActions = new MyInputActions();
        inputActions.Enable();
        // 键盘控制移动,且inputActions必须配合+=,-=使用
        inputActions.Player.KBD_MOVE.performed += ctx =>
        {
            transform.Translate(ctx.ReadValue<Vector2>());
        };
        inputActions.Player.ACTION_DOWN.performed += ctx =>
        {
            Debug.Log("Action_Down" + UnityEngine.InputSystem.Mouse.current.position.ReadValue());
        };
        // 鼠标移动时即时反馈坐标
        inputActions.Player.ACTION_MOVE.performed += ctx =>
        {
            Debug.Log("Action_Move" + ctx.ReadValue<Vector2>());
        };
        inputActions.Player.ACTION_UP.performed += ctx =>
        {
            Debug.Log("Action_Up" + UnityEngine.InputSystem.Mouse.current.position.ReadValue());
        };
    }

    void Start(){}
    void Update(){}

    private void OnDestroy()
    {
        inputActions.Disable();
    }
}
 public InputManager inputActions;
    private Vector2 direction;

    private void Awake()
    {
        inputActions = new InputManager();
    }

    private void OnEnable()
    {
        inputActions.Enable();
        inputActions.Player.Move.performed += ctx =>  Move(ctx);
        inputActions.Player.Move.canceled += ctx => Move(ctx);
    }
    private void OnDisable()
    {
        inputActions.Player.Move.performed -= ctx =>  Move(ctx); ;
        inputActions.Player.Move.canceled -= ctx => Move(ctx);
        inputActions.Disable();
    }
    public void Move(InputAction.CallbackContext context)
    {
        var moveValue = context.ReadValue<Vector2>();
        Debug.Log(moveValue);
        direction = moveValue;
        
    }

    void Update()
    {
        if (direction != Vector2.zero)
        {
            Vector3 delta = new Vector3(direction.x, direction.y, 0) * Time.deltaTime * 5f;
            transform.position = transform.position + delta;
        }
    }

鼠标使用例子

unity input system 使用记录(实例版)_第21张图片

unity input system 使用记录(实例版)_第22张图片

鼠标单击长按例子

unity input system 使用记录(实例版)_第23张图片

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem.Interactions;

public class TictactoeControl : MonoBehaviour
{
    private TictactoeAction InputActions;
    private void Awake()
    {
        InputActions = new TictactoeAction();
        InputActions.TestMap.Tap.started += ctx =>
        {
            Debug.Log("操作开始");
        };
        InputActions.TestMap.Tap.performed += ctx =>
        {
            if (ctx.interaction is MultiTapInteraction)
            {
                Debug.Log("执行双击逻辑");
            }
            else if (ctx.interaction is HoldInteraction)
            {
                Debug.Log("执行长按逻辑");
            }
            else
            {
                //列表中只有MultiTapInteraction和HoldInteraction对应的两种Interaction。
                //故不会走到这个else里。
            }
        };
        InputActions.TestMap.Tap.canceled += ctx =>
        {
            if (ctx.interaction is MultiTapInteraction)
            {
                Debug.Log("执行点击逻辑");
            }
        };
    }
    void Start()
    {
        
    }
    void Update()
    {

    }
    public void OnEnable()
    {
        InputActions.Enable();
    }
    public void OnDisable()
    {
        InputActions.Disable();
    }
}


鼠标左键点击例子

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Interactions;
 
public class MouseInputPlayer : MonoBehaviour
{
    private RaycastHit hit;
    private bool hitBool; //是否点击到目标
    private IMouseInputPlayer mouseClickInterface; //接口
    private ObjectProperties mIPScriptName; // 物体属性脚本
    private bool ifMouseClickInterface; // 是否存在
    private bool ifObjectProperties; // 是否存在
 
    public void OnLeftBottonClick(InputAction.CallbackContext context)
    {
        switch (context.phase)
        {
            case InputActionPhase.Started:
                {
                    //Debug.Log("操作开始");
                    mouseClickInterface = null; //初始化接口
 
                    Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue()); //射线
                    hitBool = Physics.Raycast(ray, out hit); //返回是否点击到目标
                    if (hitBool)
                    {
                        //Debug.Log("操作开始");
                        ifObjectProperties = hit.collider.gameObject.TryGetComponent(out objectProperties); // 获取物体属性脚本
 
                        ifMouseClickInterface = hit.collider.gameObject.TryGetComponent(out mouseClickInterface); //设置接口
                    }
                }
                break;
            case InputActionPhase.Performed:
                {
                    if (hitBool && ifObjectProperties)
                    {
                        if (context.interaction is MultiTapInteraction)
                        {
                            //Debug.Log("执行双击逻辑");
                            if (objectProperties.ifLeftMouseDblclick && ifMouseClickInterface)
                            {
                                mouseClickInterface.OnLeftMouseDblclick();
                            }
                        }
                        else if (context.interaction is HoldInteraction)
                        {
                            //Debug.Log("执行长按逻辑");
                            if (objectProperties.ifLeftMouseHold && ifMouseClickInterface)
                            {
                                mouseClickInterface.OnLeftMouseHold();
                            }
                        }
                        else
                        {
                            //列表中只有MultiTapInteraction和HoldInteraction对应的两种Interaction。
                            //故不会走到这个else里。
                        }
                    }
                }
                break;
            case InputActionPhase.Canceled:
                {
                    if (context.interaction is MultiTapInteraction)
                    {
                        //Debug.Log("执行点击逻辑");
                        if (hitBool && ifObjectProperties)
                        {
                            if (objectProperties.ifLeftMouseClick && ifMouseClickInterface)
                            {
                                mouseClickInterface.OnLeftMouseClick();
                            }
                        }
                    }
                }
                break;
        }
    }
}

后面看到好代码例子再加吧

你可能感兴趣的:(unity,unity,游戏引擎)