--- uid: input-system-step-4-device-registration --- # Step 4 Device registration and creation You now have a functioning device, but you haven't registered it (added it to the system) yet. This means you can't see the device when, for example, you create bindings in the [Action editor](actions-editor.md). You can register your device type with the system from within the code that runs automatically as part of Unity's startup. To do so, modify the definition of `MyDevice` like so: ```CSharp // Add the InitializeOnLoad attribute to automatically run the static // constructor of the class after each C# domain load. #if UNITY_EDITOR [InitializeOnLoad] #endif public class MyDevice : InputDevice, IInputUpdateCallbackReceiver { //... static MyDevice() { // RegisterLayout() adds a "Control layout" to the system. // These can be layouts for individual Controls (like sticks) // or layouts for entire Devices (which are themselves // Controls) like in our case. InputSystem.RegisterLayout(); } // You still need a way to trigger execution of the static constructor // in the Player. To do this, you can add the RuntimeInitializeOnLoadMethod // to an empty method. [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] private static void InitializeInPlayer() {} } ``` This registers the Device type with the system and makes it available in the Control picker. However, you still need a way to add an instance of the Device when it is connected. In theory, you could call [`InputSystem.AddDevice()`](xref:UnityEngine.InputSystem.InputSystem) somewhere, but in a real-world setup you likely have to correlate the Input Devices you create with their identities in the third-party API. It might be tempting to do something like this: ```CSharp public class MyDevice : InputDevice, IInputUpdateCallbackReceiver { //... // This does NOT work correctly. public ThirdPartyAPI.DeviceId externalId { get; set; } } ``` and then set that on the Device after calling [`AddDevice`](xref:UnityEngine.InputSystem.InputSystem). However, this doesn't work as expected in the Editor, because the Input System requires Devices to be created solely from their [`InputDeviceDescription`](xref:UnityEngine.InputSystem.Layouts.InputDeviceDescription) in combination with the chosen layout (and layout variant). In addition, the system supports a fixed set of mutable per-device properties such as device usages (that is, [`InputSystem.SetDeviceUsage()`](xref:UnityEngine.InputSystem.InputSystem) and related methods). This allows the system to easily recreate Devices after domain reloads in the Editor, as well as to create replicas of remote Devices when connecting to a Player. To comply with this requirement, you must cast that information provided by the third-party API into an [`InputDeviceDescription`](xref:UnityEngine.InputSystem.Layouts.InputDeviceDescription) and then use an [`InputDeviceMatcher`](xref:UnityEngine.InputSystem.Layouts.InputDeviceMatcher) to match the description to our custom `MyDevice` layout. This example assumes that the third-party API has two callbacks, like this: ```CSharp public static ThirdPartyAPI { // This example assumes that the argument is a string that // contains the name of the Device, and that no two Devices // have the same name in the external API. public static Action deviceAdded; public static Action deviceRemoved; } ``` You can hook into those callbacks and create and destroy devices in response. ```CSharp // This example uses a MonoBehaviour with [ExecuteInEditMode] // on it to run the setup code. You can do this many other ways. [ExecuteInEditMode] public class MyDeviceSupport : MonoBehaviour { protected void OnEnable() { ThirdPartyAPI.deviceAdded += OnDeviceAdded; ThirdPartyAPI.deviceRemoved += OnDeviceRemoved; } protected void OnDisable() { ThirdPartyAPI.deviceAdded -= OnDeviceAdded; ThirdPartyAPI.deviceRemoved -= OnDeviceRemoved; } private void OnDeviceAdded(string name) { // Feed a description of the Device into the system. In response, the // system matches it to the layouts it has and creates a Device. InputSystem.AddDevice( new InputDeviceDescription { interfaceName = "ThirdPartyAPI", product = name }); } private void OnDeviceRemoved(string name) { var device = InputSystem.devices.FirstOrDefault( x => x.description == new InputDeviceDescription { interfaceName = "ThirdPartyAPI", product = name, }); if (device != null) InputSystem.RemoveDevice(device); } // Move the registration of MyDevice from the // static constructor to here, and change the // registration to also supply a matcher. protected void Awake() { // Add a match that catches any Input Device that reports its // interface as "ThirdPartyAPI". InputSystem.RegisterLayout( matches: new InputDeviceMatcher() .WithInterface("ThirdPartyAPI")); } } ```