如何为第三人称射击(TPS)多人游戏添加 matchmaking

关键洞察

关键洞察

关键洞察

Edgegap 的 配对系统 是一个完全管理的、无限自定义的配对系统,能够最优地将全球玩家分组——在开发您的第三人称射击多人游戏期间使用它是免费的。

它也是我们所知的唯一配对系统,具有基于延迟的配对规则,为您的游戏提供理想的在线多人体验,无论使用什么引擎(Unity、Unreal 等)或游戏服务(EOS、UGS、PlayFab、Heroic Labs Nakama、Braincloud 等)。

由于我们的配对系统是基于参数的,因此无需编写代码。因此,集成非常简单,如果需要,我们的 入门指南 将为您提供每一步的帮助。

当您的游戏上线时,由于我们的配对系统是完全管理的,您无需处理基础设施、错误、故障、可扩展性或数据库管理。我们为您处理这一切。将您的 DevOps 工作量减少到几乎为零。

如何在你的第三人称射击(TPS)多人游戏中集成匹配机制

-> 本文基于 匹配机制文档。如果你遇到问题或不一致之处,请确保参考 原始指南,因为它们通常会保持更新。

以下示例将帮助你测试核心 匹配机制 玩家流程,即:

  • 在共享的 托管集群 上创建匹配器实例,

  • 在你的匹配器 配置 中定义规则和设置,

  • 最后,测试玩家流程并通过我们的 API 管理 玩家票据

将我们的匹配器实现到你的游戏中有 五个步骤

  1. 第一步是 创建一个账户 并使用我们的 TPS 游戏示例。,你已经(在技术上)完成了一半!你只需在你的游戏中集成匹配器即可(见步骤 5)。

  2. 现在,你绝不能盲目遵循在互联网上找到的 JSON 示例,因此强烈建议将上述规则调整为适合你的游戏。第 2 步(“探索配置”)是我们的“阅读方式”,内容涉及每个 匹配机制 规则 函数的功能(“探索配置”)。

  3. 第 3 步(“查看实例详情”)涵盖你的个人特定匹配器,以确保其已经部署并与你的游戏设计一致。

  4. 步骤 4,如其名所示(“4. 测试票据 API”),是关于测试玩家的匹配请求是否被匹配器接收,称为 票据

  5. 步骤 5(“在你的游戏中集成匹配机制”)强调如何在你的引擎项目中集成匹配器。

如果你在故障排除方面遇到挑战,我们的深入 学习中心 提供了额外的故障排除提示。

1. 设置免费层

注册你的免费 Edgegap 账户,并导航到 匹配器仪表板页面

从那里,首先点击 创建匹配器 ,然后输入:

  • 你的匹配器名称——这纯粹是供你参考,例如 quickstart-dev

  • 然后,上传以下简单示例作为你 TPS 游戏的 JSON 配置:

{
  "version": "1.0.0",
  "max_deployment_retry_count": 3,
  "ticket_expiration_period": "5m",
  "ticket_removal_period": "1m",
  "profiles": {
    "casual-example": {
      "application": {
        "name": "my-game-server=>CHANGE-THIS-NAME-HERE",
        "version": "2024.01.30-16.23.00-UTC=>CHANGE-THIS-HERE "
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 25,
              "max_latency": 100
            }
          },
          "league_rank": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 1
            }
          },
          "selected_maps": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "selected_beacons": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "10": {
            "beacons": {
              "difference": 40,
              "max_latency": 150
            }
          },
          "30": {
            "beacons": {
              "difference": 50
            }
          },
          "60": {
            "league_rank": {
              "max_difference": 2
            }
          },
          "180": {
            "beacons": {
              "difference": 100,
              "max_latency": 500
            }
          }
        }
      }
    },
    "competitive-example": {
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 25,
              "max_latency": 100
            }
          },
          "league_rank": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 0
            }
          },
          "selected_maps": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "selected_beacons": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "beacons": {
              "difference": 40,
              "max_latency": 150
            }
          },
          "60": {
            "beacons": {
              "difference": 50
            }
          },
          "180": {
            "beacons": {
              "max_latency": 250
            }
          }
        }
      }
    },
    "challenger-example": {
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 25,
              "max_latency": 100
            }
          },
          "league_rank": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 0
            }
          },
          "selected_maps": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "selected_beacons": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "beacons": {
              "difference": 40,
              "max_latency": 150
            }
          },
          "180": {
            "beacons": {
              "difference": 50
            }
          },
          "240": {
            "beacons": {
              "max_latency": 250
            }
          }
        }
      }
    }
  }
}

(温馨提醒,请确保更改应用程序的 name 和 version 以匹配你的 应用程序和版本!)

如果没有验证错误出现,点击 创建并启动 并等待过程完成。这将导致一个新的免费集群启动,并带有你的简单示例匹配器。

你现在可以继续下一步。

2. 探索配置

独特的 TPS 游戏规则

专门针对第三人称射击游戏,你可以定义多个 匹配机制配置文件 以适应特定游戏模式的规则和设置:

  • 在较为休闲的游戏中,限制两名玩家之间的排名差异,

  • 限制排名差异,仅允许具有相同排名的对手进行排名游戏,

  • 允许玩家提供地图偏好并选择适合所有人的地图,

  • 添加 中心选择 UI 以限制对手到指定的 延迟基站

  • 限制 匹配延迟 在最大阈值内,以防止匹配远距离玩家,

  • 限制 匹配延迟 在最大差值以内,以最大化延迟公平性,

  • 当允许更多玩家时,利用不同的 应用程序版本 分配更多 CPU 或内存,

  • 作为组加入 以便于创建预设大厅或填补团队而不超过团队规模。

从理想条件开始,逐步 扩展限制 以确保快速匹配:

  • 随着时间的推移慢慢放宽延迟限制,以找到更多玩家,

  • 慢慢增加允许的排名差异,以找到更多玩家,

  • 在最高排名(挑战者)之间增加扩展之间的时间,因为可用的玩家较少。

创建更高排名的票据以用于晋升匹配,以匹配更强的对手。

定义 单独的作弊者配置文件 以确保被标记的作弊者或有大量管理报告的玩家不会对正常玩家在排名游戏中的体验产生负面影响。

语义版本控制

每个新版本都使用 语义版本控制 通过解释格式 major.minor.patch 来清楚地传达更改的影响:

  • major 版本包括破坏性更改,需要集成审查,

  • minor 版本包括大量向后兼容的改进,

  • patch 版本包括错误修复和小型改进。

某些 部署可能导致错误。我们通过自动重试部署最多 max_deployment_retry_count 次来尝试解决此问题(无需客户端确认)。

为了确保意外的客户端崩溃或被放弃的票据不会滞留并占用你的匹配器资源,将在 ticket_expiration_period 后取消票据,使其状态变为 CANCELLED ,并在 ticket_removal_period 后永久删除。

我们的匹配逻辑核心配置在 匹配机制配置文件中。每个配置文件都是一个完全孤立的匹配队列,指向具有预定数量所需 CPU 和内存(RAM)资源的 应用程序版本

匹配机制规则 必须满足初始规则集中的条件,才能将玩家组合在一起,每个条件由三个属性定义:

  • 你选择的名称,例如 - 匹配大小

  • 规则类型,也称为运算符,例如 - player_count

  • 最后是运算符属性,例如 team_count 或 team_size

玩家计数规则

这是一个特殊规则,定义需要多少玩家匹配以启动分配:

  • team_count 指的是团队数量,1 个团队可以用于合作或全自由模式,

  • team_size 指的是每个团队的 玩家数量。

我们的简单示例演示了一个有 2 名玩家的合作游戏。

请注意,"玩家计数"规则 是必需的,只能在你的初始配置规则中定义一次

延迟规则

使用此规则为所有玩家提供最低可能的延迟。一旦客户端测量并提交其往返时间(延迟)与所有可用基站相比,Gen2 将仅考虑在特定的 difference 延迟值内的匹配,该值是相对于 延迟基站 进行测量的。这为划分你的玩家基础提供了一种“软”解决方案,使得与邻近区域的匹配成为可能,尤其改善了地区较少的匹配速度。使用 max_latency来防止与远处的玩家匹配。

你现在可以继续下一步。

我们的示例 基站 规则的初始设置为 "difference": 50, "max_latency": 200 :

  • Alice 和 Bob 将匹配,因为北京被丢弃(>200),其余均在 | A-B | < 50 的范围内:

    • Alice {蒙特利尔: 12.3,纽瓦克: 45.6,达拉斯: 59.9,北京: 264.4}; 和

    • Bob {蒙特利尔: 27.3,纽瓦克: 32.4,达拉斯: 23.1,北京: 252.2}。

  • Charlie 和 Dave 将不匹配,因为在达拉斯基站的 | C-D | > 50:

    • Alice {蒙特利尔: 5.7 纽瓦克: 44.2,达拉斯: 59.5,北京: 263.2}; 和

    • Bob {蒙特利尔: 57.8,纽瓦克: 32.0,达拉斯: 24.2,北京: 272.3}。

请注意,"延迟规则" 只能在你的初始配置规则中定义一次

3. 查看实例详情

在我们的仪表板中查看新匹配器的详细信息,一旦它初始化完成:

状态 指示服务健康情况,可能为在线、离线或错误状态。

  • 标识符 帮助 Edgegap 员工快速找到你的匹配器,如果你需要故障排除帮助。

  • 启动时间 可追踪最后更新时间。

  • 规模 对应于我们的 定价层

  • API URL 将由游戏客户端和游戏服务器用于与 Gen2 通信。

  • Swagger URL 是一个方便的 openAPI 规范 GUI,我们提供以探索 API 架构。

  • 认证令牌 是由游戏客户端和游戏服务器用于认证的唯一私密令牌。

要使用 API 测试新的匹配器, 你将需要 Swagger URL、API URL 和认证令牌

你现在可以继续下一步。

4. 测试票据 API

首先, 打开你的 Swagger URL 以在 Swagger GUI 中检查你的 openAPI 架构

点击“匹配器”标题下的 /...swagger.json URL 以打开原始 JSON 架构:

将此页面保存为文件在你的驱动器上(CTRL/CMD+S)。

打开你的 Postman 应用程序 并登录你的免费账户。

从上一步导入你的 swagger.json 文件:

  • 保持 Postman 集合 被选中,

  • 选择 查看导入设置 并将设置 参数生成 更改为 示例

确认导入,这将导致列表左侧的集合中出现一个新集合,名为匹配器。

查看更多操作,打开 授权 选项卡并选择:

  • 授权类型 - API 密钥

  • 密钥 - “授权

  • 值 - 在这里插入你的 AuthToken 值,

  • 添加到 - 头部

按下 (CTRL/CMD+S) 或保存图标以 保存更改。你的 Postman 标签中的橙色点应该消失。

在匹配器集合中,选择 票据 并 创建匹配票据,打开新选项卡。

选择选项卡 正文 预览你的 玩家票据请求

注意 player_ip 设置为 null——这将导致自动使用添加到你的请求中的 IP 地址(请参见 服务器到服务器的集成 以获取替代方案),

  • profile 指的是你的 匹配机制配置文件

  • attributes 包括匹配器规则的值,在这个例子中是为 latencies 规则,

    • 规则 player_count 是唯一不需要在玩家票据中包含任何属性的规则。

注意:确保参考示例的 Swagger 导入配置

点击 发送 并查看你的玩家票据请求的响应:

  • id 是你唯一的匹配票据 ID,保存该值以便稍后查看你的票据,

  • profile 确认匹配的 匹配机制配置文件

  • group_id 是分配给每张票据的唯一组 ID,单个玩家被表示为一个组,

  • player_ip 是玩家的公共 IP 地址,无论使用何种识别方法,

  • assignment 设置为 null 以指示票据尚未匹配或分配给服务器,

  • created_at 提供有关创建玩家票据的时间的信息,以用于游戏 UI,

  • status 指示票据的当前状态,所有票据在 SEARCHING 状态下开始(请参阅 匹配机制流程 获取详细信息)。

创建第二张票据,点击 发送 再次,让我们的两名玩家匹配并启动服务器。

在你的匹配器集合中,选择 {ticketId} 并 阅读匹配票据

输入上一步骤的票据 ID 并点击 发送

查看玩家票据的更新分配:

  • 状态首先更改为 MATCH_FOUND ,同时保持 assignment 设置为 null 以指示玩家已匹配并正在分配服务器,

点击 发送 再次检查你的票据,并查看玩家票据的更新分配:

  • 状态更改为 HOST_ASSIGNED ,同时 assignment 中包含分配服务器的详细信息。

 在我们的仪表板中检查你的新部署

  • 请注意,每个部署都带有所有票据 ID 和配置文件的标签,以增加可追溯性。

尝试从你的游戏客户端连接到指定的服务器。

一旦你验证能够顺利连接到你的部署并完成测试, 停止你的部署 以释放你的账户中的容量,供下一个构建使用。

你现在可以继续下一步。

5. 在你的游戏中集成匹配器

Edgegap 的匹配机制集成:

  • 与 游戏客户端,以管理 玩家票据

  • 与 游戏服务器,以:

    • 处理通过其票据传递的玩家偏好,

    • 选择性支持 回填 在开始后添加或替换玩家。

在 游戏客户端中,我们建议在整个 匹配机制流程 中向玩家提供票据状态更新,使用游戏内 UI 以获得最佳玩家体验。请参见:

在 游戏客户端中,确保处理不可重试的错误:

  • HTTP 404 未找到 - 票据已被删除,

  • HTTP 500 内部服务器错误 - 临时服务中断。

在 游戏服务器中,处理玩家偏好和初始服务器上下文。无需 API 集成:

  1. 读取 注入环境变量(Gen2) 以检索初始玩家的匹配数据。

  2. 读取 注入环境变量(应用程序版本) 以获取版本特定参数、设置(玩家容量)和秘密信息。

  3. 读取 注入环境变量(部署) 以获取部署信息,例如 IP 地址、位置等。

一旦玩家连接, 游戏服务器和游戏客户端 开始加载场景以执行同步步骤(例如选择和加载地图/场景/关卡)。我们建议使用完整的 3D 场景、类大厅的社交 UI 或带有进度条的加载屏幕,以指示初始化过程正在进行中。

一旦 游戏客户端 完全加载,玩家加载/前往主要游戏场景。

可选地, 游戏服务器 可以创建和管理 回填 以及玩家容量(添加或替换离开的玩家)。

确保你的 部署会正确停止 使用 注入 DELETE_URL,如果:

  • 没有玩家加入匹配,

  • 所有玩家已离开匹配,

  • 匹配正确结束。

恭喜你,已完成 Edgegap 匹配器集成!如果你想了解更多,请在我们的学习中心阅读更多内容。