Roblox Studio · 第 12 课

补间动画:制作平滑升降门

用 TweenService、TweenInfo 和 Completed 做一扇能打开、等待、关闭的门。

10–15 岁 60 分钟 TweenService 动手实践 测试与保存

Course overview

让基地大门慢慢升起,再稳稳落回原位。

直接修改 Position 会让门瞬间跳到新位置。TweenService 则负责计算中间过程,让你指定“从这里到那里,用一秒完成”。

我们先用触碰开门,再在下一课换成主动按键。门只是视觉与碰撞练习,不承担乘客运输,也不当作安全权限边界。

01 · BEFORE

开始之前

会使用 Touched 和 busy。新建 Lesson12,了解 Position 是 Vector3。

02 · MAKE

你的作品

触碰开关后,门上升一秒、保持两秒、下降一秒,期间不会重复启动。

03 · CHECK

完成标志

连踩开关不会抖动;每次关门都回到同一位置,不会越升越高。

官方缓动曲线对比图,不是门的运行截图
图 12-1:官方缓动曲线图:曲线展示变化快慢,不是门的运行结果。先用 Sine 做一次平滑移动,再比较其他曲线。Roblox Creator Documentation · CC BY 4.0 · 原图未修改 · 许可说明

Learning route

先准备,再动手;看到结果后,记得保存。

每完成一小步,就测试一次。先说出你预计会看到什么,再用 Play 和 Output 检查,不用急着一次写完所有代码。

1

01 · 门与开关分开放

门应该 Anchored=true,这样重力不会和补间争着控制它。碰撞在打开期间关闭,关门时也暂时不阻挡,避免把角色夹在动画途中。

2

02 · 一次补间需要三个信息

TweenService:Create(对象, TweenInfo, 目标表) 要知道改谁、怎样变化、变成什么。目标表里的键必须是真实属性名,例如 Position。

3

03 · 等动画完成,再执行下一步

Completed:Wait() 等待这段动画结束,然后才开始保持或关闭。比随意猜一个 task.wait 时长更清楚。

4

04 · 一次只换一种动画手感

把时长从 1 改成 2,门会更慢。把 Sine 改为 Linear,则变化速度更加均匀。每次只改一项,你才知道差别来自哪里。

5

05 · 检查重复触发和最后位置

一次开门好看还不够,连续运行五轮后也应该准确归位。位置越来越偏,通常说明起点或终点在循环过程中被重新累加了。

Step by step

01 · 门与开关分开放

门应该 Anchored=true,这样重力不会和补间争着控制它。碰撞在打开期间关闭,关门时也暂时不阻挡,避免把角色夹在动画途中。

练习时不要站在最终关门位置。真正的大门还需要检测门口是否有人,本课先把完整动画周期做清楚。

  1. 创建 Gate:Size=10, 10, 1,Position=0, 5, -16,Anchored=true。
  2. 创建 Switch:Size=6, 1, 6,Position=0, 0.5, -8,Anchored=true、CanTouch=true。
  3. 在 Switch 中创建普通 Script:DoorTween。

Step by step

02 · 一次补间需要三个信息

TweenService:Create(对象, TweenInfo, 目标表) 要知道改谁、怎样变化、变成什么。目标表里的键必须是真实属性名,例如 Position。

TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut) 表示用一秒完成,起步与结束都比较柔和。Create 只是准备动画,Play 才会启动。

  1. 找到完整脚本中的两个 Create,比较它们的目标 Position。
  2. closedPosition 只在开始时记录一次,避免每次打开都把“当前位置再加 10”当成终点。
用 Output 检查脚本反馈的界面截图
图 12-2:官方 Output 界面参考:门不移动时,先检查错误消息和脚本行号,再确认 Gate 与 Switch 名称。Roblox Creator Documentation · CC BY 4.0 · 原图未修改 · 许可说明

Step by step

03 · 等动画完成,再执行下一步

Completed:Wait() 等待这段动画结束,然后才开始保持或关闭。比随意猜一个 task.wait 时长更清楚。

busy 在任何等待之前设为 true,整个开关周期结束后才恢复。另一个玩家此时踩开关,也不会创建第二套相互争抢的动画。

  1. 将完整代码放入 Switch > DoorTween。
  2. Play 后踩开关,观察一次完整开关过程。
  3. 连续踩或让两名玩家一起踩,门仍应只执行一个周期。
Workspace > Switch > DoorTween · 完整脚本Luau
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local switch = script.Parent
local gate = workspace:WaitForChild("Gate")
local closedPosition = gate.Position
local openPosition = closedPosition + Vector3.new(0, 10, 0)
local info = TweenInfo.new(1, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut)
local busy = false

switch.Touched:Connect(function(hit)
    if busy then return end
    local character = hit:FindFirstAncestorOfClass("Model")
    local player = character and Players:GetPlayerFromCharacter(character)
    local humanoid = character and character:FindFirstChildOfClass("Humanoid")
    if not player or not humanoid or humanoid.Health <= 0 then return end
    busy = true
    gate.CanCollide = false
    local opening = TweenService:Create(gate, info, {Position = openPosition})
    opening:Play()
    opening.Completed:Wait()
    task.wait(2)
    local closing = TweenService:Create(gate, info, {Position = closedPosition})
    closing:Play()
    closing.Completed:Wait()
    gate.CanCollide = true
    busy = false
end)

Step by step

04 · 一次只换一种动画手感

把时长从 1 改成 2,门会更慢。把 Sine 改为 Linear,则变化速度更加均匀。每次只改一项,你才知道差别来自哪里。

同一属性上同时运行的补间会互相影响。不要在另一个脚本里又不停给 Gate.Position 赋值。

  1. 比较一秒和两秒的开门过程。
  2. 把上升距离改为 12,确认没有碰到屋顶。
  3. 保留最容易观察的版本,不用追求夸张弹跳。

Step by step

05 · 检查重复触发和最后位置

一次开门好看还不够,连续运行五轮后也应该准确归位。位置越来越偏,通常说明起点或终点在循环过程中被重新累加了。

Tween 移动的 Anchored 平台不保证像电梯一样可靠带着角色移动。做载人平台需要额外研究物理与角色行为,不在这里直接照搬。

  1. 运行五轮,每轮结束检查 Gate.Position。
  2. 确认门关闭后 CanCollide 恢复为 true。
  3. 保存你的起点、终点和动画时长三项参数。

Homework

轮到你来改一改,做出自己的版本。

1 慢速仓库门

把开关动画改为两秒,保持时间改为三秒。

2 颜色配合

在 busy 时把开关变橙色,完成后恢复蓝色。

3 选做:侧滑门

把终点偏移改为 X 方向,确保侧面有足够空间。

完成标准:先在 Playtest 中验证作品,再点击 Stop,保存为“姓名缩写_Lesson12”或对应 Homework 副本;不要覆盖上一课的可运行版本。

Exit questions

先自己回答,再展开看看。

Create 后门为什么还没动?

还需要对生成的 Tween 调用 Play。

为什么只记录一次 closedPosition?

避免每次开门从变化后的坐标再累加距离,导致位置漂移。

busy 什么时候才能恢复?

在开门、保持、关门全部结束之后。

这个例子可以直接当载人电梯吗?

不应直接照搬,补间移动与可靠运送角色不是同一个问题。

Explore further

需要查资料时,从这里出发。

正文代码可以直接复制。先确认脚本类型、放置位置,以及这段代码是完整版本还是小实验;不要把同一脚本的多个版本叠加运行。界面参考图已标注来源,图中的对象名可能与本课不同,请以操作步骤为准。