I try to create a Custom Device.
But the result wasn’t great.
For now this could be the best solution I can figure out.
The mapped keys are get by reading the Input System Keyboard.
The Non Mapped keys are get by using Android Java Calls to the Override Main Activity.
It was working, until I compile with IL2CPP (The Build that I need to upload in any Store)
I don’t know what to from here.
using System.Linq;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.InputSystem.Utilities;
#if UNITY_EDITOR
using UnityEditor;
#endif
public struct AftvRemoteDeviceState : IInputStateTypeInfo
{
public FourCC format => new FourCC('A','G','C');
//Buttons
[InputControl(name = "selectButton", layout = "Button", bit = 0, displayName = "Select Button")]
[InputControl(name = "backButton", layout = "Button", bit = 1, displayName = "Back Button")]
[InputControl(name = "menuButton", layout = "Button", bit = 2, displayName = "Menu Button")]
[InputControl(name = "rewindButton", layout = "Button", bit = 3, displayName = "Rewind Button")]
[InputControl(name = "playPauseButton", layout = "Button", bit = 4, displayName = "PlayPause Button")]
[InputControl(name = "fastForwardButton", layout = "Button", bit = 5, displayName = "FastForward Button")]
public ushort buttons;
[InputControl(name = "stick", format = "VC2B", layout = "Stick", displayName = "Main Stick")]
[InputControl(name = "stick/x", defaultState = 127, format = "BYTE",
offset = 0,
parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5")]
public byte x;
[InputControl(name = "stick/y", defaultState = 127, format = "BYTE",
offset = 1,
parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5")]
[InputControl(name = "stick/up", parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp=2,clampMin=0,clampMax=1")]
[InputControl(name = "stick/down", parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp=2,clampMin=-1,clampMax=0,invert")]
[InputControl(name = "stick/left", parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp=2,clampMin=-1,clampMax=0,invert")]
[InputControl(name = "stick/right", parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp=2,clampMin=0,clampMax=1")]
public byte y;
}
#if UNITY_EDITOR
[InitializeOnLoad] // Call static class constructor in editor.
#endif
[InputControlLayout(stateType = typeof(AftvRemoteDeviceState))]
public class AftvRemoteDevice : InputDevice, IInputUpdateCallbackReceiver
{
#if UNITY_EDITOR
static AftvRemoteDevice()
{
Initialize();
}
#endif
[RuntimeInitializeOnLoadMethod]
public static void Initialize()
{
InputSystem.RegisterLayout<AftvRemoteDevice>
(
matches: new InputDeviceMatcher()
.WithInterface("Android")
.WithDeviceClass("AndroidGameController")
.WithCapability("vendorId", 369) //
.WithCapability("productId", 1043)
);
}
public ButtonControl selectButton { get; private set; }
public ButtonControl backButton { get; private set; }
public ButtonControl menuButton { get; private set; }
//Unity Activity Override Buttons
public ButtonControl rewindButton { get; private set; }
public ButtonControl playPauseButton { get; private set; }
public ButtonControl fastForwardButton { get; private set; }
public StickControl stick { get; private set; }
private static AndroidJavaClass javaClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
protected override void FinishSetup()
{
base.FinishSetup();
selectButton = GetChildControl<ButtonControl>("selectButton");
backButton = GetChildControl<ButtonControl>("backButton");
menuButton = GetChildControl<ButtonControl>("menuButton");
rewindButton = GetChildControl<ButtonControl>("rewindButton");
playPauseButton = GetChildControl<ButtonControl>("playPauseButton");
fastForwardButton = GetChildControl<ButtonControl>("fastForwardButton");
stick = GetChildControl<StickControl>("stick");
}
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;
}
public void OnUpdate()
{
var keyboard = Keyboard.current;
if (keyboard == null)
return;
//Debug.Log("Aftv Update");
AftvRemoteDeviceState state = new AftvRemoteDeviceState();
state.x = 127;
state.y = 127;
var wPressed = keyboard.wKey.isPressed || keyboard.upArrowKey.isPressed;
var aPressed = keyboard.aKey.isPressed || keyboard.leftArrowKey.isPressed;
var sPressed = keyboard.sKey.isPressed || keyboard.downArrowKey.isPressed;
var dPressed = keyboard.dKey.isPressed || keyboard.rightAltKey.isPressed;
if (aPressed)
state.x -= 127;
if (dPressed)
state.x += 127;
if (wPressed)
state.y += 127;
if (sPressed)
state.y -= 127;
// Map buttons to 1, 2, and 3.
if (keyboard.leftMetaKey.isPressed || keyboard.rightMetaKey.isPressed || keyboard.escapeKey.isPressed)//back
state.buttons |= 1 << 1;
if (keyboard.contextMenuKey.isPressed)//menu
state.buttons |= 1 << 2;
///Call this Only Works once
///For the Rewind KeyButton
///After that the Input Fails.
///I wonder If I can make this different
///
#if UNITY_ANDROID && !UNITY_EDITOR
using (AndroidJavaObject currentActivity = javaClass.GetStatic<AndroidJavaObject>("currentActivity"))
{
if (currentActivity.GetStatic<bool>("DPadCenter"))//select
state.buttons |= 1 << 0;
if (currentActivity.GetStatic<bool>("RewindButtonDown"))//RewindButton
{
state.buttons |= 1 << 3;
}
if (currentActivity.GetStatic<bool>("PlayPauseButtonDown"))//PlayPauseButton
{
state.buttons |= 1 << 4;
}
if (currentActivity.GetStatic<bool>("FastForwardButtonDown"))//ForwardButton
{
state.buttons |= 1 << 5;
}
}
#endif
InputSystem.QueueStateEvent(this, state);
}
#if UNITY_EDITOR
[MenuItem("Tools/Custom Device Sample/Create Aftv Device")]
private static void CreateDevice()
{
// This is the code that you would normally run at the point where
// you discover devices of your custom type.
InputSystem.AddDevice<AftvRemoteDevice>();
}
// For completeness sake, let's also add code to remove one instance of our
// custom device. Note that you can also manually remove the device from
// the input debugger by right-clicking in and selecting "Remove Device".
[MenuItem("Tools/Custom Device Sample/Remove Aftv Device")]
private static void RemoveDevice()
{
var customDevice = InputSystem.devices.FirstOrDefault(x => x is AftvRemoteDevice);
if (customDevice != null)
InputSystem.RemoveDevice(customDevice);
}
#endif
}
This is the override Unity Main Activity
public class UnityAtaPlayerActivity extends UnityPlayerActivity
{
public static boolean DPadCenter;
public static boolean PlayPauseButtonDown;
public static boolean RewindButtonDown;
public static boolean FastForwardButtonDown;
@Override
public boolean onKeyUp(int keyCode, KeyEvent event)
{
switch (keyCode)
{
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
this.PlayPauseButtonDown=false;
case KeyEvent.KEYCODE_MEDIA_REWIND:
this.RewindButtonDown=false;
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
this.FastForwardButtonDown=false;
case KeyEvent.KEYCODE_DPAD_CENTER:
this.DPadCenter=false;
}
return mUnityPlayer.injectEvent(event);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
switch (keyCode)
{
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
this.PlayPauseButtonDown=true;
case KeyEvent.KEYCODE_MEDIA_REWIND:
this.RewindButtonDown=true;
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
this.FastForwardButtonDown=true;
case KeyEvent.KEYCODE_DPAD_CENTER:
this.DPadCenter=true;
}
return mUnityPlayer.injectEvent(event);
}
}
In the debug version the controllers work a little bit strange, when I use the Dpad it works fine.
When using the Media button (Rewind, Play,Pause) it works the first time, after that it fails.