Skip to content

Instantly share code, notes, and snippets.

@Rene-Damm
Created August 30, 2021 11:27
Show Gist options
  • Save Rene-Damm/ec75f7ea6806f21177742bd59d697037 to your computer and use it in GitHub Desktop.
Save Rene-Damm/ec75f7ea6806f21177742bd59d697037 to your computer and use it in GitHub Desktop.
Setting up mock input for InputActions automatically
// Take a set of actions and create an InputDevice for it that has a control
// for each of the actions. Also binds the actions to that those controls.
public static InputDevice SetUpMockInputForActions(InputActionAsset actions)
{
var layoutName = actions.name;
// Build a device layout that simply has one control for each action in the asset.
InputSystem.RegisterLayoutBuilder(() =>
{
var builder = new InputControlLayout.Builder()
.WithName(layoutName);
foreach (var action in actions)
{
builder.AddControl(action.name) // Must not have actions in separate maps with the same name.
.WithLayout(action.expectedControlType);
}
return builder.Build();
}, name: layoutName);
// Create the device.
var device = InputSystem.AddDevice(layoutName);
// Add a control scheme for it to the actions.
actions.AddControlScheme("MockInput")
.WithRequiredDevice($"<{layoutName}>");
// Bind the actions in the newly added control scheme.
foreach (var action in actions)
action.AddBinding($"<{layoutName}>/{action.name}", groups: "MockInput");
// Restrict the actions to bind only to our newly created
// device using the bindings we just added.
actions.bindingMask = InputBinding.MaskByGroup("MockInput");
actions.devices = new[] { device };
return device;
}
[Test]
[Category("Actions")]
public void Actions_CanCreateMockInputDeviceForActions()
{
var keyboard = InputSystem.AddDevice<Keyboard>();
var mouse = InputSystem.AddDevice<Mouse>();
var actions = ScriptableObject.CreateInstance<InputActionAsset>();
actions.name = "MyActions";
actions.AddControlScheme("KeyboardMouse")
.WithRequiredDevice<Keyboard>()
.WithRequiredDevice<Mouse>();
var map = actions.AddActionMap("Gameplay");
var move = map.AddAction("Move", type: InputActionType.Value, expectedControlLayout: "Vector2");
var look = map.AddAction("Look", type: InputActionType.Value, expectedControlLayout: "Vector2");
var fire = map.AddAction("Fire", type: InputActionType.Button, expectedControlLayout: "Button");
move.AddCompositeBinding("Dpad")
.With("Up", "<Keyboard>/w", groups: "KeyboardMouse")
.With("Down", "<Keyboard>/s", groups: "KeyboardMouse")
.With("Left", "<Keyboard>/a", groups: "KeyboardMouse")
.With("Right", "<Keyboard>/d", groups: "KeyboardMouse");
look.AddBinding("<Mouse>/delta", groups: "KeyboardMouse");
fire.AddBinding("<Mouse>/leftButton", groups: "KeyboardMouse");
// So, now we have a pretty standard action setup for kb&mouse.
// Automatically modify the asset to add a "mock" input method.
var mockInput = SetUpMockInputForActions(actions);
Assert.That(move.controls, Is.EquivalentTo(new[] { mockInput["move"] }));
Assert.That(look.controls, Is.EquivalentTo(new[] { mockInput["look"] }));
Assert.That(fire.controls, Is.EquivalentTo(new[] { mockInput["fire"] }));
actions.Enable();
var fireWasPerformed = false;
fire.performed += _ => fireWasPerformed = true;
Press((ButtonControl)mockInput["fire"]);
Assert.That(fireWasPerformed, Is.True);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment