Managing inputs in Unity can quickly become unwieldy, especially when dealing with multiple devices and input schemes. This guide explores a modular approach using ScriptableObjects to manage device-specific icons, decouple input events, and enable dependency injection for flexibility.
Goals
- Ease of Management: Simplify handling device-specific input icons.
- Decoupling: Avoid relying on a centralized input manager.
- Flexibility: Use ScriptableObjects for modular and reusable input definitions.
Drawbacks
InputActionDefinitionOnInputreturns aCallbackContextthat can have any information- Subscribers have to assume the
CallbackContexthas the info they need (ex. aVector2)
Steps
Follow these steps to implement this architecture:
- Setup Input Actions: Open a Unity
InputActionasset and configure the necessary inputs. - Create InputActionDefinitions: For each input, create an
InputActionDefinitionScriptableObject. - Add a PlayerInput Component: Attach a
PlayerInputcomponent to a GameObject in the scene. - Set to Invoke Unity Events: Configure the
PlayerInputcomponent’s behavior to Invoke Unity Events. - Bind Input Definitions: Assign an
InputActionDefinitionto trigger theFire()method for each input action. - Inject Inputs Where Needed: In future components, reference the appropriate
InputActionDefinitionassets to handle inputs.
Architecture Diagram
Below is a high-level architecture diagram of this setup:
classDiagram
class ScriptableObject
class InputActionDefinition {
+name : string
+keyboardIcon : Sprite
+gamepadIcon : Sprite
+touchIcon : Sprite
+OnInput : Action~InputAction.CallbackContext~
+Fire() void
+GetIcon() Sprite
}
ScriptableObject <|-- InputActionDefinition
InputActionDefinition -- Move.asset : Create SO
InputActionDefinition -- Jump.asset : Create SO
Move.asset <.. PlayerController : References
Jump.asset <.. PlayerController : References
class PlayerController {
+InputActionDefinition OnMove
+InputActionDefinition OnJump
+Move() void
+Jump() void
}
class PlayerInput {
}
note for PlayerController "Pass in the desired definition assets.
Use their OnInput event." note for PlayerInput "Set behavior to invoke Unity Event.
Match the InputActions with
the related InputActionDefinition"
Use their OnInput event." note for PlayerInput "Set behavior to invoke Unity Event.
Match the InputActions with
the related InputActionDefinition"
Example PlayerInput Component
Example Implementation
Here’s a simple example of how input handling might look in your script:
//PlayerController.cs
[SerializeField] InputActionDefinition OnMove;
[SerializeField] InputActionDefinition OnJump;
private void Start()
{
OnMove.OnInput += HandleMove;
OnJump.OnInput += HandleJump;
}
private void HandleMove(InputAction.CallbackContext ctx) {
Vector2 movement = ctx.ReadValue<Vector2>();
// Movement Logic
}
private void HandleJump(InputAction.CallbackContext ctx) {
if (ctx.started) {
// Jump Logic
}
}
