IndieGame/client/Assets/Samples/Input System/1.7.0/Custom Device Usages/CustomDeviceUsages.cs

124 lines
5.0 KiB
C#
Raw Normal View History

2024-10-11 10:12:15 +08:00
using UnityEngine;
using UnityEngine.InputSystem;
#if UNITY_EDITOR
using UnityEditor;
#endif
// Say you want to distinguish a device not only by its type (e.g. "PS4 Controller")
// but also by the way it is used. This is a common scenario for VR controllers, for
// example, where the same type of controller may be used once in the left hand and
// once in the right hand. However, the need for distinguishing devices in a similar
// manner can pop up in a variety of situations. For example, on Switch it is used
// to distinguish the current orientation of the Joy-Con controller ("Horizontal" vs.
// "Vertical") allowing you to take orientation into account when binding actions.
//
// The input system allows you to distinguish devices based on the "usages" assigned
// to them. This is a generic mechanism that can be used to tag devices with arbitrary
// custom usages.
//
// To make this more concrete, let's say we have a game where two players control
// the game together each one using a gamepad but each receiving control over half
// the actions in the game.
//
// NOTE: What we do here is only one way to achieve this kind of setup. We could
// alternatively go and just create one control scheme for the first player
// and one control scheme for the second one and then have two PlayerInputs
// each using one of the two.
//
// So, what we'd like to do is tag one gamepad with "Player1" and one gamepad with
// with "Player2". Then, in the actions we can set up a binding scheme specifically
// for this style of play and bind actions such that are driven either from the
// first player's gamepad or from the second player's gamepad (or from either).
//
// The first bit we need for this is to tell the input system that "Player1" and
// "Player2" are usages that we intend to apply to gamepads. For this, we need
// to modify the "Gamepad" layout. We do so by applying what's called a "layout
// override". This needs to happen during initialization so here we go:
#if UNITY_EDITOR
[InitializeOnLoad]
#endif
public static class InitCustomDeviceUsages
{
static InitCustomDeviceUsages()
{
Initialize();
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Initialize()
{
// Here we register the layout override with the system.
//
// The layout override is just a fragment of layout information
// in JSON format.
//
// The key property here is "commonUsages" which tells the system
// that "Player1" and "Player2" are possible usages applied to devices
// using the given layout ("Gamepad" in our case).
InputSystem.RegisterLayoutOverride(@"
{
""name"" : ""GamepadPlayerUsageTags"",
""extend"" : ""Gamepad"",
""commonUsages"" : [
""Player1"", ""Player2""
]
}
");
// Now that we have done this, you will see that when using the
// control picker in the action editor, that there is now a
// "Gamepad (Player1)" and "Gamepad (Player2)" entry underneath
// "Gamepad". When you select those, you can bind specifically
// to a gamepad with the respective device usage.
//
// Also, you will now be able to *require* a device with the
// given usage in a control scheme. So, when creating a control
// scheme representing the shared Player1+Player2 controls,
// you can add one "Gamepad (Player1)" and one "Gamepad (Player2)"
// requirement.
//
// You can see an example setup for how this would look in an
// .inputactions file in the TwoPlayerControls.inputactions file
// that is part of this sample.
}
}
// However, we are still missing a piece. At runtime, no gamepad will
// receive either the "Player1" or the "Player2" usage assignment yet.
// So none of the bindings will work yet.
//
// To assign the usage tags to the devices, we need to call
// InputSystem.AddDeviceUsage or SetDeviceUsage.
//
// We could set this up any which way. As a demonstration, let's create
// a MonoBehaviour here that simply associates a specific tag with a
// specific gamepad index.
//
// In practice, you would probably want to do the assignment in a place
// where you handle your player setup/joining.
public class CustomDeviceUsages : MonoBehaviour
{
public int gamepadIndex;
public string usageTag;
private Gamepad m_Gamepad;
protected void OnEnable()
{
if (gamepadIndex >= 0 && gamepadIndex < Gamepad.all.Count)
{
m_Gamepad = Gamepad.all[gamepadIndex];
InputSystem.AddDeviceUsage(m_Gamepad, usageTag);
}
}
protected void OnDisable()
{
// If we grabbed a gamepad and it's still added to the system,
// remove the usage tag we added.
if (m_Gamepad != null && m_Gamepad.added)
InputSystem.RemoveDeviceUsage(m_Gamepad, usageTag);
m_Gamepad = null;
}
}