编写游戏循环

*此内容使用人工智能(Beta)翻译,可能包含错误。若要查看英文页面,请点按 此处

已创建地图后,我们可以开始构建脚本了。剩下的这个课程将重点关注脚本所有不同的元素。

设置脚本

战斗模式将使用模块脚本和普通脚本的组合。以下是脚本和其函数。

游戏管理器脚本。 使用游戏设置中的变量从匹配管理器运行函数
匹配管理器模块脚本。 运行如发送玩家进入竞技场或跟踪时间在匹配赛中。
游戏设置模块脚本。用于其他脚本的常见变量。

游戏设置脚本

创建名为 GameSettings 的模块脚本,用于储存其他脚本中使用的变量,例如匹配和中场休息时间。这些变量将被游戏管理器脚本稍后使用。

  1. ServerStorage 中,创建一个名为ModuleScripts的文件夹。在该文件夹中,创建一个名为GameSettings的新模块脚本。

  2. 打开游戏设置并将模块表重命名为与脚本名称匹配。


    local GameSettings = {}
    return GameSettings
  3. 在模块表中,为以下用途添加变量。 为每个值做出最佳猜想,您总是可以在测试时更改它。

    • 中场休息时间 - 秒后玩家才能开始匹配。
    • 比赛时长 - 以秒为单位的比赛时长。
    • 最低参赛者 - 最小参赛者数量需要开始。
    • 过渡时间 - 在秒后进行匹配之前和之后的时间。使游戏循环的零件之间的过渡更顺滑。

    local GameSettings = {}
    -- 游戏变量
    GameSettings.intermissionDuration = 5
    GameSettings.matchDuration = 10
    GameSettings.minimumPlayers = 2
    GameSettings.transitionTime = 5
    return GameSettings

MatchManager 脚本

GameManager 的第二个脚本是 MatchManager 。 此脚本管理任务,例如启动计时器或重置玩家一旦结束比赛。

在 MatchManager 中,有一个名为 prepareGame() 的函数,可以通过将玩家转换为匹配赛开始游戏。

  1. 在 ServerStorage > ModuleScripts > 添加一个名为 MatchManager 的模块脚本。重命名模块表。


    local MatchManager = {}
    return MatchManager
  2. 增加一个名为 prepareGame() 的新模块功能。包括打印声明来测试脚本。


    local MatchManager = {}
    function MatchManager.prepareGame()
    print("Game starting!")
    end
    return MatchManager

编写游戏循环

主游戏循环将使用创建的变量在GameManager脚本中编码。记住,游戏循环有三个阶段:中场休息、比赛和清理和重置。

游戏管理器脚本

这是一个普通的服务器脚本,请将其放入 ServerScriptService 而不是模块脚本目录。 实际游戏循环将在一段时间内真的循环。

  1. 在 ServerScriptService 中,创建一个名为 GameManager 的新脚本。

  2. 为“ServerStorage”服务添加变量,这是“ModuleScripts”的所在地。然后为“Players”服务添加变量,这将在中场休息时检查玩家数量。


    -- 服务
    local ServerStorage = game:GetService("ServerStorage")
    local Players = game:GetService("Players")
  3. 要使用以前创建的模块:

    • moduleScripts 设置到 ModuleScripts 文件夹的位置。
    • 添加名为 matchManagergameSettings 的变量。将每个变量设置为需要它们的脚本。

    -- 服务
    local ServerStorage = game:GetService("ServerStorage")
    local Players = game:GetService("Players")
    -- 模块脚本
    local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
    local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
    local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
  4. 在变量之后,添加一个 while true do 循环。游戏循环的所有阶段都会进入内部重复无限。


    -- 模块脚本
    local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
    local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
    local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
    -- 主游戏循环
    while true do
    end

编写中场休息

当游戏循环无限运行时,中场休息应暂停循环,并且只有足够的玩家才能开始匹配。要编写此中场休息,请在 while 循环中包含一个递归循环。该递归循环将重复直到有足够的玩家,暂停主循环。一旦有足够的玩家,它就会退出并转换玩家进入匹配。

使用 重复循环 ,代码在循环中至少会运行一次。与时间循环不同,它不会检查它是否为闭环直到闭环结束。这确保玩家总是在比匹配开始前返回大厅。

  1. while true do 循环中,输入 repeat ,并按 输入 键完成自动完成,并使用关键字 1> til1> 。


    while true do
    repeat
    until
    end
  2. 检查当前玩家数量 (#Players:GetPlayers()) 是否大于或等于在 GameSettings 模块中创建的 minimumPlayers 变量。


    while true do
    repeat
    until #Players:GetPlayers() >= gameSettings.minimumPlayers
    end
  3. 在重复循环中,添加一个打印声明,说明中场休息即将开始。使用 task.wait() 暂停游戏设置中的中场休息使用 intermissionDuration 从游戏设置。


    while true do
    repeat
    print("Starting intermission")
    task.wait(gameSettings.intermissionDuration)
    until #Players:GetPlayers() >= gameSettings.minimumPlayers
    end
  4. 测试打印声明 "Starting intermission" 是否显示至少两次。看到两次都是看到消息的最佳方式,因为这表明重复循环没有找到足够的玩家并且运行再次。你必须等待第二次查看消息的时间才能看到消息。

排查提示

如果您未能按照计划生成,请尝试以下其中一个。

  • task.wait() 应该位于重复循环内。在等待之前,脚本将在一秒内运行太多次,导致 Roblox Studio 过度加载并导致错误。
  • 在游戏设置模块中,变量 intermissionDuration 应大于 1 。如果小于 1 ,脚本可能会重复太频繁,导致滞后问题。

结束中场休息

一旦有足够的玩家,请等待他们短暂的过渡时间。然后,通过调用 prepareGame() 函数在 MatchManager 中发送他们到比赛。记住,该函数只打印一行,但您稍后会添加更多代码。

  1. 在重复循环结束时,添加一个打印声明,说明中场休息结束,测试你的代验证码。然后,使用 GameSettings 的 transitionTime 变量使用。


    while true do
    repeat
    print("Starting intermission")
    task.wait(gameSettings.intermissionDuration)
    until #Players:GetPlayers() >= gameSettings.minimumPlayers
    print("Intermission over")
    task.wait(gameSettings.transitionTime)
    end
  2. 在等待后,从 prepareGame() 从匹配管理器模块调用。当代码运行时,这将只打印文本到输出窗口。等待下一节测试此验证码。


    while true do
    repeat
    print("Starting intermission")
    task.wait(gameSettings.intermissionDuration)
    until #Players:GetPlayers() >= gameSettings.minimumPlayers
    print("Intermission over")
    task.wait(gameSettings.transitionTime)
    matchManager.prepareGame()
    end

测试多人游戏

现在,要使代码运行 prepareGame() ,它需要退出重复循环。但要实现这一点,需要有更多 than 一个玩家。 这意味着 如果您使用“玩测试”按钮,函数将永远不会运行,因为您是游戏中的唯一玩家(除非您的最低玩家是一个)。 要测试这一点,您需要模拟多人游戏。

启动一个本地服务器

要测试需要超过一名玩家的代码,请创建一个本地服务器。 与发布的游戏通常在 Roblox 服务器上,但 本地服务器 模拟您的电脑上的多人游戏。

  1. 要启动一个本地服务器,请在 测试 选项卡> 客户端和服务器 部分>将玩家下拉列为游戏设置的最低游戏玩家数。 此课程使用 2 个玩家。

  2. 单击“开始”以启动服务器。

  3. 等待服务器设置。多个窗口将在您的原始 Studio 窗口之上打开。您可能需要允许 Roblox Studio 从 firewalls 或其他在线安全软件中访问。

排查提示

在此时,您无法查看测试服务器,请尝试以下其中一个。

  • 如果您有服务器启动时的任何问题,请重新检查文章服务器和路由器问题
  • 将玩家数量设置为小数,例如 2 或 3。
  • 如果问题仍然没有解决,请尝试重新启动 Studio 或重新启动您的计算机。

在本地服务器上测试

当服务器启动时,您会看到多个窗口。每个窗口都代表服务器/客户端关系的不同部分。

  • 服务器 (绿色边框) 运行游戏。
  • 客户端 (蓝色边框) 模拟玩家的体验。
绿色边界的服务器
蓝色边框的客户端

当服务器运行时,您可以检查代码是否工作。

  1. 找到 服务器 窗口,边框绿色。检查从MatchManager脚本调用的打印声明。因为有重复循环,您会看到相同的打印声明重复。

  2. 一旦您完成测试,在任何窗口中关闭服务器按钮。这将关闭所有服务器和客户端窗口,并将您带回到您的普通 Studio 窗口。

排查提示

如果没有出现预期的打印声明,请尝试以下其中一个。

  • 检查函数 like prepareGame() 是否在真实时间内循环。
  • 如果 MatchManager 打印失败,请检查一些常见的问题,例如确保 MatchManager 脚本在 GameManager 中是否需要,或将 prepareGame() 添加到该模块的表。

已完成的脚本

以下是完成脚本来重新检查您的工作。

游戏管理器脚本


-- 服务
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- 模块脚本
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- 主游戏循环
while true do
repeat
print("Starting intermission")
task.wait(gameSettings.intermissionDuration)
until #Players:GetPlayers() >= gameSettings.minimumPlayers
print("Intermission over")
task.wait(gameSettings.transitionTime)
matchManager.prepareGame()
end

MatchManager 脚本


local MatchManager = {}
function MatchManager.prepareGame()
print("Game starting!")
end
return MatchManager

游戏设置脚本


local GameSettings = {}
-- 游戏变量
GameSettings.intermissionDuration = 5
GameSettings.roundDuration = 10
GameSettings.minimumPlayers = 2
GameSettings.transitionTime = 5
return GameSettings