In this lesson, you will learn how to create a unified input abstraction layer that maps disparate platform controls—like keyboard-mouse clicks and mobile touch gestures—into a single, consistent set of game commands.
The Problem of Platform Fragmentation
When developing for both PC and mobile, hard-coding Input.GetKeyDown(KeyCode.Space) alongside Input.GetTouch(0) inside your player controller creates spaghetti code. It makes your logic difficult to debug and hard to extend. Instead, we use the Provider Pattern to decouple what the input is from how the game reacts to it.
Implementing an Abstraction Layer
The goal is to create an interface that defines the "intent" of the player, regardless of the input hardware.
- Define an
IInputProviderinterface that exposes properties likeMoveVectorandIsActionPressed. - Create two concrete classes:
StandaloneInput(usingInput.GetAxis) andMobileInput(usingInput.GetTouchor the newEnhancedTouchAPI). - Use
Preprocessor Directives(as discussed in previous modules) to inject the correct provider at runtime:
public interface IInputProvider {
Vector2 GetMovement();
bool IsInteractPressed();
}
public class GameController : MonoBehaviour {
private IInputProvider _input;
void Awake() {
#if UNITY_ANDROID || UNITY_IOS
_input = new MobileInput();
#else
_input = new StandaloneInput();
#endif
}
void Update() {
// The controller doesn't care if it's touch or mouse/keyboard
Vector2 move = _input.GetMovement();
if (_input.IsInteractPressed()) PerformAction();
}
}
Why This Matters
By abstracting input, your core game logic remains clean and platform-agnostic. This is critical for multiplayer games, where the server-side reconciliation logic depends on consistent, normalized input data. If the MoveVector is always a normalized Vector2 (regardless of whether it came from a joystick thumb-drag or WASD keys), the downstream movement systems and network synchronization scripts can process that data identically. You are essentially turning hardware events into "input intent," which is the gold standard for scalable multi-platform architecture.
Key Takeaway: Decoupling your input logic via an abstraction interface ensures that your game mechanics remain identical across platforms, simplifying synchronization and testing in multiplayer environments.