在新的 Unity 输入系统中如何映射到 KeyCode.JoystickButton0?
How do you map to KeyCode.JoystickButton0 in the new Unity Input System?
我正在为 Android TV 和 Fire TV 开发一个 Unity 项目,该项目使用 v2019.3 中发布的新输入系统。
Fire TV's button mappings在旧系统中如下:
Back KeyCode.Escape
Select (D-Pad Center) KeyCode.JoystickButton0
Left (D-Pad) KeyCode.LeftArrow
Right (D-Pad) KeyCode.RightArrow
Up (D-Pad) KeyCode.UpArrow
Down (D-Pad) KeyCode.DownArrow
除了 Select/D-Pad 中心之外,我已经在新系统中使用以下绑定路径成功映射了所有内容:
Escape [Keyboard]
Right Arrow [Keyboard]
Left Arrow [Keyboard]
Up Arrow [Keyboard]
Down Arrow [Keyboard]
如果我映射到 Any Key [Keyboard]
并实现以下代码作为回调,它显示为 key: JoystickButton0
,这与亚马逊的文档相匹配,但在新系统中不作为选项存在在键盘绑定路径下:
public void DebugKey(InputAction.CallbackContext context)
{
foreach(KeyCode vKey in System.Enum.GetValues(typeof(KeyCode))){
if(Input.GetKey(vKey)){
Debug.Log ("key: " + vKey);
}
}
}
我尝试了 Gamepad、Android Gamepad、Joystick 和 Android Joystick 下的各种按钮,但均未成功。另一个奇怪的事情是 Center/D-Pad 在没有任何绑定的情况下在 UI 按钮上工作正常。
使用新输入系统映射到旧 KeyCode.JoystickButtonX 命名约定的正确方法是什么?
谢谢!
在新系统中,设备被读取为HID,KeyCode没有用,所以如果你想读取摇杆按钮的状态,你可以这样做:
using UnityEngine.InputSystem;
public Joystick joy;
void Start()
{
joy = Joystick.current;
}
void FixedUpdate()
{
var button2 = joy.allControls[2].IsPressed();
if (button2)
{
Debug.Log("Button2 of current joystick is pushed");
}
}
如果您想映射按钮 0(在旧输入系统中),现在是按钮 1 或触发器
var button1 = joy.allControls[1].IsPressed();
或
var button1 = joy.trigger.IsPressed();
而且你可以测试更多棒的按钮..
void Start()
{
var ListOfJoys = Joystick.all;
joy = Joystick.current;//here current joy is ListOfJoys[1]
otherjoy = ListOfJoys[0];
}
var Buttons = joy.allControls;
if ((Buttons[2] as ButtonControl).wasPressedThisFrame)
{
Debug.Log("b2 pressed during this frame");
}
if ((Buttons[2] as ButtonControl).wasReleasedThisFrame)
{
Debug.Log("b2 released during this frame");
}
if (joy.trigger.wasPressedThisFrame)
{
Debug.Log("trig or button1 pressed during this frame");
}
if (joy.trigger.wasReleasedThisFrame)
{
Debug.Log("trig or button1 released during this fram");
}
if (otherjoy.trigger.wasPressedThisFrame)
{
Debug.Log("otherjoy trigger");
}
另一种方法是使用新系统的映射,我已经将动作press Only
Test1映射到stick
的button3
简化代码,您可以混合使用事件和直接测试:
//Newinputsystem is a name of class generated
private Newinputsystem playerAction;
void Awake()
{
playerAction = new Newinputsystem();
playerAction.Player.Test1.performed += ctx => FireTest();
}
void FixedUpdate()
{
if (playerAction.Player.Test1.triggered)
{
Debug.Log("fire!!!");
}
}
public void FireTest()
{
Debug.Log("i am in firetest");
}
private void OnEnable()
{
playerAction.Enable();
}
private void OnDisable()
{
playerAction.Disable();
}
因此您可以添加新的动作 test2,它将被按钮 3 的动作 release only
触发...
要显示 HID 设备,请转到菜单 Window/analysis/input 调试器
你得看看你的设备(我的是hotas)
然后您单击它并在选项卡项 HID 描述符中单击
所以我想你已经在项目设置中选择了你的设备:
为了将使用 Unity 的 Amazon Fire TV 控制器与新的输入系统完全映射,您需要一个自定义设备。
使用此脚本,您可以使所有按钮正常工作。
也可以调高音量、调低音量和静音。但我不认为覆盖此按钮是个好主意。
using System.Linq;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.Scripting;
#if UNITY_EDITOR
using UnityEditor;
#endif
[Preserve]
public struct AftvRemoteDeviceState : IInputStateTypeInfo
{
public FourCC format => new FourCC('A', 'G', 'C');
//Mapped Here
[InputControl(name = "dPadUpButton", layout = "Button", bit = 19, displayName = "Dpad Up")]
[InputControl(name = "dPadRightButton", layout = "Button", bit = 22, displayName = "Dpad Right")]
[InputControl(name = "dPadDownButton", layout = "Button", bit = 20, displayName = "Dpad Down")]
[InputControl(name = "dPadLeftButton", layout = "Button", bit = 21, displayName = "Dpad Left")]
//[InputControl(name = "backButton", layout = "Button", bit = 4, displayName = "Back Button")]
[InputControl(name = "menuButton", layout = "Button", bit = 82, displayName = "Menu Button")]
//Non Maped
[InputControl(name = "selectButton", layout = "Button", bit = 23, displayName = "Select Button")]
[InputControl(name = "rewindButton", layout = "Button", bit = 89, displayName = "Rewind Button")]
[InputControl(name = "playPauseButton", layout = "Button", bit = 85, displayName = "Play Pause Button")]
[InputControl(name = "fastForwardButton", layout = "Button", bit = 90, displayName = "Fast Forward Button")]
public uint buttons;
}
#if UNITY_EDITOR
[InitializeOnLoad] // Call static class constructor in editor.
#endif
[Preserve]
[InputControlLayout(displayName = "Aftv Remote", stateType = typeof(AftvRemoteDeviceState))]
public class AftvRemoteDevice : InputDevice
{
#if UNITY_EDITOR
static AftvRemoteDevice()
{
Initialize();
}
#endif
[RuntimeInitializeOnLoadMethod]
private static void Initialize()
{
InputSystem.RegisterLayout<AftvRemoteDevice>
(
matches: new InputDeviceMatcher()
.WithInterface("Android")
.WithDeviceClass("AndroidGameController")
.WithProduct("Amazon Fire TV Remote")
);
}
public ButtonControl dPadUpButton { get; private set; }
public ButtonControl dPadRightButton { get; private set; }
public ButtonControl dPadDownButton { get; private set; }
public ButtonControl dPadLeftButton { get; private set; }
public ButtonControl selectButton { get; private set; }
public ButtonControl rewindButton { get; private set; }
public ButtonControl playPauseButton { get; private set; }
public ButtonControl fastForwardButton { get; private set; }
//public ButtonControl backButton { get; private set; }
public ButtonControl menuButton { get; private set; }
public bool SelectButtonDown { get; set; }
public bool RewindButtonDown { get; set; }
public bool PlayPauseButtonDown { get; set; }
public bool FastForwardButtonDown { get; set; }
protected override void FinishSetup()
{
base.FinishSetup();
dPadUpButton = GetChildControl<ButtonControl>("dPadUpButton");
dPadRightButton = GetChildControl<ButtonControl>("dPadRightButton");
dPadDownButton = GetChildControl<ButtonControl>("dPadDownButton");
dPadLeftButton = GetChildControl<ButtonControl>("dPadLeftButton");
rewindButton = GetChildControl<ButtonControl>("rewindButton");
playPauseButton = GetChildControl<ButtonControl>("playPauseButton");
fastForwardButton = GetChildControl<ButtonControl>("fastForwardButton");
//backButton = GetChildControl<ButtonControl>("backButton");
menuButton = GetChildControl<ButtonControl>("menuButton");
selectButton = GetChildControl<ButtonControl>("selectButton");
}
public static AftvRemoteDevice current { get; private set; }
public override void MakeCurrent()
{
base.MakeCurrent();
current = this;
}
protected override void OnRemoved()
{
base.OnRemoved();
if (current == this)
current = null;
}
#region Editor
#if UNITY_EDITOR
[MenuItem("Tools/AftvRemote/Create Device")]
private static void CreateDevice()
{
InputSystem.AddDevice<AftvRemoteDevice>();
}
[MenuItem("Tools/AftvRemote/Remove Device")]
private static void RemoveDevice()
{
var customDevice = InputSystem.devices.FirstOrDefault(x => x is AftvRemoteDevice);
if (customDevice != null)
InputSystem.RemoveDevice(customDevice);
}
#endif
#endregion
}
位值与 来自 AndroidAPI 的常数值相同。
您可以查看列表 Here
您只需要将此脚本包含在项目中,设置您的输入操作和输入操作映射。
由于某种原因,播放器输入组件有问题。
但是对于 UI 导航来说,这很好用,它也适用于输入调试器。
我正在为 Android TV 和 Fire TV 开发一个 Unity 项目,该项目使用 v2019.3 中发布的新输入系统。
Fire TV's button mappings在旧系统中如下:
Back KeyCode.Escape
Select (D-Pad Center) KeyCode.JoystickButton0
Left (D-Pad) KeyCode.LeftArrow
Right (D-Pad) KeyCode.RightArrow
Up (D-Pad) KeyCode.UpArrow
Down (D-Pad) KeyCode.DownArrow
除了 Select/D-Pad 中心之外,我已经在新系统中使用以下绑定路径成功映射了所有内容:
Escape [Keyboard]
Right Arrow [Keyboard]
Left Arrow [Keyboard]
Up Arrow [Keyboard]
Down Arrow [Keyboard]
如果我映射到 Any Key [Keyboard]
并实现以下代码作为回调,它显示为 key: JoystickButton0
,这与亚马逊的文档相匹配,但在新系统中不作为选项存在在键盘绑定路径下:
public void DebugKey(InputAction.CallbackContext context)
{
foreach(KeyCode vKey in System.Enum.GetValues(typeof(KeyCode))){
if(Input.GetKey(vKey)){
Debug.Log ("key: " + vKey);
}
}
}
我尝试了 Gamepad、Android Gamepad、Joystick 和 Android Joystick 下的各种按钮,但均未成功。另一个奇怪的事情是 Center/D-Pad 在没有任何绑定的情况下在 UI 按钮上工作正常。
使用新输入系统映射到旧 KeyCode.JoystickButtonX 命名约定的正确方法是什么?
谢谢!
在新系统中,设备被读取为HID,KeyCode没有用,所以如果你想读取摇杆按钮的状态,你可以这样做:
using UnityEngine.InputSystem;
public Joystick joy;
void Start()
{
joy = Joystick.current;
}
void FixedUpdate()
{
var button2 = joy.allControls[2].IsPressed();
if (button2)
{
Debug.Log("Button2 of current joystick is pushed");
}
}
如果您想映射按钮 0(在旧输入系统中),现在是按钮 1 或触发器
var button1 = joy.allControls[1].IsPressed();
或
var button1 = joy.trigger.IsPressed();
而且你可以测试更多棒的按钮..
void Start()
{
var ListOfJoys = Joystick.all;
joy = Joystick.current;//here current joy is ListOfJoys[1]
otherjoy = ListOfJoys[0];
}
var Buttons = joy.allControls;
if ((Buttons[2] as ButtonControl).wasPressedThisFrame)
{
Debug.Log("b2 pressed during this frame");
}
if ((Buttons[2] as ButtonControl).wasReleasedThisFrame)
{
Debug.Log("b2 released during this frame");
}
if (joy.trigger.wasPressedThisFrame)
{
Debug.Log("trig or button1 pressed during this frame");
}
if (joy.trigger.wasReleasedThisFrame)
{
Debug.Log("trig or button1 released during this fram");
}
if (otherjoy.trigger.wasPressedThisFrame)
{
Debug.Log("otherjoy trigger");
}
另一种方法是使用新系统的映射,我已经将动作press Only
Test1映射到stick
简化代码,您可以混合使用事件和直接测试:
//Newinputsystem is a name of class generated
private Newinputsystem playerAction;
void Awake()
{
playerAction = new Newinputsystem();
playerAction.Player.Test1.performed += ctx => FireTest();
}
void FixedUpdate()
{
if (playerAction.Player.Test1.triggered)
{
Debug.Log("fire!!!");
}
}
public void FireTest()
{
Debug.Log("i am in firetest");
}
private void OnEnable()
{
playerAction.Enable();
}
private void OnDisable()
{
playerAction.Disable();
}
因此您可以添加新的动作 test2,它将被按钮 3 的动作 release only
触发...
要显示 HID 设备,请转到菜单 Window/analysis/input 调试器
你得看看你的设备(我的是hotas)
然后您单击它并在选项卡项 HID 描述符中单击
所以我想你已经在项目设置中选择了你的设备:
为了将使用 Unity 的 Amazon Fire TV 控制器与新的输入系统完全映射,您需要一个自定义设备。
使用此脚本,您可以使所有按钮正常工作。 也可以调高音量、调低音量和静音。但我不认为覆盖此按钮是个好主意。
using System.Linq;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.Scripting;
#if UNITY_EDITOR
using UnityEditor;
#endif
[Preserve]
public struct AftvRemoteDeviceState : IInputStateTypeInfo
{
public FourCC format => new FourCC('A', 'G', 'C');
//Mapped Here
[InputControl(name = "dPadUpButton", layout = "Button", bit = 19, displayName = "Dpad Up")]
[InputControl(name = "dPadRightButton", layout = "Button", bit = 22, displayName = "Dpad Right")]
[InputControl(name = "dPadDownButton", layout = "Button", bit = 20, displayName = "Dpad Down")]
[InputControl(name = "dPadLeftButton", layout = "Button", bit = 21, displayName = "Dpad Left")]
//[InputControl(name = "backButton", layout = "Button", bit = 4, displayName = "Back Button")]
[InputControl(name = "menuButton", layout = "Button", bit = 82, displayName = "Menu Button")]
//Non Maped
[InputControl(name = "selectButton", layout = "Button", bit = 23, displayName = "Select Button")]
[InputControl(name = "rewindButton", layout = "Button", bit = 89, displayName = "Rewind Button")]
[InputControl(name = "playPauseButton", layout = "Button", bit = 85, displayName = "Play Pause Button")]
[InputControl(name = "fastForwardButton", layout = "Button", bit = 90, displayName = "Fast Forward Button")]
public uint buttons;
}
#if UNITY_EDITOR
[InitializeOnLoad] // Call static class constructor in editor.
#endif
[Preserve]
[InputControlLayout(displayName = "Aftv Remote", stateType = typeof(AftvRemoteDeviceState))]
public class AftvRemoteDevice : InputDevice
{
#if UNITY_EDITOR
static AftvRemoteDevice()
{
Initialize();
}
#endif
[RuntimeInitializeOnLoadMethod]
private static void Initialize()
{
InputSystem.RegisterLayout<AftvRemoteDevice>
(
matches: new InputDeviceMatcher()
.WithInterface("Android")
.WithDeviceClass("AndroidGameController")
.WithProduct("Amazon Fire TV Remote")
);
}
public ButtonControl dPadUpButton { get; private set; }
public ButtonControl dPadRightButton { get; private set; }
public ButtonControl dPadDownButton { get; private set; }
public ButtonControl dPadLeftButton { get; private set; }
public ButtonControl selectButton { get; private set; }
public ButtonControl rewindButton { get; private set; }
public ButtonControl playPauseButton { get; private set; }
public ButtonControl fastForwardButton { get; private set; }
//public ButtonControl backButton { get; private set; }
public ButtonControl menuButton { get; private set; }
public bool SelectButtonDown { get; set; }
public bool RewindButtonDown { get; set; }
public bool PlayPauseButtonDown { get; set; }
public bool FastForwardButtonDown { get; set; }
protected override void FinishSetup()
{
base.FinishSetup();
dPadUpButton = GetChildControl<ButtonControl>("dPadUpButton");
dPadRightButton = GetChildControl<ButtonControl>("dPadRightButton");
dPadDownButton = GetChildControl<ButtonControl>("dPadDownButton");
dPadLeftButton = GetChildControl<ButtonControl>("dPadLeftButton");
rewindButton = GetChildControl<ButtonControl>("rewindButton");
playPauseButton = GetChildControl<ButtonControl>("playPauseButton");
fastForwardButton = GetChildControl<ButtonControl>("fastForwardButton");
//backButton = GetChildControl<ButtonControl>("backButton");
menuButton = GetChildControl<ButtonControl>("menuButton");
selectButton = GetChildControl<ButtonControl>("selectButton");
}
public static AftvRemoteDevice current { get; private set; }
public override void MakeCurrent()
{
base.MakeCurrent();
current = this;
}
protected override void OnRemoved()
{
base.OnRemoved();
if (current == this)
current = null;
}
#region Editor
#if UNITY_EDITOR
[MenuItem("Tools/AftvRemote/Create Device")]
private static void CreateDevice()
{
InputSystem.AddDevice<AftvRemoteDevice>();
}
[MenuItem("Tools/AftvRemote/Remove Device")]
private static void RemoveDevice()
{
var customDevice = InputSystem.devices.FirstOrDefault(x => x is AftvRemoteDevice);
if (customDevice != null)
InputSystem.RemoveDevice(customDevice);
}
#endif
#endregion
}
位值与 来自 AndroidAPI 的常数值相同。 您可以查看列表 Here 您只需要将此脚本包含在项目中,设置您的输入操作和输入操作映射。
由于某种原因,播放器输入组件有问题。 但是对于 UI 导航来说,这很好用,它也适用于输入调试器。