開始使用 Input SDK

本主題說明如何在支援 Google Play 遊戲的遊戲中,設定及顯示 Input SDK 疊加層。這些工作包含將 SDK 新增至遊戲並產生輸入項目對應,其中包含了使用者輸入指派的遊戲動作。如果遊戲支援按鍵繫結變更,您也必須透過 SDK 追蹤及同步處理變更。

事前準備

在遊戲中新增 Input SDK 之前,您必須先新增鍵盤與滑鼠支援。

新增 SDK

在模組層級 build.gradle 檔案 (可能位於 app 目錄內) 中加入依附元件,以便取得 Java 或 Kotlin 的 Input SDK:

dependencies {
  implementation 'com.google.android.libraries.play.games:inputmapping:1.0.0-beta'
  ...
}

Unity 的 Input SDK 尚無法提供下載。Unity 開發人員之後可透過 unitypackagetgz 使用此 SDK。

別忘了表達使用意願,以率先存取新的 SDK。

產生輸入項目對應

輸入項目對應代表的是使用者輸入指派的遊戲動作,顯示在 Input SDK 疊加層中。如要產生輸入項目對應,您必須建立 InputMap 並透過 InputMappingProvider 將其傳回。

以下是 InputMappingProvider 的示例大綱:

Kotlin

class MyInputMapProvider : InputMappingProvider {
    override fun onProvideInputMap(): InputMap {
        TODO("Not yet implemented")
    }
}

Java

public class MyInputMapProvider implements InputMappingProvider {
    @NonNull
    @Override
    public InputMap onProvideInputMap() {
        // TODO: return an InputMap
    }
}

C#

private class MyInputMappingProvider : PlayInputMappingProvider
{
    public PlayInputMap OnProvideInputMap()
    {
        // TODO("Not yet implemented")
    }
}

以下章節將說明如何建立 InputMap,以便從 InputMappingProvider 傳回。

定義輸入動作

InputAction 類別是用於將按鍵或按鍵組合對應至遊戲動作。

以下示例會將空白鍵對應至跳躍動作:

Kotlin

val jumpInputAction = InputAction.create(
    "Jump",
    InputEventIds.JUMP.id,
    InputControls.create(
        listOf(KeyEvent.KEYCODE_SPACE),
        emptyList()
    )
)

Java

InputAction jumpInputAction = InputAction.create(
        "Jump",
        InputEventIds.JUMP.ordinal(),
        InputControls.create(
                Collections.singletonList(KeyEvent.KEYCODE_SPACE),
                Collections.emptyList()
        )
);

C#

var jumpInputAction = PlayInputAction.Create(
    "Jump",
    (int)InputEventIds.Jump,
    PlayInputControls.Create(
        new[]
        {
            AndroidKeyCode.KEYCODE_SPACE
        },
        null
    )
);

「跳躍」動作與空白鍵繫結的輸入項目疊加層螢幕截圖。

動作也可以代表滑鼠輸入。這個示例會將按一下滑鼠右鍵的動作設為移動動作:

Kotlin

val cmbMove = InputAction.create(
    "Move",
    InputEventIds.CMB_MOVE.id,
    InputControls.create(
        emptyList(),
        listOf(InputControls.MOUSE_RIGHT_CLICK)
    )
)

Java

InputAction cmbMove = InputAction.create(
        "Move",
        InputEventIds.CMB_MOVE.ordinal(),
        InputControls.create(
                Collections.emptyList(),
                Collections.singletonList(InputControls.MOUSE_RIGHT_CLICK)
        )
);

C#

var cmbMove = PlayInputAction.Create(
    "Move",
    (int)InputEventIds.CmbMove,
    PlayInputControls.Create(
        null,
        new[]
        {
            PlayMouseAction.MouseRightClick
        }
    )
);

「移動」動作與按一下滑鼠右鍵動作繫結的輸入項目疊加層螢幕截圖。

按鍵組合的指定方式是將多個按鍵程式碼傳送至您的 InputAction。在這個示例中,空白 + Shift 鍵會對應至快跑動作,即使將空白鍵對應至跳躍時,也能正常運作。

Kotlin

val cmbDash = InputAction.create(
    "Dash",
    InputEventIds.CMB_DASH.id,
    InputControls.create(
        listOf(KeyEvent.KEYCODE_SPACE, KeyEvent.KEYCODE_SHIFT_LEFT),
        emptyList()
    )
)

Java

InputAction cmbDash = InputAction.create(
        "Dash",
        InputEventIds.CMB_DASH.ordinal(),
        InputControls.create(
                Arrays.asList(KeyEvent.KEYCODE_SHIFT_LEFT, KeyEvent.KEYCODE_SPACE),
                Collections.emptyList()
        )
);

C#

var cmbDash = PlayInputAction.Create(
    "Dash",
    (int)InputEventIds.CmbDash,
    PlayInputControls.Create(
        new[]
        {
            AndroidKeyCode.KEYCODE_SPACE, AndroidKeyCode.KEYCODE_SHIFT_LEFT
        }, null
    )
);

Shift + 空白鍵與衝刺動作繫結的輸入項目疊加層螢幕截圖。

Input SDK 可讓您結合滑鼠和按鍵按鈕,用於單一指令。這個範例表示,同時按下 shift 鍵並按一下滑鼠右鍵,即可在這款遊戲中增加路線控點:

Kotlin

val cmbWaypoint = InputAction.create(
    "Add Waypoint",
    InputEventIds.CMB_WAYPOINT.id,
    InputControls.create(
        listOf(KeyEvent.KEYCODE_SHIFT_LEFT),
        listOf(InputControls.MOUSE_RIGHT_CLICK)
    )
)

Java

InputAction cmbWaypoint = InputAction.create(
        "Add Waypoint",
        InputEventIds.CMB_WAYPOINT.ordinal(),
        InputControls.create(
                Collections.singletonList(KeyEvent.KEYCODE_SHIFT_LEFT),
                Collections.singletonList(InputControls.MOUSE_RIGHT_CLICK)
        )
);

C#

var cmbWaypoint = PlayInputAction.Create(
    "Add Waypoint",
    (int)InputEventIds.CmbWaypoint,
    PlayInputControls.Create(
        new[]
        {
            AndroidKeyCode.KEYCODE_SHIFT_LEFT
        },
        new[]
        {
            PlayMouseAction.MouseRightClick
        }
    )
);

「新增路線控點」動作與 Shift + 按一下滑鼠右鍵動作繫結的輸入項目疊加層螢幕截圖。

本節將說明在程式碼範例中呼叫的方法:

Kotlin

InputAction.create 的參數如下:

  • actionLabel 是 UI 中顯示的字串,代表這項動作。 系統不會為您執行本地化作業,因此您可以選擇先執行任何本地化作業。
  • uniqueId 為整數 ID,用於識別這項動作。每個動作都必須有一致的不重複 ID,因此這個範例中使用列舉的方式。詳情請參閱追蹤按鍵 ID
  • inputControls 會定義此動作使用的輸入控制項。這類控制項會對應到使用者介面中的一致字符。

InputControls.create 會建立與動作相關聯的輸入項目。參數說明如下:

  • keycodes 這個整數清單代表與動作相關聯的鍵盤輸入項目,相關定義位於 KeyEvent 類別中。
  • mouseActions 這個整數清單代表與這個動作相關聯的滑鼠輸入項目,相關定義就位於 InputControls 中。

Java

InputAction.create 的參數如下:

  • actionLabel 是 UI 中顯示的字串,代表這項動作。 系統不會為您執行本地化作業,因此您可以選擇先執行任何本地化作業。
  • uniqueId 為整數 ID,用於識別這項動作。每個動作都必須有一致的不重複 ID,因此這個範例中使用列舉的方式。詳情請參閱追蹤按鍵 ID
  • inputControls 會定義此動作使用的輸入控制項。這類控制項會對應到使用者介面中的一致字符。

InputControls.create 會建立與動作相關聯的輸入項目。參數說明如下:

  • keycodes 這個整數清單代表與動作相關聯的鍵盤輸入項目,相關定義位於 KeyEvent 類別中。
  • mouseActions 這個整數清單代表與這個動作相關聯的滑鼠輸入項目,相關定義就位於 InputControls 中。

C#

InputAction 包含下列欄位:

  • ActionLabel 是 UI 中顯示的字串,代表這項動作。 系統不會為您執行本地化作業,因此您可以選擇先執行任何本地化作業。
  • UniqueId 為整數 ID,用於識別這項動作。每個動作都必須有一致的不重複 ID,因此這個示例中使用列舉的方式。請參閱「追蹤金鑰 ID」一文。
  • InputControls 會定義此動作使用的輸入控制項。這類控制項會對應到使用者介面中的一致字符。

InputControls 代表與動作相關聯的輸入項目,具有以下欄位:

  • AndroidKeycodes 這個整數清單代表與動作相關聯的鍵盤輸入項目,相關定義位於 AndroidKeycode 類別中。
  • MouseActions 是 MouseAction 值清單,代表與這項動作相關聯的滑鼠輸入。

定義輸入項目群組

InputGroup 是一組類似的 InputAction 物件。例如:

  • 您可以針對導覽選單和遊戲中的移動方式指定不同的輸入項目組合。
  • 您可以針對遊戲中的移動模式 (例如開車或步行) 指定不同的輸入項目組合。
  • 您可以針對遊戲的目前狀態指定不同的輸入項目組合,例如瀏覽整個世界或前往個別關卡。

如果將輸入項目分成多個群組,可讓玩家更輕鬆地找出目前情境適用的按鍵繫結。

Kotlin

val movementInputGroup = InputGroup.create(
    "Basic Movement",
    listOf(jumpInputAction, leftInputAction, rightInputAction, useInputAction)
)

Java

InputGroup movementInputGroup = InputGroup.create(
        "Basic Movement",
        Arrays.asList(jumpInputAction, leftInputAction, rightInputAction, useInputAction)
);

C#

var movementInputGroup = PlayInputGroup.Create(
    "Basic Movement",
    new[]
    {
        jumpInputAction, leftInputAction, rightInputAction, useInputAction
    }
);

本節將說明程式碼示例中使用的方法呼叫:

Kotlin

InputGroup.create 的參數如下:

  • groupLabel 是 UI 中顯示的字串,可按照特定邏輯為一組動作分組。系統不會針對這個字串為您執行本地化作業。
  • inputActions 是您在上一個步驟中定義的 InputAction 物件清單。這些動作都會顯示於這個群組的標題下方。

Java

InputGroup.create 的參數如下:

  • groupLabel 是 UI 中顯示的字串,可按照特定邏輯為一組動作分組。系統不會針對這個字串為您執行本地化作業。
  • inputActions 是您在上一個步驟中定義的 InputAction 物件清單。這些動作都會顯示於這個群組的標題下方。

C#

InputGroup 包含下列欄位:

  • GroupLabel 是 UI 中顯示的字串,可按照特定邏輯為一組動作分組。系統不會針對這個字串為您執行本地化作業。
  • InputActions 是您在上一個步驟中定義的 InputAction 物件清單。這些動作都會顯示於這個群組的標題下方。

建立輸入項目對應

InputMap 是遊戲中所有可用 InputGroup 物件的集合,因此是玩家可執行的所有 InputAction 物件。

在以下示例中,MovementInputGroup 物件會與 MouseSettings 物件分組在一起。MouseSettings 物件代表可以調整滑鼠靈敏度,且滑鼠會在 Y 軸上反轉:

Kotlin

return InputMap.create(
    listOf(movementInputGroup, specialInputGroup),
    MouseSettings.create(true, true)
)

Java

return InputMap.create(
        Arrays.asList(movementInputGroup, specialInputGroup),
        MouseSettings.create(true, true)
);

C#

return PlayInputMap.Create(
    new[]
    {
        movementInputGroup, specialInputGroup, combinationInputGroup
    },
    PlayMouseSettings.Create(true, false)
);

提交輸入項目對應

針對傳回有效 InputMap 的遊戲撰寫 InputMapProvider 之後,必須透過 Input SDK 註冊。如果遊戲的輸入項目不會變更,則在遊戲生命週期中,這項操作只需要執行一次,因為 InputMapProvider 不會受到 Android 生命週期事件的影響。

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val inputMappingClient = Input.getInputMappingClient(this)
    inputMappingClient.setInputMappingProvider(MyInputMapProvider())
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    InputMappingClient inputMappingClient = Input.getInputMappingClient(this);
    inputMappingClient.setInputMappingProvider(new MyInputMapProvider());
}

C#

void Start()
{
    _inputMappingProvider = new MyInputMappingProvider();
    PlayInput.GetInputMappingClient().SetInputMappingProvider(_inputMappingProvider);
}

遊戲完成時,您應該取消註冊輸入項目對應關係提供者,不過就算沒有這樣做,SDK 功能也足以避免資源外洩。

Kotlin

override fun onDestroy() {
    val inputMappingClient = Input.getInputMappingClient(this)
    inputMappingClient.clearInputMappingProvider()

    super.onDestroy()
}

Java

@Override
protected void onDestroy() {
    InputMappingClient inputMappingClient = Input.getInputMappingClient(this);
    inputMappingClient.clearInputMappingProvider();

    super.onDestroy();
}

C#

private void OnDestroy()
{
    PlayInput.GetInputMappingClient().ClearInputMappingProvider();
}

追蹤按鍵 ID

您必須為自己定義的每個 InputAction 追蹤專屬 ID。以下列舉項目會針對這個主題中的所有範例追蹤專屬 ID。由於這些 ID 是用於追蹤按鍵變更,因此請勿使用本地化動作名稱的雜湊。

Kotlin

enum class InputEventIds(val id: Int) {
    JUMP(0),
    LEFT(1),
    RIGHT(2),
    USE(3),
    SPECIAL_JUMP(4),
    SPECIAL_DUCK(5),
}

Java

public enum InputEventIds {
    JUMP,
    LEFT,
    RIGHT,
    USE,
    SPECIAL_JUMP,
    SPECIAL_DUCK
}

C#

public enum InputEventIds
{
    JUMP,
    LEFT,
    RIGHT,
    USE,
    SPECIAL_JUMP,
    SPECIAL_DUCK
}

測試

有兩種方式可以測試 Input SDK 是否已正確實作。其中一種方式是在 Google Play 遊戲 UI 中開啟,以查看玩家會看到的畫面,另一種方式是在 adb shell 中開啟,用於自動執行測試和驗證。

使用者介面

如要在 Google Play 遊戲 UI 中進行測試,請按下 Shift+Tab 鍵,開啟遊戲資訊主頁。按一下資訊主頁中的「Controls」(控制項),查看目前繫結的控制項清單。

說明上述流程的圖片。按下 Shift+Tab 鍵可開啟遊戲資訊主頁,接著按一下「Controls」即可開啟控制項疊加層。此疊加層顯示一個名為「Basic Movement」的群組,其中包含「Jump」、「Left」和「Right」。每個控制項都會顯示用來執行該動作的控制鍵。舉例來說,「Jump」下方會顯示「Key W + Key Up」,右側則顯示「W」鍵和「Up」鍵的大型圖片。還有一個部分叫做「Special Input」(特殊輸入項目),上面寫著「Duck」(躲避)。

指令列

您也可以在指令列透過 adb 驗證輸入項目,這有助於自動測試功能。

如要取得目前的輸入項目對應,請使用以下 adb shell 指令 (將 MY.PACKAGE.NAME 替換成您的遊戲名稱):

adb shell dumpsys input_mapping_service --get MY.PACKAGE.NAME

成功註冊 InputMap 後,就會看到如下的輸出內容:

Getting input map for com.example.inputsample...
Successfully received the following inputmap:
# com.google.android.libraries.play.games.InputMap@d73526e1
input_groups {
  group_label: "Basic Movement"
  input_actions {
    action_label: "Jump"
    input_controls {
      keycodes: 51
      keycodes: 19
    }
    unique_id: 0
  }
  input_actions {
    action_label: "Left"
    input_controls {
      keycodes: 29
      keycodes: 21
    }
    unique_id: 1
  }
  input_actions {
    action_label: "Right"
    input_controls {
      keycodes: 32
      keycodes: 22
    }
    unique_id: 2
  }
  input_actions {
    action_label: "Use"
    input_controls {
      keycodes: 33
      keycodes: 66
      mouse_actions: MOUSE_LEFT_CLICK
      mouse_actions_value: 0
    }
    unique_id: 3
  }
}
input_groups {
  group_label: "Special Input"
  input_actions {
    action_label: "Jump"
    input_controls {
      keycodes: 51
      keycodes: 19
      keycodes: 62
      mouse_actions: MOUSE_LEFT_CLICK
      mouse_actions_value: 0
    }
    unique_id: 4
  }
  input_actions {
    action_label: "Duck"
    input_controls {
      keycodes: 47
      keycodes: 20
      keycodes: 113
      mouse_actions: MOUSE_RIGHT_CLICK
      mouse_actions_value: 1
    }
    unique_id: 5
  }
}
mouse_settings {
  allow_mouse_sensitivity_adjustment: true
  invert_mouse_movement: true
}

同步處理按鍵繫結變更

很多遊戲都能讓玩家自訂按鍵繫結。因此,您應該確保在 InputMapProvider 中傳回的資料符合玩家目前的設定。如有需要,只要玩家完成輸入項目配置,您就能使用最新的輸入項目對應關係安全地呼叫 setInputMappingProvider

本地化

Input SDK 不會使用 Android 的本地化系統。因此,您必須在提交 InputMap 時提供本地化字串。 不過,您也可以使用遊戲引擎的本地化系統。

後續步驟

將 Input SDK 整合到遊戲後,您就可以繼續完成剩餘的 Google Play 遊戲規定。詳情請參閱開始使用 Google Play 遊戲