A game about forced loneliness, made by TACStudios
at master 123 lines 5.1 kB view raw
1using UnityEngine; 2using UnityEngine.InputSystem; 3#if UNITY_EDITOR 4using UnityEditor; 5#endif 6 7// Say you want to distinguish a device not only by its type (e.g. "PS4 Controller") 8// but also by the way it is used. This is a common scenario for VR controllers, for 9// example, where the same type of controller may be used once in the left hand and 10// once in the right hand. However, the need for distinguishing devices in a similar 11// manner can pop up in a variety of situations. For example, on Switch it is used 12// to distinguish the current orientation of the Joy-Con controller ("Horizontal" vs. 13// "Vertical") allowing you to take orientation into account when binding actions. 14// 15// The input system allows you to distinguish devices based on the "usages" assigned 16// to them. This is a generic mechanism that can be used to tag devices with arbitrary 17// custom usages. 18// 19// To make this more concrete, let's say we have a game where two players control 20// the game together each one using a gamepad but each receiving control over half 21// the actions in the game. 22// 23// NOTE: What we do here is only one way to achieve this kind of setup. We could 24// alternatively go and just create one control scheme for the first player 25// and one control scheme for the second one and then have two PlayerInputs 26// each using one of the two. 27// 28// So, what we'd like to do is tag one gamepad with "Player1" and one gamepad with 29// with "Player2". Then, in the actions we can set up a binding scheme specifically 30// for this style of play and bind actions such that are driven either from the 31// first player's gamepad or from the second player's gamepad (or from either). 32// 33// The first bit we need for this is to tell the input system that "Player1" and 34// "Player2" are usages that we intend to apply to gamepads. For this, we need 35// to modify the "Gamepad" layout. We do so by applying what's called a "layout 36// override". This needs to happen during initialization so here we go: 37#if UNITY_EDITOR 38[InitializeOnLoad] 39#endif 40public static class InitCustomDeviceUsages 41{ 42 static InitCustomDeviceUsages() 43 { 44 Initialize(); 45 } 46 47 [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] 48 private static void Initialize() 49 { 50 // Here we register the layout override with the system. 51 // 52 // The layout override is just a fragment of layout information 53 // in JSON format. 54 // 55 // The key property here is "commonUsages" which tells the system 56 // that "Player1" and "Player2" are possible usages applied to devices 57 // using the given layout ("Gamepad" in our case). 58 InputSystem.RegisterLayoutOverride(@" 59 { 60 ""name"" : ""GamepadPlayerUsageTags"", 61 ""extend"" : ""Gamepad"", 62 ""commonUsages"" : [ 63 ""Player1"", ""Player2"" 64 ] 65 } 66 "); 67 68 // Now that we have done this, you will see that when using the 69 // control picker in the action editor, that there is now a 70 // "Gamepad (Player1)" and "Gamepad (Player2)" entry underneath 71 // "Gamepad". When you select those, you can bind specifically 72 // to a gamepad with the respective device usage. 73 // 74 // Also, you will now be able to *require* a device with the 75 // given usage in a control scheme. So, when creating a control 76 // scheme representing the shared Player1+Player2 controls, 77 // you can add one "Gamepad (Player1)" and one "Gamepad (Player2)" 78 // requirement. 79 // 80 // You can see an example setup for how this would look in an 81 // .inputactions file in the TwoPlayerControls.inputactions file 82 // that is part of this sample. 83 } 84} 85 86// However, we are still missing a piece. At runtime, no gamepad will 87// receive either the "Player1" or the "Player2" usage assignment yet. 88// So none of the bindings will work yet. 89// 90// To assign the usage tags to the devices, we need to call 91// InputSystem.AddDeviceUsage or SetDeviceUsage. 92// 93// We could set this up any which way. As a demonstration, let's create 94// a MonoBehaviour here that simply associates a specific tag with a 95// specific gamepad index. 96// 97// In practice, you would probably want to do the assignment in a place 98// where you handle your player setup/joining. 99public class CustomDeviceUsages : MonoBehaviour 100{ 101 public int gamepadIndex; 102 public string usageTag; 103 104 private Gamepad m_Gamepad; 105 106 protected void OnEnable() 107 { 108 if (gamepadIndex >= 0 && gamepadIndex < Gamepad.all.Count) 109 { 110 m_Gamepad = Gamepad.all[gamepadIndex]; 111 InputSystem.AddDeviceUsage(m_Gamepad, usageTag); 112 } 113 } 114 115 protected void OnDisable() 116 { 117 // If we grabbed a gamepad and it's still added to the system, 118 // remove the usage tag we added. 119 if (m_Gamepad != null && m_Gamepad.added) 120 InputSystem.RemoveDeviceUsage(m_Gamepad, usageTag); 121 m_Gamepad = null; 122 } 123}