OKONAONLINE

Developer Docs

Unity SDK

OkonaPad

A lightweight Unity SDK for integrating smartphone controllers into your WebGL games. Drop it in, map your inputs, and let Okona handle the rest.

Introduction

OkonaPad is a lightweight Unity SDK for integrating smartphone controllers into WebGL games hosted on the Okona Online platform. The SDK receives controller input from the website shell via JavaScript interop, translating it into Unity Input System events.

Key Features

  • Seamless Unity Input System integration
  • Support for up to 6 concurrent controllers
  • Binary protocol for efficient input transmission
  • Controller slot system with disconnect/reconnect handling
  • Custom InputDevice with buttons, D-pad, and joystick
  • Haptic feedback support via rumble callbacks

Architecture

Phone Browser
Okona Website
JS Interop
OkonaInputBridge
Unity Input System

The Okona Online website handles all networking (WebSocket connections, QR codes, controller UI). Your Unity WebGL game only needs to receive input through the OkonaInputBridge component.

System Requirements

Unity Requirements

  • Unity 6 (6000.3.2f1) or higher
  • Input System package (com.unity.inputsystem) v1.17.0+

Build Target

  • WebGL (primary target for Okona Online integration)

Project Settings

  1. Open Edit > Project Settings > Player > Other Settings
  2. Set Active Input Handling to Both or Input System (New)
  3. Ensure the Input System package is installed via Package Manager

Quick Start Guide

1

Add OkonaInputBridge to Your Scene

Create an empty GameObject and add the OkonaInputBridge component:

using OkonaPad.Input;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    [SerializeField] private OkonaInputBridge inputBridge;

    void Awake()
    {
        // OkonaInputBridge automatically registers the
        // OkonaPadControllerDevice with Unity's Input System
    }
}

Or simply add the OkonaInputBridge component to any GameObject in your scene via the Unity Inspector.

2

Configure Input Actions

  1. Open or create an Input Actions asset
  2. Map your actions to OkonaPad controls using <OkonaPad>/buttonA, <OkonaPad>/leftStick, etc.
  3. The OkonaPadControllerDevice appears as OkonaPad in the Input System
  4. Use <OkonaPad> as the device requirement in your control scheme
3

Build for WebGL

  1. File > Build Settings > WebGL
  2. Build your project
  3. Deploy to Okona Online platform

The website shell automatically establishes connections with phone controllers and forwards input to your game.

API Reference

OkonaInputBridge

OkonaPad.Input.OkonaInputBridge

The main component that receives input from the website and updates Unity Input System devices.

Lifecycle Methods

Called by the website shell via JavaScript SendMessage:

// Called when a phone controller connects or reconnects
public void OnControllerConnected(int controllerId)

// Called when a phone controller temporarily disconnects
public void OnControllerDisconnected(int controllerId)

// Called when a phone controller is permanently removed
public void OnControllerRemoved(int controllerId)

// Called with binary input data (JSON with base64 payload)
// Format: {"controllerId":1,"data":"base64string"}
public void ReceiveControllerMessageBase64(string jsonData)

Events

// New device created for the first time
event Action<int, OkonaPadControllerDevice> OnDeviceConnected;

// Temporary disconnect - device preserved
event Action<int> OnDeviceDisconnected;

// Previously disconnected device has reconnected
event Action<int, OkonaPadControllerDevice> OnDeviceReconnected;

// Permanent removal - device destroyed
event Action<int> OnDeviceRemoved;

Helper Methods

// Get device for a specific controller ID (null if not found)
public OkonaPadControllerDevice GetDevice(int controllerId)

// Get connection state for a controller
public DeviceConnectionState? GetConnectionState(int controllerId)

// Get all controller IDs (connected and disconnected)
public int[] GetAllControllerIds()

// Get only connected controller IDs
public int[] GetConnectedControllerIds()

// Enable/disable debug logging
public void EnableDebugLogging(bool enable)

OkonaPadControllerDevice

OkonaPad.Input.OkonaPadControllerDevice

Custom Unity InputDevice representing a smartphone controller. This is not a Gamepad — it only exposes controls that physically exist on the phone controller.

Controls

ControlTypeDescription
ButtonAButtonControlA button
ButtonBButtonControlB button
ButtonXButtonControlX button
ButtonYButtonControlY button
StartButtonButtonControlStart button
SelectButtonButtonControlSelect button
DPadDpadControlDirectional pad
LeftStickStickControlAnalog joystick

Input Binding Paths

ControlBinding Path
A button<OkonaPad>/buttonA
B button<OkonaPad>/buttonB
X button<OkonaPad>/buttonX
Y button<OkonaPad>/buttonY
Start<OkonaPad>/startButton
Select<OkonaPad>/selectButton
D-pad<OkonaPad>/dpad
Left Stick<OkonaPad>/leftStick

Properties

PropertyTypeDescription
ControllerIdintController slot identifier (1-6)

Haptic Feedback

OkonaPadControllerDevice implements IDualMotorRumble. Subscribe to the static event to forward rumble to controllers:

OkonaPadControllerDevice.OnRumbleRequested += (controllerId, lowFreq, highFreq) =>
{
    // Forward haptic feedback to the phone controller
};

Usage Example

using OkonaPad.Input;
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    private OkonaPadControllerDevice controller;

    void Start()
    {
        var bridge = OkonaInputBridge.Instance;
        if (bridge != null)
        {
            bridge.OnDeviceConnected += (id, device) =>
                controller = device;
            bridge.OnDeviceRemoved += (id) =>
            {
                if (controller?.ControllerId == id)
                    controller = null;
            };
        }
    }

    void Update()
    {
        if (controller == null) return;

        // Read button states
        if (controller.ButtonA.wasPressedThisFrame)
            Jump();

        // Read joystick
        Vector2 movement = controller.LeftStick.ReadValue();
        Move(movement);

        // Read D-Pad
        if (controller.DPad.up.isPressed)
            MoveUp();
    }
}

Using PlayerInputManager (Recommended)

For multiplayer, use Unity's PlayerInputManager with "Join Players When Button Is Pressed". Players auto-destroy when their device is removed:

private PlayerInput _playerInput;

void Awake()
{
    _playerInput = GetComponent<PlayerInput>();
    _playerInput.onDeviceLost += (pi) => Destroy(gameObject);
}

BinaryProtocol

OkonaPad.Networking.Binary

Defines the binary message format for controller input. Messages use a length-prefixed format:

[Length: 2 bytes BE] [MessageType: 1 byte] [Payload: variable]

Message Types

TypeValuePayloadDescription
Button0x00[buttonCode:1][pressed:1]Button press/release
Dpad0x01[direction:1][pressed:1]D-pad direction
Joystick0x02[x:2][y:2] (int16 BE)Left joystick
Join0x03(none)Connection handshake
Pong0x04(none)Keep-alive response
Rumble0x05[duration:2] (uint16 BE)Haptic feedback

Button Codes

ButtonValue
A0x00
B0x01
X0x02
Y0x03
Start0x04
Select0x05

D-pad Directions

DirectionValue
Up0x00
Down0x01
Left0x02
Right0x03

Integration with Okona Online

How It Works

  1. Website Shell — The Okona Online website hosts your WebGL game in a container
  2. Controller Management — The website handles phone connections via WebSocket and manages controller slots (1-6)
  3. Input Forwarding — Controller input is forwarded to your game via Unity's SendMessage()
  4. Rumble Feedback — Your game sends haptic feedback through OkonaSendRumbleToController, which calls window.okonaOnRumble() on the website

JavaScript Interop

The SDK includes OkonaInterop.jslib which sets up communication between Unity and the website shell.

Website → Unity (via SendMessage)

// When a phone controller connects:
unityInstance.SendMessage('OkonaInputBridge',
    'OnControllerConnected', controllerId);

// When a phone controller temporarily disconnects:
unityInstance.SendMessage('OkonaInputBridge',
    'OnControllerDisconnected', controllerId);

// When a phone controller is permanently removed:
unityInstance.SendMessage('OkonaInputBridge',
    'OnControllerRemoved', controllerId);

// When input data arrives:
unityInstance.SendMessage('OkonaInputBridge',
    'ReceiveControllerMessageBase64',
    JSON.stringify({
        controllerId: controllerId,
        data: base64EncodedData
    }));

Unity → Website (via jslib)

// The website shell should define this to receive rumble:
window.okonaOnRumble = function(controllerId, durationMs) {
    // Forward haptic feedback to the phone controller
};

Deployment

  1. Build your Unity project for WebGL
  2. Upload to Okona Online via the Developer Portal
  3. Configure your game settings in the Okona dashboard
  4. The platform handles controller connections automatically

Troubleshooting

Controller Not Detected

  • Verify OkonaInputBridge component is in the scene
  • Ensure the GameObject is named exactly OkonaInputBridge (required for SendMessage)
  • Check browser console for JavaScript errors
  • Verify Input System package is installed and configured

Input Not Responding

  • Check that Input Actions use <OkonaPad>/ binding paths (not <Gamepad>/)
  • Verify the device is registered: check InputSystem.devices for OkonaPadControllerDevice
  • Enable debug logging: OkonaInputBridge.Instance.EnableDebugLogging(true)

Rumble Not Working

  • Ensure window.okonaOnRumble callback is defined in the website shell
  • Check that the controller supports haptic feedback
  • Verify the device implements IDualMotorRumble

WebGL Build Issues

  • Ensure "Input System (New)" is enabled in Project Settings
  • Check that assembly definitions are properly configured
  • Verify no server-side code is included (WebGL cannot run HTTP/WebSocket servers)

Debug Logging

Enable verbose logging via the bridge:

OkonaInputBridge.Instance.EnableDebugLogging(true);

Check the browser's developer console (F12) for log output.

Ready to build?

Download the SDK and start integrating smartphone controllers into your Unity WebGL game.

Back to Okona