开发 / ROBLOX
Roblox Studio检查点:独立练习障碍路线
制作两个检查点,为每位玩家设置独立重生位置,并检查死亡、重复接触、顺序和离开会话。
先定义小机制的规则 #
建立一条短练习路线,包含Start、Checkpoint1和Checkpoint2。玩家依次到达各点。接受与下一检查点的接触后,死亡应让角色回到那里。走回较早平台不能降低进度。第二名玩家具有独立进度和重生目的地。先明确这个规则,才能把预测与观察比较,而不是只看场景是否运行。
这是全新的教学原型,不是Stone Trail或本站作者其他游戏的实现。下面的脚本为本课原创;我们分析逻辑,但本文没有在Roblox引擎中运行它。进度只存在于当前服务器内存中。这里不添加跨访问保存、奖励或对所有绕路手段的防护。先验证这个有限机制,再扩展它。教学示意图也不是实际游戏地图或Studio截图。
1. 用准确名称准备独立场景 #
保存一个新的小项目,不干扰正在使用的游戏。在Workspace中准备一个名为Start的SpawnLocation和一个名为Checkpoints的Folder。文件夹里放两个SpawnLocation,分别叫Checkpoint1与Checkpoint2。在ServerScriptService里添加普通Script,命名为CheckpointServer。最终路径是Workspace.Start、Workspace.Checkpoints.Checkpoint1、Workspace.Checkpoints.Checkpoint2以及ServerScriptService.CheckpointServer。名称必须一致;Checkpoint 1多一个空格就不同。
其他路面可用普通锚定Part,但检查点必须真正是SpawnLocation,而非颜色相似的Part。在这个新练习场景中移除无关出生点。无需插入带未知脚本的模型包:自己的平台和一个服务器脚本就够了。加代码前确认三点都看得见且互不重叠,路线短而清楚。
2. 配置接触与安全重生空间 #
沿短而安全的路依次放Start、Checkpoint1、Checkpoint2。保持距离,以便单独触碰每个点。在SpawnLocation上方留出空间,避免角色出现在墙内、低天花板下或悬崖边。颜色和标签用于识别,不会自动记录进度。第一次测试不需要困难陷阱;障碍难度与检查点逻辑是两个问题。
下表列出本练习配置,脚本启动时会再次设置必要值。各点允许不依赖队伍的重生,关闭接触换队。CanTouch允许接触事件,Anchored固定平台。以后添加队伍或collision groups时,必须重新检查重生资格和物理接触。暂时保持默认自动加载角色启用;自定义加载不在这个原型范围内。
| 属性 | 值 | 本练习用途 |
|---|---|---|
| Class | SpawnLocation | 出生及重生平台 |
| Anchored | true | 固定平台 |
| CanCollide | true | 角色可站在平台上 |
| CanTouch | true | 允许检测物理接触 |
| Enabled | true | 允许出现 |
| Neutral | true | 不限制队伍 |
| AllowTeamChangeOnTouch | false | 接触不改变队伍 |
3. 将完整脚本放在服务器 #
打开ServerScriptService里的CheckpointServer,用下面完整示例替换内容。不要只复制Touched处理器;准备和初始化也必须存在。checkpoints表明确两个对象顺序,不依赖GetChildren的返回排列。configure核对对象类型并设置属性。缺少名称时WaitForChild会等待,类型错误时assert会报错。先修复结构,再测试路线,不要用延迟掩盖拼写错误。
服务器设置Player.RespawnLocation,并以Player为键保存progress。StarterPlayerScripts里的LocalScript不是等价放置方式。测试时不要同时运行另一个修改RespawnLocation的脚本。准备完场景后启动新的测试。如果在已经运行的测试里插入代码,设置未来重生点不会把活着的角色立即移到Start;这里没有传送命令。
local Players = game:GetService("Players")
local start = workspace:WaitForChild("Start")
local folder = workspace:WaitForChild("Checkpoints")
local checkpoints = {
folder:WaitForChild("Checkpoint1"),
folder:WaitForChild("Checkpoint2"),
}
local progress = {}
local function configure(spawn)
assert(spawn:IsA("SpawnLocation"), "Expected SpawnLocation")
spawn.Anchored = true
spawn.CanCollide = true
spawn.CanTouch = true
spawn.Enabled = true
spawn.Neutral = true
spawn.AllowTeamChangeOnTouch = false
end
configure(start)
for _, checkpoint in ipairs(checkpoints) do
configure(checkpoint)
end
local function initialize(player)
if progress[player] ~= nil then return end
progress[player] = 0
player.RespawnLocation = start
end
Players.PlayerAdded:Connect(initialize)
Players.PlayerRemoving:Connect(function(player)
progress[player] = nil
end)
for _, player in ipairs(Players:GetPlayers()) do
initialize(player)
end
for index, checkpoint in ipairs(checkpoints) do
checkpoint.Touched:Connect(function(hit)
local character = hit:FindFirstAncestorOfClass("Model")
if not character then return end
local player = Players:GetPlayerFromCharacter(character)
if not player or player.Character ~= character then return end
local humanoid = character:FindFirstChildOfClass("Humanoid")
if not humanoid or humanoid.Health <= 0 then return end
local current = progress[player]
if current == nil or index ~= current + 1 then return end
player.RespawnLocation = checkpoint
progress[player] = index
end)
end4. 从碰到的部件识别玩家 #
Touched提供另一个部件,可能属于角色、掉落方块或其他物体。处理器查找最近的Model,用GetPlayerFromCharacter判断是否对应玩家,再核对player.Character,并寻找Health大于零的Humanoid。不做这些检查,物体或已死亡角色可能错误改变进度。不合格接触在设置重生位置之前return。
示例针对Humanoid位于角色Model中的普通角色。自定义嵌套rig需要有意识地调整模型查找;不要为了消除症状直接删除玩家验证。服务器观察到接触也不证明整条路线被诚实完成。角色移动和物理仍需要单独安全分析。本课检查普通短路线的个人检查点,不声称完成了反作弊系统。
5. 保持顺序而不阻塞其他玩家 #
新玩家的progress为0。仅接受current + 1:先索引1,再2。确认第一点后,脚或其他身体部件再次接触该平台,不再符合下一个索引。到达第二点后,第一点同样被拒绝。规则既防回退,也防跳过第一点。这是本练习选择的合同;自由顺序路线需要不同规则。
这里没有一次接触后锁住所有人的全局debounce。每个Player都是独立表键,检查及两次赋值没有task.wait或其他等待,因此玩家独立推进。这是对短处理器的逻辑分析,不是对以后异步代码的保证。如果加入奖励、数据请求或延迟,必须重新分析重复调用及修改状态的时机。
6. 分清死亡、新测试与重新加入 #
接受接触后只更新该Player的RespawnLocation。活角色留在原地,在下一次正常重生时核对目的地。死亡创建新的角色Model,但Player仍留在会话中,因此progress记录保留。不要在CharacterAdded里把progress清零,否则每次死亡都丢掉检查点。
离开时PlayerRemoving删除内存记录。重新加入得到新的0并指向Start。停止Studio测试再启动,也开始新会话。示例没有游戏内完整重置按钮。以后添加时,应同时重置索引和RespawnLocation;只改界面文字不够。保存项目保存场景和代码,不保存运行中的玩家表。不能把“保存文件”和“永久保存玩家进度”混为一谈。
7. 按步骤进行单人测试 #
在Studio测试下拉菜单中选择Test并启动。该模式插入角色;Run仅运行模拟而不插入化身,不适合首次走路检查。开始新会话并核对Start出生。正常走到Checkpoint1,停在平台上,然后在原型专门设计的坠落区域造成死亡。等正常重生并记录位置。
对Checkpoint2重复。之后实际走回第一点,再检查死亡:应继续选择第二点。不要与Stop后新Test混淆,因为新测试故意清空内存。实际结果与预测分开记录。如果所选坠落区域没有让角色死亡,还不能认定RespawnLocation测试失败。先确认死亡与新角色出现确实发生,再评价目标。
8. 检查物体、跳序和重复接触 #
另一次尝试先碰Checkpoint2,再碰Checkpoint1之前检查结果:顺序条件应保留Start。随后正常完成两点。物体测试可创建普通未锚定方块,让它物理落在检查点上。它不是Player,不应改变任何人的进度。通过服务器状态或对应玩家之后的重生进行比较,而非仅看平台颜色。
Touched依赖物理运动。修改CFrame使两块锚定部件重叠,不是同样的事件测试。没有接触时,检查双方CanTouch及collision groups规则。实验没执行之前不要写“方块已被拒绝”的虚构结果。后面的用例表列出预期,不是本脚本已在Roblox引擎测试的报告;自己的笔记也应保留这个区别。
9. 两名玩家分别验证进度 #
选择Server & Clients,设置两个客户端,按Play或F7启动。A到第一点,B留在Start。死亡后A应在Checkpoint1出现,B仍在Start。然后B到第一点、A到第二点,分别比较结果。还要试两个角色几乎同时接触第一点:共享锁不能导致一人没有自己的进度。
两台相机看到同样颜色的平台不能证明个人设置。Workspace物体颜色是共享的,RespawnLocation属于某个Player。记录哪个客户端执行动作、哪个角色重生。结束后使用End Session关闭整个多客户端会话。两个本地客户端能检查具体情况,不证明大服务器性能、嵌套角色兼容性或所有异常接触顺序。
10. 每次查一个失败条件 #
检查点无效时,从结构走到状态:准确路径、SpawnLocation类型、普通服务器Script、CanTouch、活Player、预期索引、允许重生。拼写错误和故意拒绝索引2是不同原因。执行错误可使用相关Output指南;此处不重复完整控制台课程。下表没有“通过”标记,把自己的观察写在预期旁。
尤其检查启动后Enabled是否关闭、Neutral是否改变。检查点应留在Workspace且对玩家有效。其他脚本可能后来修改属性或RespawnLocation。如果目的地错误,记录动作顺序与真实平台,而非只说“坏了”。每次修改用明确的新尝试复核。无止境加等待不能修复错误的顺序条件。
| 用例 | 预期状态 | 检查 |
|---|---|---|
| 新Test/加入 | 0;Start | 真实首次出生 |
| Checkpoint1后死亡 | 1;Checkpoint1 | 等待新角色 |
| 再次Checkpoint1 | 不改变 | 不同身体部件接触 |
| 第一点后Checkpoint2 | 2;Checkpoint2 | 死亡返回第二点 |
| 第二点后回第一点 | 2;Checkpoint2 | 不回退 |
| 先第二点再第一点 | 0;Start | 拒绝跳序 |
| 方块/非玩家模型 | 不改变 | 没有对应Player |
| 死亡/旧角色 | 不改变 | Health及当前Character |
| A推进,B未推进 | A/B目的地独立 | 分别死亡后检查 |
| 离开/Stop后新测试 | 新的0 | 没有永久保存 |
11. 保存结果,再选一个扩展 #
结束测试,以可辨识名称保存原型。记录层级、脚本版本、自动加载角色假设、实际完成的单人与双客户端用例以及预期和真实重生位置。本文的逻辑分析不表示你的项目已经通过Studio测试。把机制移入现有游戏之前,在自己场景中比较所有重要用例。
下一步可以是个人确认消息或明确重置按钮。永久保存是独立任务,涉及加载、写入失败、数据版本和重置规则;此处不用DataStore。不要向玩家承诺永远保留进度。先保留清楚的当前规则:本次访问中死亡回到已到达的点,离开结束教学内存状态。小而验证过的机制比同时加多个未测试系统更容易扩展。
原始资料
Roblox Creator HubRoblox Creator Hub — Player.RespawnLocation
Roblox Creator Hub — BasePart.Touched and CanTouch
Roblox Creator Hub — Studio testing modes
Roblox Creator Hub — Players lifecycle
Roblox Creator Hub — ServerScriptService