docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    Add a layout from C#

    In its most basic form, a layout can be expressed by a C# class derived from:

    • InputControl for a Control layout.
    • InputDevice for a Device layout.
    // The InputControlLayout attribute is not strictly necessary here.
    // However, you can use it to set additional properties (such as
    // a custom display name for the layout).
    [InputControlLayout]
    public class MyDevice : InputDevice
    {
        public AxisControl axis { get; private set; }
        public ButtonControl button { get; private set; }
    
        protected override void FinishSetup(InputDeviceBuilder builder)
        {
            base.FinishSetup(builder);
    
            axis = builder.GetControl<AxisControl>("axis");
            button = builder.GetControl<ButtonControl>("button");
        }
    }
    

    You can then register the layout with InputSystem.RegisterLayout. This works the same for Control and for Device layouts.

    // Note: This should generally be done from InitializeOnLoad/
    // RuntimeInitializeOnLoad code.
    InputSystem.RegisterLayout<MyDevice>();
    

    When the layout is instantiated, the system looks at every field and property defined directly in the type to potentially turn it into one or more Control items.

    1. If the field or property is annotated with InputControlAttribute, the system applies the attribute's properties to the Control item. Some special defaults apply in this case:
      • If no offset is set, and the attribute is applied to a field, offset defaults to the offset of the field.
      • If no name is set, it defaults to the name of the property/field.
      • If no layout is set, the system infers it from the type of the field/property.
    2. If the field or property has a struct type which implements IInputStateTypeInfo, the field is considered to be an embedded state struct and the system recurses into the field or property to gather Controls from it.
    3. Otherwise, if the type of the field or property is based on InputControl, the system adds a Control item similar to case 1, where the member is annotated with InputControlAttribute.

    Using a state structure

    When you implement support for a new Input Device, there's usually an existing data format in which the Input System receives input for the Device. The easiest way to add support for the data format is to describe it with a C# struct annotated with InputControlAttribute.

    public struct MyDeviceState : IInputStateTypeInfo
    {
        public FourCC format => new FourCC('M', 'D', 'E', 'V');
    
        [InputControl(name = "button1", layout = "Button", bit = 0)]
        [InputControl(name = "button2", layout = "Button", bit = 1)]
        [InputControl(name = "dpad", layout = "Dpad", bit = 2, sizeInBits = 4)]
        [InputControl(name = "dpad/up", bit = 2)]
        [InputControl(name = "dpad/down", bit = 3)]
        [InputControl(name = "dpad/left", bit = 4)]
        [InputControl(name = "dpad/right", bit = 5)]
        public int buttons;
    
        [InputControl(layout = "Stick")]
        public Vector2 stick;
    
        [InputControl(layout = "Axis")] // Automatically converts from byte to float.
        public byte trigger;
    }
    
    // The Device must be directed to the state struct we have created.
    [InputControlLayout(stateType = typeof(MyDeviceState)]
    public class MyDevice : InputDevice
    {
    }
    
    In This Article
    Back to top
    Copyright © 2026 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)