Create custom composite bindings
You can define new types of Composites, and register them with the API. Unity treats these the same as predefined types, which the Input System internally defines and registers in the same way.
To define a new type of Composite, create a class based on InputBindingComposite<TValue>.
Important
Composites must be stateless. This means that you cannot store local state that changes depending on the input being processed. For stateful processing on bindings, refer to interactions.
// Use InputBindingComposite<TValue> as a base class for a composite that returns
// values of type TValue.
// NOTE: It is possible to define a composite that returns different kinds of values
// but doing so requires deriving directly from InputBindingComposite.
#if UNITY_EDITOR
[InitializeOnLoad] // Automatically register in editor.
#endif
// Determine how GetBindingDisplayString() formats the composite by applying
// the DisplayStringFormat attribute.
[DisplayStringFormat("{firstPart}+{secondPart}")]
public class CustomComposite : InputBindingComposite<float>
{
// Each part binding is represented as a field of type int and annotated with
// InputControlAttribute. Setting "layout" restricts the controls that
// are made available for picking in the UI.
//
// On creation, the int value is set to an integer identifier for the binding
// part. This identifier can read values from InputBindingCompositeContext.
// See ReadValue() below.
[InputControl(layout = "Button")]
public int firstPart;
[InputControl(layout = "Button")]
public int secondPart;
// Any public field that is not annotated with InputControlAttribute is considered
// a parameter of the composite. This can be set graphically in the UI and also
// in the data (For example, "custom(floatParameter=2.0)").
public float floatParameter;
public bool boolParameter;
// This method computes the resulting input value of the composite based
// on the input from its part bindings.
public override float ReadValue(ref InputBindingCompositeContext context)
{
var firstPartValue = context.ReadValue<float>(firstPart);
var secondPartValue = context.ReadValue<float>(secondPart);
//... do some processing and return value
}
// This method computes the current actuation of the binding as a whole.
public override float EvaluateMagnitude(ref InputBindingCompositeContext context)
{
// Compute normalized [0..1] magnitude value for current actuation level.
}
static CustomComposite()
{
// Can give custom name or use default (type name with "Composite" clipped off).
// Same composite can be registered multiple times with different names to introduce
// aliases.
//
// NOTE: Registering from the static constructor using InitializeOnLoad and
// RuntimeInitializeOnLoadMethod is only one way. You can register the
// composite from wherever it works best for you. Note, however, that
// the registration has to take place before the composite is first used
// in a binding. Also, for the composite to show in the editor, it has
// to be registered from code that runs in edit mode.
InputSystem.RegisterBindingComposite<CustomComposite>();
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void Init() {} // Trigger static constructor.
}
The Composite should now appear in the editor UI when you add a binding, and you can now use it in scripts.
myAction.AddCompositeBinding("custom(floatParameter=2.0)")
.With("firstpart", "<Gamepad>/buttonSouth")
.With("secondpart", "<Gamepad>/buttonNorth");
To define a custom parameter editor for the Composite, you can derive from InputParameterEditor<TObject>.
#if UNITY_EDITOR
public class CustomParameterEditor : InputParameterEditor<CustomComposite>
{
public override void OnGUI()
{
EditorGUILayout.Label("Custom stuff");
target.floatParameter = EditorGUILayout.FloatField("Some Parameter", target.floatParameter);
}
}
#endif