Kanda Players 0.7.0
Loading...
Searching...
No Matches
Player Input

We use Unity's Input System to handle player input across different devices. This page explains how input is collected and processed, and how to implement basic locomotion for PC and XR players.

Input Collectors

The "Input Collector" approach is used to gather and process input data. This abstraction layer separates the input collection logic from the systems that use the input, allowing for better modularity and easier testing.

Input collectors are implemented as managed components, which allows them to interact directly with Unity's Input System while still being accessible within the ECS framework. They serve as a bridge between the Unity Input System and our ECS-based logic.

Key input collectors include:

  1. IKeyboardInputCollector: Collects keyboard input for movement and actions.
  2. IMouseInputCollector: Collects mouse input for camera control and interactions.
  3. IOpenXrInputCollector: Collects input data from OpenXR devices.

Each collector is responsible for:

  • Setting up appropriate Input Actions
  • Reading input values from these actions
  • Providing methods to access the collected input data

For example, the OpenXrInputCollector sets up actions for HMD position and rotation, and provides methods like GetHmdPosition() and GetHmdRotation() to access this data.

Adding Input to Players

To add input capabilities to a player:

  1. Add the appropriate Input Collector authoring components to your player prefab:
    • KeyboardInputAuthoring (for keyboard input)
    • MouseInputAuthoring (for mouse input)
    • OpenXrInputAuthoring (for OpenXR input)
  2. These components will add the necessary ECS components to your player entity:
    • KeyboardInputData (storing newest keyboard input)
    • MouseInputData (storing newest mouse input)
    • OpenXrInputData (storing newest OpenXR input)

Input System Update

The InputUpdateSystem is responsible for updating the Unity Input System.

The system ensures that the Input System is updated manually, which is necessary when using InputSystem.settings.updateMode = InputSettings.UpdateMode.ProcessEventsManually. This setting is configured in the Startup class to ensure consistent behavior across all platforms.

Implementing PC Player Locomotion

To implement basic movement and looking for PC players:

  1. Add PcHeadKeyboardMovementAuthoring and PcHeadMouseRotationAuthoring to your player head prefab.
  2. These will add the corresponding ECS components: PcHeadKeyboardMovement and PcHeadMouseRotation.
  3. The provided systems will use these components along with the input data to move and rotate the player:
    • PcHeadMovementClientSystem: Handles keyboard-based movement
    • PcHeadLookClientSystem: Handles mouse-based looking

Note: PcHeadMovementClientSystem and PcHeadLookClientSystem depend on PcPlayerSettings, which is produced by PlayerSettingsSystem. PlayerSettingsSystem constructs PcPlayerSettings by combining default configuration values with any user-specific preferences.

Implementing XR Player Locomotion

To implement basic movement for VR players:

  1. Add OpenXrHeadMovementAuthoring to your XR player head prefab.
  2. This will add the corresponding ECS component: OpenXrHeadMovement.
  3. The OpenXrHeadMovementSystem will use this component along with the OpenXrInputData to move and rotate the VR player's head based on the HMD's position and rotation.

Input Synchronization

For multiplayer functionality, input needs to be synchronized between the local player and its remote representation. This is achieved through a combination of components and systems:

Components

  1. ClientTransformInput: An IInputComponentData that allows a client to control the transform of a ghost by providing a target transform as input.
  2. LocalPlayerPartRef: Keeps a reference to a local player part, used on remote player parts to replicate data from the local player.

Synchronization Systems

  1. SynchronizePlayerOriginClientSystem:
    • Synchronizes the local player origin transform to that of the remote player ghost which is owned by the player.
    • This allows the server to apply spawn point logic and force-teleport while keeping the local player synchronized.
  2. SynchronizePlayerHeadClientSystem:
    • Finds the remote PlayerHead, ensures it has a reference to the local PlayerHead.
    • Writes the LocalTransform of the local head to the ClientTransformInput component of the remote head.
  3. ClientTransformInputSystem:
    • Applies input from ClientTransformInput to the adjacent LocalTransform.
    • Runs for both clients and servers, allowing for local prediction.

This synchronization setup ensures that:

  • The local player's movements are accurately reflected on remote clients.
  • Server-side logic (like spawn points or teleportation) is properly applied to all clients.
  • The game maintains a consistent state across all connected players.

Adding New Input Types

To add new types of input:

  1. Create a new input collector interface and implementation.
  2. Register the input collector in Startup.cs
  3. Create corresponding authoring and ECS components.
  4. Implement a system that processes the new input data and applies it to the player or game state.

This structure allows you to extend the input system to support new devices or input methods while maintaining compatibility with the existing ECS framework.

Cursor Control

We provide ECS-based mouse cursor control through the CursorState component and CursorStateInitializationSystem.

Setting Initial Cursor State

1. Add CursorState component to an entity:

var cursorState = new CursorState {
VisibleOnStart = false,
LockModeOnStart = CursorLockMode.Locked
};

This is added by default if using the high-level LocalPcPlayerHeadAuthoring script.

2. The CursorStateInitializationSystem will apply these settings on startup.

Runtime Cursor Modification

Query and modify cursor state from any system:

foreach (var cursorState in SystemAPI.Query()) {
var cursor = cursorState.Get();
cursor.Visible = false; // Hide cursor
cursor.LockMode = CursorLockMode.Confined; // Keep cursor within window
}

Available lock modes:

  • None: Cursor moves freely
  • Locked: Cursor is hidden and locked to center
  • Confined: Cursor stays within window bounds