Input Mapper
Input Mapper is a class that greatly simplifies the process of remapping controls. It handles listening for controller input, conflict checking, and creating Action-element assignments in a Controller Map.
Please see How To's - Creating a Control Mapping Screen before creating a control remapping system using Input Mapper.
Usage
The basic process is as follows:
- Create an Input Mapper.
- Configure Options.
- Subscribe to events.
- Create a mapping Context.
- Start listening for input.
- Handle assignment conflicts (optional).
- Advanced operations (optional).
For additional issues, see the FAQ.
You can either create a new instance of an Input Mapper or use the Default instance as shown below:
// Create a new instance InputMapper inputMapper = new InputMapper(); inputMapper.Start(context); // Or you can use the Default instance instead if you only need one Input Mapper InputMapper.Default.Start(context);
Each Input Mapper has an Options object which allows you to configure various settings to fit your needs. These settings should be configured before starting the Input Mapper. Each available option is described in the class documentation.
inputMapper.options.timeout = 5f; // set the timeout to 5 seconds inputMapper.options.ignoreMouseXAxis = true; // ignore the mouse X axis when polling for input inputMapper.options.ignoreMouseYAxis = true; // ignore the mouse Y axis when polling for input
There are numerous events to which you can subscribe to receive notifications when important events take place such as when an input assignment is made or when an assignment conflict is found.
inputMapper.InputMappedEvent += OnInputMapped; inputMapper.ConflictFoundEvent += OnConflictFound;
A mapping context provides information about the current mapping session. The mapping context is just a few pieces of information that informs the Input Mapper about what is being mapped.
InputMapper.Context context = new InputMapper.Context() { actionId = action.id, // the id of the Action being mapped
controllerMap = controllerMap, // the Controller Map which will have the new mapping added
actionRange = AxisRange.Full, // the range of the Action being mapped
actionElementMapToReplace = actionElementMap // the Action Element Map to be replaced (optional)
};
inputMapper.Start(context);
6. Handle assignment conflicts (optional)
Conflict checking is enabled by default in InputMapper.Options. See How To's - Conflict Checking for more information.
If you subscribed to the InputMapper.ConflictFoundEvent, you will receive a notification when a conflicting assignment was found during input mapping. The object returned contains complete information about the assignment, the conflicts that were found, and provides a callback to be used to respond to the event.
private InputMapper.ConflictFoundEventData conflictData; void OnConflictFound(InputMapper.ConflictFoundEventData data) { conflictData = data; // store the event data for use in user response if(data.isProtected) { // the conflicting assignment was protected and cannot be replaced // Display some message to the user asking whether to cancel or add the new assignment. // Protected assignments cannot be replaced. // ... // ... After the user has made a decision conflictData.responseCallback(InputMapper.ConflictResponse.Cancel); // cancel polling } else { // Display some message to the user asking whether to cancel, replace the existing, // or add the new assignment. // ... // ... After the user has made a decision // Tell the Input Mapper to replace the conflicting assignments conflictData.responseCallback(InputMapper.ConflictResponse.Replace); } }
If you do not subscribe to the ConflictsFoundEvent and you have left conflict checking enabled in the Options.checkForConflicts property, the default action specified in Options.defaultActionWhenConflictFound will be used to resolve the conflict(s).
7. Advanced operations (optional)
Ignoring certain controller elements:
void Setup() { // When setting up Options, add a callback to handle element confirmation inputMapper.options.isElementAllowedCallback = OnIsElementAllowed; // manually allow or ignore specific elements } // Called by InputMapper when a controller element is activated while polling bool OnIsElementAllowed(ControllerPollingInfo info) { // Ignore the Space key on the keyboard if(info.controllerType == ControllerType.Keyboard && info.keyboardKey == KeyCode.Space) return false; // Allow all other controller elements return true; }
Using multiple Input Mappers to listen to multiple input devices at the same time:
See Simple Combined Keyboard Mouse Remapping example for a working example.
// Begin listening for input on both keyboard and mouse at the same time inputMapper_keyboard.Start( new InputMapper.Context() { actionId = actionId, controllerMap = keyboardMap, actionRange = actionRange, actionElementMapToReplace = keyboardMap.GetElementMap(actionElementMapToReplaceId) } ); inputMapper_mouse.Start( new InputMapper.Context() { actionId = actionId, controllerMap = mouseMap, actionRange = actionRange, actionElementMapToReplace = mouseMap.GetElementMap(actionElementMapToReplaceId) } );
Frequently Asked Questions
Why is binding replacement not working?
You must pass the ActionElementMap to be replaced in InputMapper.Context.actionElementMapToReplace when calling InputMapper.Start. After an ActionElementMap is replaced, a new ActionElementMap is created. If you are storing a reference to the ActionElementMap and then it is replaced, the reference to the old ActionElementMap is no longer valid because itpoints to an ActionElementMap that is no longer present in the Controller Map. If you are storing a reference to the ActionElementMap, you must update your reference to the new ActionElementMap after it is replaced.
In addition, whether replacement happens automatically when a mapping conflict is found is determined by InputMapper.Options.defaultActionWhenConflictFound. You can also handle conflicts manually and determine what happens to conflicting bindings.