# 使用 Lobby

> Use Cloud Code and Lobby service together to trigger server-side actions when players join lobbies.

您可以将 Lobby 与 Cloud Code 结合使用来定义游戏中的常见触发器。假设游戏大厅已准备好开始匹配。您可以触发以下脚本来响应游戏大厅准备就绪状态。此示例还与 [Remote Config](/remote-config.md) 集成。

在按照此示例操作之前，请通过 [Unity Dashboard](https://cloud.unity.com) 启用 Lobby 和 Cloud Code，然后按照步骤安装所需的 SDK。使用服务身份验证在项目中[创建一个大厅](/lobby/create-a-lobby.md)，并记下其 [ID](https://cloud-code-sdk-documentation.cloud.unity3d.com/lobby/v1.0/lobby)。您可以通过 Cloud Code 执行此操作（查看 [Unity Lobby](../how-to-guides/unity-services-integration#using-the-unity-lobby-sdk) 的示例）。

以下示例为脚本提供了两个参数：用于创建大厅的服务 ID 以及大厅 ID。我们获取大厅后，通过对大厅元数据进行一些更改来更新大厅。这些更改如下：

* 锁定大厅，使新玩家无法再加入大厅。
* 使用大厅的玩家 ID 为游戏构建随机的“玩家顺序”。
* 使用 Remote Config 中定义的 `LOBBY_CURRENT_MAPS` 配置来随机选择一张游戏地图。该脚本返回一个指示成功或失败结果的基本布尔值。

###### JavaScript##javascript

```js
const _ = require("lodash-4.17");
const { LobbyApi, DataObjectVisibilityEnum } = require("@unity-services/lobby-1.2");
const { SettingsApi } = require("@unity-services/remote-config-1.1");

module.exports = async ({params,context,logger}) => {
    const { serviceId, lobbyId } = params;
    const { projectId, environmentId, playerId } = context;
    const lobbyApi = new LobbyApi(context);
    const remoteConfig = new SettingsApi(context);

    try {
        const {data: lobby} = await lobbyApi.getLobby(lobbyId, serviceId);
        return setUpGame(remoteConfig, projectId, environmentId, serviceId, lobbyApi, logger, lobby);
    } catch (err) {
       logger.error(`Failed to set up lobby: ${err.response.data.detail}`);
       return false;
    }

};

// Updates a lobby to set up for the start of a game, including reading a value from Remote Config to randomly assign to the lobby.
async function setUpGame(remoteConfig, projectId, environmentId, serviceId, lobbyApi, logger, lobby) {
    let playerIds = [];
    for (let i = 0; i < lobby.players.length; i++) {
        playerIds.push(lobby.players[i].id);
    }

    // Generate a turn order for the game by shuffling the player IDs.
    _.shuffle(playerIds);

    // Load all of the maps that are currently configured as available in Remote Config and pick a random one for this game.
    let maps = getCurrentMapsFromRemoteConfig(remoteConfig, projectId, environmentId)
    if (maps == null) {
      throw "Maps loaded from Remote Config are null.";
    }
    let gameMap = _.sample(maps);

    try {
      const updateResponse = await lobbyApi.updateLobby(
          lobby.id,
          serviceId,
          null,
          {
              isLocked: true, // Lock the lobby so that new players cannot join.
              hostId: playerIds[0], // Transfer host ownership from the service to one of the players.
              data: {
                  "playerOrder": {
                      value: playerIds.toString(),
                      visibility: DataObjectVisibilityEnum.Member // Set the visibility of the player order so that only lobby members can access it.
                  },
                  "map": {
                      value: gameMap,
                      visibility: DataObjectVisibilityEnum.Public // Set the visibility of the game map so that anyone who views the lobby can access it.
                  }
              }
          }
      );

      return true;
    } catch (err) {
      throw err;
    }

    return lobbyUpdateSuccess;
}

// Loads the Remote Config JSON value for LOBBY_CURRENT_MAPS and returns the array of maps inside of it.
// If the JSON is invalid, the return value is null.
async function getCurrentMapsFromRemoteConfig(remoteConfig, projectId, environmentId) {
  const currentMapsId = 'LOBBY_CURRENT_MAPS';
  const remoteConfigResponse = await remoteConfig.assignSettingsGet(
    projectId,
    environmentId,
    'settings',
    [currentMapsId]
  );

  let mapsJSON = remoteConfigResponse?.data?.configs?.settings?.[currentMapsId];
  if (!mapsJSON || !mapsJSON.maps || mapsJSON.maps.length == 0) {
    return null;
  }

  return mapsJSON.maps;
}

// Uncomment the code below to enable the inline parameter definition
// - Requires Cloud Code JS dev environment setup with NodeJS (https://docs.unity3d.com/Packages/com.unity.services.cloudcode@latest/index.html?subfolder=/manual/Authoring/javascript_project.html)
//
// module.exports.params = {
//   serviceId: { type: "String", required: true },
//   lobbyId: { type: "String", required: true },
// };
```

> **Note:**
>
> **注意：** 如果您使用 Unity 编辑器来管理您的脚本，您可以取消注释脚本尾部的代码，以便声明所需的 `serviceId` 和 `lobbyId` 脚本内参数。要了解有关如何管理脚本内参数的更多信息，请参阅在 Unity 编辑器中[修改脚本参数](../../scripts/how-to-guides/write-scripts/unity-editor#modify-script-parameters)。

此处的 Remote Config JSON 结构简单，但您可以扩展此示例配置来实现对游戏的更精细控制。同样，除了游戏设置之外，您可能还需要考虑大量不同的 Cloud Code 触发器，例如：

* 在创建大厅时触发调整元数据值并清理字符串。
* 使用 Cloud Save 玩家数据过滤玩家的查询结果、批准/拒绝玩家加入大厅以及设置元数据。
* 使用 Economy 数据设置玩家或大厅元数据。
