Touch

Implementation guide for handling touch contacts in your game.

New to Board’s touch system? Read Touch first to understand how Board handles unlimited contacts, noise rejection, and Piece recognition.

Getting Active Contacts

Access current contacts through BoardInput.GetActiveContacts():

using Board.Input;

void Update()
{
    // Get all active contacts (fingers and Pieces)
    var contacts = BoardInput.GetActiveContacts();

    foreach (var contact in contacts)
    {
        ProcessContact(contact);
    }
}

Filtering by Type

Filter contacts by type to handle fingers and Pieces separately:

// Only finger touches
var fingers = BoardInput.GetActiveContacts(BoardContactType.Finger);

// Only Pieces
var pieces = BoardInput.GetActiveContacts(BoardContactType.Glyph);

// Both (explicit)
var all = BoardInput.GetActiveContacts(BoardContactType.Finger, BoardContactType.Glyph);

Checking if a Contact is Active

// Check if a specific contact is still active
bool isActive = false;
foreach (var c in BoardInput.GetActiveContacts())
{
    if (c.contactId == savedContactId) { isActive = true; break; }
}

Contact Properties

Each BoardContact provides:

Property Type Description
contactId int Unique identifier for this contact session
type BoardContactType Finger or Glyph
screenPosition Vector2 Position in screen coordinates (pixels)
previousScreenPosition Vector2 Position in the previous frame
orientation float Rotation in radians counter-clockwise from vertical (Pieces only)
previousOrientation float Rotation in the previous frame
phase BoardContactPhase Current contact phase
isTouched bool Whether a finger is touching the Piece (always true for Finger contacts)
glyphId int Which Piece from the set (Pieces only)
timestamp double Time when this contact was last updated
isInProgress bool Whether the contact is currently active (not ended or canceled)

Position

Screen position is in pixel coordinates matching the display resolution (1920×1080):

Vector2 position = contact.screenPosition;

// Convert to world position (for 2D games)
Vector3 worldPos = Camera.main.ScreenToWorldPoint(
    new Vector3(position.x, position.y, 10f)
);

Orientation

Piece rotation in radians counter-clockwise from vertical:

float rotation = contact.orientation;

// Apply to a transform (convert radians to degrees for Euler)
transform.rotation = Quaternion.Euler(0, 0, rotation * Mathf.Rad2Deg);

Delta Values

Calculate movement and rotation between frames:

Vector2 deltaPosition = contact.screenPosition - contact.previousScreenPosition;
float deltaRotation = contact.orientation - contact.previousOrientation;

Contact Phases

Contact phases indicate the lifecycle of a touch or Piece placement:

Phase Description
Began Contact started this frame
Moved Contact position or rotation changed
Stationary Contact is active but unchanged
Ended Contact ended normally (lifted)
Canceled Contact ended abnormally (e.g., pause screen opened)

Note: When the pause screen opens, all active contacts are canceled. Your game should handle this by cleaning up any contact-related state when receiving Canceled phases.

Handling Phases

void ProcessContact(BoardContact contact)
{
    switch (contact.phase)
    {
        case BoardContactPhase.Began:
            // Create visual representation, start tracking
            SpawnContactVisual(contact);
            break;

        case BoardContactPhase.Moved:
            // Update position/rotation
            UpdateContactVisual(contact);
            break;

        case BoardContactPhase.Stationary:
            // Contact unchanged, may still need processing
            break;

        case BoardContactPhase.Ended:
        case BoardContactPhase.Canceled:
            // Clean up
            RemoveContactVisual(contact);
            break;
    }
}

Phase Helper Methods

// True for Began, Moved, or Stationary
bool isActive = contact.phase.IsActive();

// True for Ended or Canceled
bool isFinished = contact.phase.IsEndedOrCanceled();

// Alternative property
bool isInProgress = contact.isInProgress;

Piece Touch State

Pieces report whether a finger is touching them:

if (contact.type == BoardContactType.Glyph)
{
    if (contact.isTouched)
    {
        // Player is holding the Piece
        HighlightPiece(contact);
    }
    else
    {
        // Piece is on Board but not being touched
        ShowIdleState(contact);
    }
}

This enables interactions like:

  • Highlighting Pieces when picked up
  • Different behavior for touched vs. resting Pieces
  • Detecting when a player releases a Piece

Glyph IDs

For Piece contacts, glyphId identifies which Piece from the set:

if (contact.type == BoardContactType.Glyph)
{
    int pieceType = contact.glyphId;

    // Map to game objects
    switch (pieceType)
    {
        case 0: SpawnWarrior(contact); break;
        case 1: SpawnMage(contact); break;
        case 2: SpawnArcher(contact); break;
        // ... etc
    }
}

Note: Glyph IDs are indices (0 to N-1) within your Piece Set. To determine which ID corresponds to which physical Piece, place each Piece on Board one at a time and log the glyph ID.

Input Settings

Configure tracking behavior through BoardInputSettings:

Setting Default Description
Translation Smoothing 0.5 Smooths position updates. 0 = raw values, 1 = maximum smoothing. Lower values improve responsiveness; higher values reduce jitter.
Rotation Smoothing 0.5 Smooths orientation updates. Same range as translation smoothing. Higher values help with rotational jitter.
Persistence 4 How many frames a Piece remains tracked after losing detection. Higher values keep Pieces “alive” during brief detection gaps. Finger contacts die immediately when detection is lost.

Changing Settings at Runtime

// Load a different settings asset
BoardInput.settings = myAlternateSettings;

// Note: This cancels all active contacts

Access the settings through BoardInput.settings.

Note: If the new settings use a different pieceSetModelFilename (Piece Set), there will be a brief delay while the new model loads. Touch input is unavailable during this time. Plan model switches during transitions (e.g., loading screens) rather than mid-gameplay.

Multiple Input Settings

You can create multiple BoardInputSettings assets for different configurations (e.g., different Piece Sets or smoothing values).

Creating Additional Settings Assets

From Project Settings:

  1. Open Edit > Project Settings > Board > Input Settings
  2. Click the dropdown at the top showing the current settings asset
  3. Select New Settings Asset… to create a new one

Manually:

  1. Right-click in the Project window
  2. Select Create > Board > Input Settings
  3. Configure the new asset

Note: BoardInputSettings properties (smoothing, persistence) are readonly at runtime. To use different values, create separate settings assets and switch between them.

Runtime Settings Switching

When you assign a different BoardInputSettings to BoardInput.settings:

  • All active contacts are immediately canceled — any Pieces or fingers being tracked receive a Canceled phase and must be re-detected
  • Assigning the same object reference is a no-op — the setter returns early if the settings haven’t changed
// Load a different settings asset
var alternateSettings = Resources.Load<BoardInputSettings>("AlternateBoardInputSettings");
BoardInput.settings = alternateSettings;

The Piece Set Model determines whether there’s an additional delay:

Scenario Behavior
Same model, different parameters Contacts reset, new parameters apply immediately (~1-10ms)
Different model Contacts reset, model loads (~500ms-1s delay during which no touches are detected)

This means if you have multiple settings assets that share the same Piece Set Model (but differ in smoothing/persistence), switching between them is fast. Only changing the model file incurs the loading delay.

Downloading models for multiple settings:

When downloading a model through Project Settings, it’s applied to the currently selected BoardInputSettings asset. Use the dropdown at the top of Input Settings to switch between assets before downloading.

Debug Overlay UI

Visualize contacts during development using BoardInput.enableDebugView:

// Enable the overlay
BoardInput.enableDebugView = true;

// Check current state
if (BoardInput.enableDebugView)
{
    // Overlay is active
}

The overlay displays:

  • Contact position and orientation
  • Contact ID and glyph ID
  • Touch state indicator
  • Contact type (finger vs. Piece)

Note: The debug overlay only works in Development builds. Enable Development Build in Build Settings.

When to Use

  • Verifying Piece detection accuracy
  • Debugging position/rotation tracking
  • Testing touch responsiveness
  • Diagnosing false positive contacts

UI Input

Add BoardUIInputModule to your EventSystem GameObjects. Use Board > Input > Add BoardUIInputModule to EventSystems for quick setup, or add the component manually.

BoardUIInputModule and InputSystemUIInputModule can coexist: in the Editor, BoardUIInputModule receives no input (no hardware), so InputSystemUIInputModule handles mouse and keyboard normally.

See Setup Reference for full configuration details.

UIToolkit Pointer Limit

When using UIToolkit (UI Toolkit / UI Elements), Unity imposes a 32-pointer limit on simultaneous input events. This is a Unity platform limitation, not a Board limitation.

The SDK handles this automatically:

  • The first 32 contacts work normally
  • Additional contacts beyond the limit are held in a queue
  • When an existing contact ends or is canceled, queued contacts immediately receive their Began event
  • No active contacts are interrupted or repositioned—existing interactions are always preserved

This behavior ensures smooth UX even when many fingers and Pieces are on Board simultaneously. In most games, you’ll never encounter this limit.

Note: This limit only affects UIToolkit. If you’re using uGUI (Canvas-based UI) or handling input directly through BoardInput, there is no pointer limit.

See Also

  • Touch - How Board’s touch technology works
  • Simulator - Test input without hardware
  • Hardware - Touch panel specifications
  • Concepts - Terminology and definitions