本主题介绍如何在支持 Google Play 游戏的游戏中设置和显示输入 SDK 叠加层。这些任务包括将该 SDK 添加到游戏中并生成输入映射,该映射包含游戏操作到用户输入的分配关系。对于支持按键组合更改的游戏,您还必须跟踪更改并将更改与 SDK 同步。
准备工作
在将输入 SDK 添加到游戏之前,必须先添加键盘和鼠标支持。
添加 SDK
输入 SDK 暂时无法下载。它将作为 Java 和 Kotlin 项目的 Maven 依赖项提供,以及以 unitypackage
和 tgz
的形式向 Unity 开发者提供。
请记得申请参与,以便抢先体验该新 SDK。
生成输入映射
输入映射表示要在输入 SDK 叠加层中显示的游戏操作到用户输入的分配关系。如需生成输入映射,您必须构建 InputMap
,然后通过 InputMappingProvider
返回它。
以下是 InputMappingProvider
的框架示例:
Kotlin
class MyInputMapProvider : InputMappingProvider() { override fun onProvideInputMap(): InputMap { TODO("Not yet implemented") } }
Java
public class MyInputMapProvider extends InputMappingProvider { @NonNull @Override public InputMap onProvideInputMap() { // TODO: return an InputMap } }
C#
private class MyInputMappingProvider : InputMappingProvider { public InputMap 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 = new InputAction { ActionLabel = "Jump", UniqueId = (int)InputEventIds.Jump, InputControls = new InputControls { AndroidKeycodes = new[] { AndroidKeyCode.KEYCODE_SPACE } } };
操作也可以表示鼠标输入。此示例将
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 = new InputAction { ActionLabel = "Move", UniqueId = (int)InputEventIds.CmbMove, InputControls = new InputControls { MouseActions = new[] { MouseAction.MouseRightClick } } };
您可以通过向 InputAction
传递多个按键代码来指定按键组合。在本例中,
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 = new InputAction { ActionLabel = "Dash", UniqueId = (int)InputEventIds.CmbDash, InputControls = new InputControls { AndroidKeycodes = new[] { AndroidKeyCode.KEYCODE_SPACE, AndroidKeyCode.KEYCODE_SHIFT_LEFT } } };
借助输入 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 = new InputAction { ActionLabel = "Add Waypoint", UniqueId = (int)InputEventIds.CmbWaypoint, InputControls = new InputControls { AndroidKeycodes = new[] { AndroidKeyCode.KEYCODE_SHIFT_LEFT }, MouseActions = new[] { MouseAction.MouseRightClick } } };
本部分介绍代码示例中调用的方法:
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 = new InputGroup { GroupLabel = "Basic Movement", InputActions = new List<InputAction> { 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 new InputMap { InputGroups = new List<InputGroup> {movementInputGroup, specialInputGroup}, MouseSettings = new MouseSettings { AllowMouseSensitivityAdjustment = true, InvertMouseMovement = true } }
提交输入映射
为游戏编写返回有效 InputMap
的 InputMapProvider
后,必须向输入 SDK 注册该 InputMapProvider。如果游戏输入永远不会更改,则在游戏的生命周期内将只需要执行一次此操作,因为 InputMapProvider
不受 Android 生命周期事件的影响。
Kotlin
private val myInputMapProvider by lazy { MyInputMapProvider() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val inputMappingClient = Input.getInputMappingClient(this) inputMappingClient.registerInputMappingProvider(myInputMapProvider) }
Java
private final MyInputMapProvider myInputMapProvider = new MyInputMapProvider(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); InputMappingClient inputMappingClient = Input.getInputMappingClient(this); inputMappingClient.registerInputMappingProvider(myInputMapProvider); }
C#
public void Start() { InputMappingClient inputMappingClient = Input.GetInputMappingClient(); inputMappingClient.registerInputMappingProvider(myInputMapProvider); }
您应当在游戏结束时取消注册输入映射提供程序,不过 SDK 非常智能,能够在您未取消注册的情况下避免泄露资源。
Kotlin
override fun onDestroy() { val inputMappingClient = Input.getInputMappingClient(this) inputMappingClient.unregisterInputMappingProvider(myInputMapProvider) super.onDestroy() }
Java
@Override protected void onDestroy() { InputMappingClient inputMappingClient = Input.getInputMappingClient(this); inputMappingClient.unregisterInputMappingProvider(myInputMapProvider); super.onDestroy(); }
C#
public void OnDestroy() { InputMappingClient inputMappingClient = Input.GetInputMappingClient(); inputMappingClient.unregisterInputMappingProvider(myInputMapProvider); }
跟踪按键 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(控件)以查看当前绑定的控件列表。
命令行
您也可以使用命令行通过 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
中返回的数据符合玩家的当前设置。为稳妥起见,您可以在每次玩家完成输入模式更改后,视需要使用最新的输入映射调用 registerInputMappingProvider
。
本地化
输入 SDK 不会使用 Android 的本地化系统。因此,在提交 InputMap
时,必须提供已本地化的字符串。不过,您也可以通过这种方式使用游戏引擎的本地化系统。
后续操作
将输入 SDK 集成到游戏中后,您可以继续满足剩下的 Google Play 游戏要求。如需了解详情,请参阅 Google Play 游戏使用入门。