将适用于 Unity 的输入 SDK 升级到版本 1.1

本指南介绍了如何将游戏中适用于 Unity 的输入 SDK 从 1.0 升级到 1.1。如需查看适用于 Java 和 Kotlin 的说明,请点击此处

版本说明

Google Play 游戏电脑版支持根据游戏使用输入 SDK 提供的按键绑定来重新映射键盘控制方式。

用户可以通过执行以下步骤来访问该功能:打开叠加层,选择控制方式,然后点击要重新映射的操作。

Google Play 游戏电脑版会将用户重新映射的每个输入映射到游戏的默认输入。这样,游戏就不必留意玩家所做的重新映射。如果您需要知道游戏内操作的新输入(例如在游戏中显示键盘控制方式),可以选择注册一个回调,以便收到重新映射事件通知。

Google Play 游戏电脑版会将用户重新映射的控制方式存储在本地,以便让这类控制方式在不同的游戏会话之间保持不变。这类设置存储在本地,因此不会影响移动体验,并且会在 Google Play 游戏电脑版卸载后删除。此外,该类设置不会跨多台 PC 设备保存。

您无需升级输入 SDK 即可在游戏中启用按键重新映射功能,但如果检测到不受支持的配置,系统将会对游戏停用重新映射功能。

如果您想控制输入重新映射体验,或者对游戏停用了重新映射功能,请按以下步骤操作:

  • 升级到输入 SDK 1.1.1-beta
  • 更新所有按键绑定,避免出现不受支持的配置
  • 更新 InputMap,将重新映射功能设为启用。

如果您想选择对游戏停用重新映射功能,同时仍显示按键绑定的只读版本,请按以下步骤操作:

  • 升级到输入 SDK 1.1.1-beta
  • 更新 InputMap,将重新映射功能设为停用。

您可以将输入 SDK 的版本升级到 1.1.1-beta,以便使用 InputContexts 为游戏的不同场景定义控件、添加回调以监听重新映射事件、定义一组用户无法重新映射到的预留按键,以及按 InputActionInputGroupInputMap 停用重新映射功能,从而充分利用 Google Play 游戏电脑版中的高级重新映射功能。

升级时,请考虑以下例外情况:

不受支持的配置

如果不符合以下条件,输入重新映射就会被停用:

  • 使用多个按键的 InputAction 必须由辅助键和非辅助键组成,例如:Shift 键 + A 就符合条件,但 A + BCtrl 键 + Alt 键以及 Shift 键 + A + Tab 键不符合条件。

  • 两个或更多个 InputActionInputGroup 对象不能共用相同的唯一 ID。

InputContext 简介

通过使用 InputContext,游戏中的不同操作可以使用相同的按键,且不会发生冲突。这样一来,如果游戏过程中使用空格键进行跳跃,且确认菜单选择也是使用空格键,那么玩家可以按不同的场景分别进行重新映射,将空格键重新映射为菜单中的确认键,并将空格键重新映射为游戏过程中的向上键

以下序列图显示了 setInputContext() API 在运行时的运作方式:

展示重新映射按键时输入 SDK 运作流程的示意图。

升级

采用输入 SDK 旧版实现的游戏仍然支持基本的重新映射,除非它们使用的是不受支持的配置。如果您的游戏使用的是旧版输入 SDK,不妨参阅从 0.0.4 升级到 1.0.0-beta 的指南

升级到 1.1.1-beta 后,便可使用以下新功能:

  • 触发上下文更改。
  • 接收按键映射事件的通知。
  • 按操作、组、上下文或映射停用重新映射功能。

安装

您可以使用 Unity 插件 v1.1.1-beta。您需要删除游戏中安装的所有旧版输入 SDK,然后升级到现行版本。

如需在游戏中添加输入 SDK v1.1.1-beta,请参阅添加 SDK

定义静态字段

对于版本 1.1.1-beta,最好将 InputActionsInputGroupsInputContextsInputMap 定义为 InputMappingProvider 类的静态字段,因为这些字段将可以从应用的其他部分访问:

#if PLAY_GAMES_PC
using Java.Lang;
using Java.Util;
using Google.Android.Libraries.Play.Games.Inputmapping;
using Google.Android.Libraries.Play.Games.Inputmapping.Datamodel;

public class InputSDKMappingProvider : InputMappingProviderCallbackHelper
{
    public static readonly string INPUT_MAP_VERSION = "1.0.0";

    private static readonly InputAction driveInputAction =
            InputAction.Create(...);
    private static readonly InputGroup roadInputGroup = InputGroup.Create(...);
    public static readonly InputContext roadControlsContext =
            InputContext.Create(...);
    public static readonly InputMap inputMap = InputMap.Create(...);

    public override InputMap OnProvideInputMap()
    {
        return inputMap;
    }
}
#endif

更新 InputAction

输入 SDK 1.0.0-betaInputAction.create() 方法已废弃。InputAction 具有版本标识符,且可以标记为可重新映射或不可重新映射。默认情况下,使用输入 SDK 1.0.0-beta create() 方法定义的 InputAction 可重新映射,但缺少版本控制信息:

输入 SDK 1.0.0-beta 中的 InputAction

var driveAction = PlayInputAction.Create(
    "Drive",
    (long)InputEventIds.DRIVE,
    PlayInputControls.Create(
        new[] { AndroidKeyCode.KEYCODE_SPACE },
        new List<PlayMouseAction>()
    )
);

输入 SDK 1.1.1-beta 中的 InputAction

private static readonly InputAction driveInputAction = InputAction.Create(
    "Drive",
    (long)InputEventIds.DRIVE,
    InputControls.Create(
        new[] { new Integer(AndroidKeyCode.KEYCODE_SPACE) }.ToJavaList(),
        new ArrayList<Integer>()),
    InputEnums.REMAP_OPTION_ENABLED
);

输入 SDK 1.1.1-beta 中的 InputAction(含有版本字符串)

private static readonly InputAction driveInputAction = InputAction.Create(
    "Drive",
    InputControls.Create(
        new[] { new Integer(AndroidKeyCode.KEYCODE_SPACE) }.ToJavaList(),
        new ArrayList<Integer>()),
    InputIdentifier.Create(
        INPUT_MAP_VERSION, (long)InputEventIds.DRIVE),
    InputEnums.REMAP_OPTION_ENABLED
);

如需详细了解如何对按键绑定进行版本控制,请参阅跟踪按键 ID

更新 InputGroup

在输入 SDK 1.1.1-beta 中,您需要对每个 InputGroup 进行唯一标识。每个 InputAction 都属于一个 InputGroup(即相关操作的集合)。这能让用户在游戏过程中更容易发现控件,并且能够更丝滑地切换控件。在一个 InputContext 中,InputAction 必须具有与其中所有其他操作不同的唯一标识符;同样地,InputGroup 必须具有与现有的其他组不同的唯一 ID。

在本部分的示例中,游戏有两个 InputContext 对象,分别代表主菜单和游戏内容。系统会使用如下枚举对这些上下文中每个 InputGroup 所对应的 ID 进行跟踪:

public enum InputGroupsIds
{
    // Main menu scene
    BASIC_NAVIGATION, // WASD, Enter, Backspace
    MENU_ACTIONS, // C: chat, Space: quick game, S: store
    // Gameplay scene
    BASIC_MOVEMENT, // WASD, space: jump, Shift: run
    MOUSE_ACTIONS, // Left click: shoot, Right click: aim
    EMOJIS, // Emojis with keys 1,2,3,4 and 5
    GAME_ACTIONS, // M: map, P: pause, R: reload
}

InputAction 一样,输入 SDK 1.0.0-betaInputGroup.create() 方法已废弃。您必须使用版本标识符以及用于指明组中的 InputAction 对象是否可重新映射的布尔值来更新游戏中的 InputGroup。使用已废弃的输入 SDK 1.0.0-beta create() 方法创建的组可重新映射,其 ID 为 0 且版本 ID 为空字符串 (""):

输入 SDK 1.0.0-beta 中的 InputGroup

var gameInputGroup = PlayInputGroup.Create(
    "Road controls",
    new List<PlayInputAction>
    {
        driveAction,
        turboAction,
        openGarageAction,
        openPgsAction,
        openStoreAction
    }
);

输入 SDK 1.1.1-beta 中的 InputGroup

private static readonly InputGroup roadInputGroup = InputGroup.Create(
    "Road controls",
    new[]
    {
        driveInputAction,
        turboInputAction,
        openGarageInputAction,
        openPgsInputAction,
        openStoreInputAction,
    }.ToJavaList(),
    (long)InputGroupsIds.ROAD_CONTROLS,
    // All input actions of this group will be remappable unless specified
    // the contrary by the individual input actions.
    InputEnums.REMAP_OPTION_ENABLED
);

输入 SDK 1.1.1-beta 中的 InputGroup(含有版本字符串)

private static readonly InputGroup roadInputGroup = InputGroup.Create(
    "Road controls",
    new[]
    {
        driveInputAction,
        turboInputAction,
        openGarageInputAction,
        openPgsInputAction,
        openStoreInputAction,
    }.ToJavaList(),
    InputIdentifier.Create(
        INPUT_MAP_VERSION, (long)InputGroupsIds.ROAD_CONTROLS),
    // All input actions of this group will be remappable unless specified
    // the contrary by the individual input actions.
    InputEnums.REMAP_OPTION_ENABLED
);

如需详细了解如何对按键绑定进行版本控制,请参阅跟踪按键 ID

更新 InputMap

输入 SDK 1.0.0-betaInputMap.create() 方法已废弃。请更新 InputMap 以指定版本标识符、选择彻底停用重新映射功能,或者为游戏指定您不想让用户用于重新映射的预留按键的列表。默认情况下,使用输入 SDK 1.0.0-beta create() 方法定义的每个 InputMap 都可以重新映射,通过 ID 0 进行标识,并且没有任何预留按键。

输入 SDK 1.0.0-beta 中的 InputMap

var gameInputMap = PlayInputMap.Create(
    new List<PlayInputGroup>
    {
        gameInputGroup,
        menuInputGroup
    },
    PlayMouseSettings.Create(false, false)
);

输入 SDK 1.1.1-beta 中的 InputMap


public static readonly string INPUT_MAP_VERSION = "1.0.0";
public static readonly long INPUT_MAP_ID = 0;

public static readonly InputMap inputMap = InputMap.Create(
    new[] { roadInputGroup, menuInputGroup }.ToJavaList(),
    MouseSettings.Create(false, false),
    InputIdentifier.Create(INPUT_MAP_VERSION, INPUT_MAP_ID),
    // Use ESC as reserved key
    InputEnums.REMAP_OPTION_ENABLED,
    new[]
    {
        InputControls.Create(new[]
        {
            new Integer(AndroidKeyCode.KEYCODE_ESCAPE)
        }.ToJavaList(),
        new ArrayList<Integer>())
    }.ToJavaList()
);

后续课程

继续升级到 1.1.1-beta,具体方法是:使用 InputContexts 为不同的场景分配不同的控件,或者使用 InputRemappingListeners 获取有关重新映射事件的通知来更新游戏界面。

在更新按键绑定时,请查看按键绑定设计最佳实践,并考虑重新映射功能的限制局限性