Google Play 游戏目前处于 Beta 版公开测试阶段。

输入 SDK 使用入门

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

本主题介绍如何在支持 Google Play 游戏的游戏中设置和显示输入 SDK 叠加层。这些任务包括将该 SDK 添加到游戏中并生成输入映射,该映射包含游戏操作到用户输入的分配关系。对于支持按键组合更改的游戏,您还必须跟踪更改并将更改与 SDK 同步

准备工作

在将输入 SDK 添加到游戏之前,必须先添加键盘和鼠标支持。

添加 SDK

通过将依赖项添加到模块级 build.gradle 文件(可能会位于 app 目录中),获取适用于 Java 或 Kotlin 的输入 SDK:

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

适用于 Unity 的输入 SDK 尚无法下载。它将以 unitypackagetgz 的形式提供给 Unity 开发者。

请记得申请参与,以便抢先体验该新 SDK。

生成输入映射

输入映射表示要在输入 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")
    }
}

接下来的部分将介绍如何创建要从 InputMappingProvider 返回的 InputMap

定义输入操作

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 传递多个按键代码来指定按键组合。在本例中,Space+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+Space 已绑定到短跑操作的叠加层屏幕截图。

借助输入 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 是界面中显示的用于表示此操作的字符串。系统不会为您进行本地化,如需进行任何本地化,需要由您预先完成。
  • uniqueId 是一个用于标识此操作的整数 ID。每项操作都必须具有一致的唯一标识符,因此,此示例中使用了枚举。如需了解详情,请参阅跟踪按键 ID
  • inputControls 用于定义操作使用的输入控件。这些控件在界面中将映射为一致的字形。

InputControls.create 会创建与操作关联的输入。包含以下参数:

  • keycodes 是一个整数列表,表示与操作相关联的键盘输入。这些键盘输入在 KeyEvent 类中定义。
  • mouseActions 是一个整数列表,表示与操作相关联的鼠标输入。这些鼠标输入在 InputControls 本身中定义。

Java

InputAction.create 具有以下参数:

  • actionLabel 是界面中显示的用于表示此操作的字符串。系统不会为您进行本地化,如需进行任何本地化,需要由您预先完成。
  • uniqueId 是一个用于标识此操作的整数 ID。每项操作都必须具有一致的唯一标识符,因此,此示例中使用了枚举。如需了解详情,请参阅跟踪按键 ID
  • inputControls 用于定义操作使用的输入控件。这些控件在界面中将映射为一致的字形。

InputControls.create 会创建与操作关联的输入。包含以下参数:

  • keycodes 是一个整数列表,表示与操作相关联的键盘输入。这些键盘输入在 KeyEvent 类中定义。
  • mouseActions 是一个整数列表,表示与此操作相关联的鼠标输入。这些鼠标输入在 InputControls 本身中定义。

C#

InputAction 具有以下字段:

  • ActionLabel 是界面中显示的用于表示此操作的字符串。系统不会为您进行本地化,如需进行任何本地化,需要由您预先完成。
  • UniqueId 是一个用于标识此操作的整数 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 是要在界面中显示的字符串,可用于对一组操作进行逻辑分组。系统不会为您本地化此字符串。
  • inputActions 是您在上一步中定义的 InputAction 对象的列表。所有这些操作都会直观显示于此组的标题下。

Java

InputGroup.create 具有以下参数:

  • groupLabel 是要在界面中显示的字符串,可用于对一组操作进行逻辑分组。系统不会为您本地化此字符串。
  • inputActions 是您在上一步中定义的 InputAction 对象的列表。所有这些操作都会直观显示于此组的标题下。

C#

InputGroup 具有以下字段:

  • GroupLabel 是要在界面中显示的字符串,可用于对一组操作进行逻辑分组。系统不会为您本地化此字符串。
  • 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)
);

提交输入映射

为游戏编写返回有效 InputMapInputMapProvider 后,必须向输入 SDK 注册该 InputMapProvider。如果游戏输入永远不会更改,则在游戏的生命周期内将只需要执行一次此操作,因为 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
}

测试

您可以通过以下两种方式测试是否已正确实现输入 SDK:在 Google Play 游戏界面中打开该 SDK,以查看玩家会看到的内容,或者在 adb shell 中打开该 SDK 以进行自动测试和验证。

界面

如需在 Google Play 游戏界面中进行测试,请按 Shift+Tab 打开游戏信息中心。在信息中心内,点击 Controls(控件)以查看当前绑定的控件列表。

展示上述流程的图片。按 Shift+Tab 会打开游戏信息中心。然后,点击“控件”会打开控件叠加层。此叠加层会显示一个名为“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

本地化

输入 SDK 不会使用 Android 的本地化系统。因此,在提交 InputMap 时,必须提供已本地化的字符串。不过,您也可以通过这种方式使用游戏引擎的本地化系统。

后续操作

将输入 SDK 集成到游戏中后,您可以继续满足剩下的 Google Play 游戏要求。如需了解详情,请参阅 Google Play 游戏使用入门