unity3d中用incontrol检测输入设备切换

时间:2022-06-20 19:01:41

pc上同时插着手柄的情况下,巫师3的玩家一动键盘,操作提示立即变成键盘的,一动手柄,提示立马变成手柄的了。

我们的游戏用的incontrol插件做的多输入设备管理,也有这样的需求。我问过作者,没有直接的接口可以使用,需要用incontrol的两种事件组合着来做。

直接上代码吧,注释和清楚。

/// 
/// 1.incontrol 里面的device不包括键盘鼠标,只包括各种外设手柄。
/// 要检测键盘鼠标和device之间的切换,只能用一个PlayerActionSet注册所有要触发切换的键,
/// 然后监听它的PlayerActionSet.OnLastInputTypeChanged事件。
///
/// 2.手柄device之间的切换用InControl.InputManager.OnActiveDeviceChanged了。
///
/// 3.在系统上同时插多种手柄的情况下,以上两个事件可能都会触发,
/// 所以需要在自身的update里面来检测变动,发送事件,保证事件的唯一性。
///

namespace Pathea.InputSolutionNs
{
public enum InputDevice
{
MouseKeyboard = 0,
XboxJoystick,
Ps4Joystick,
Max
}

public class InputDeviceDetector : UpdateDestroySingleton
{
private class ControllerDetector:InControl.PlayerActionSet
{
public void Init()
{
InControl.PlayerAction a = CreatePlayerAction("ControllerDetector");

for (int i = (int)InControl.InputControlType.LeftStickUp; i <= (int)InControl.InputControlType.Action12; i++)
{
a.AddDefaultBinding((InControl.InputControlType)i);
}

for (int i = (int)InControl.Mouse.LeftButton; i <= (int)InControl.Mouse.Button9; i++)
{
a.AddDefaultBinding((InControl.Mouse)i);
}

for (int i = (int)InControl.Key.Shift; i <= (int)InControl.Key.CapsLock; i++)
{
a.AddDefaultBinding((InControl.Key)i);
}

}
}

private InputDevice curDevice = InputDevice.Max;
private InputDevice nextDevice = InputDevice.MouseKeyboard;

private ControllerDetector controllerDetector = new ControllerDetector();

public event System.Action OnDeviceChanged;

public InputDevice CurDevice
{
get
{
return curDevice;
}
}

private static bool IsPs4Joystick()
{
if (InControl.InputManager.ActiveDevice == null)
{
return false;
}

if (InControl.InputManager.ActiveDevice.DeviceStyle != InControl.InputDeviceStyle.PlayStation4)
{
return false;
}

return true;
}

private static bool IsXboxJoystick()
{
if (InControl.InputManager.ActiveDevice == null)
{
return false;
}

if (InControl.InputManager.ActiveDevice.DeviceStyle != InControl.InputDeviceStyle.XboxOne
&& InControl.InputManager.ActiveDevice.DeviceStyle != InControl.InputDeviceStyle.Xbox360)
{
return false;
}

return true;
}

protected override void Update()
{
if (curDevice != nextDevice)
{
curDevice = nextDevice;

if (OnDeviceChanged != null)
{
OnDeviceChanged(curDevice);
}
}
}

protected override void OnInit()
{
base.OnInit();

controllerDetector.Init();

controllerDetector.OnLastInputTypeChanged += ControllerDetector_OnLastInputTypeChanged;

InControl.InputManager.OnActiveDeviceChanged += InputManager_OnActiveDeviceChanged;
}

//键盘,鼠标,手柄类型之间切换会受到这个消息
private void ControllerDetector_OnLastInputTypeChanged(InControl.BindingSourceType obj)
{
if (obj != InControl.BindingSourceType.DeviceBindingSource)
{
SetNextInputDevice(InputDevice.MouseKeyboard);
}
else
{
CheckController();
}
}

//只有手柄之间切换会收到这个消息。
private void InputManager_OnActiveDeviceChanged(InControl.InputDevice obj)
{
CheckController();
}

private void CheckController()
{
if (IsXboxJoystick())
{
SetNextInputDevice(InputDevice.XboxJoystick);
}
else if(IsPs4Joystick())
{
SetNextInputDevice(InputDevice.Ps4Joystick);
}
}

private void SetNextInputDevice(InputDevice device)
{
nextDevice = device;
}

protected override void Destroy()
{
base.Destroy();

controllerDetector.OnLastInputTypeChanged -= ControllerDetector_OnLastInputTypeChanged;
InControl.InputManager.OnActiveDeviceChanged -= InputManager_OnActiveDeviceChanged;
}
}
}