Roblox Studio · 第 4 课

函数与事件:踩一下,方块就变色!

给蓝色方块装一个“触碰门铃”!角色一碰,它就变金色,休息一会儿,再变回蓝色。跟着图和小实验,一步步认识函数、事件和 busy。

60 分钟 第 1—3 课后 函数:动作包 Touched:触碰通知 Connect:接上门铃 busy:忙不忙

Course overview

今天,让一块普通地板学会“回应你”。

你有没有在 Roblox 里踩到一块地板,结果门开了、灯亮了,或者机关突然启动?看起来像是地板认识你,其实它只是按我们写好的规则办事。今天,我们也来造一块会回应角色的方块。它叫 TouchPad,你可以把它理解成“碰一碰就有反应的小平台”。

这块平台的脾气很简单:平时是蓝色;角色身体碰到它,就变成金色;等大约一点五秒,再变回蓝色。如果这段时间里又有人来碰,它会挂出一块看不见的“请稍等”牌。放心,我们先做这个小效果,不需要一口气造出整个冒险世界。

今天会遇到几个英文名字。别把它们当成单词考试,把它们当成工具箱里的工具就好。每认识一件工具,我们马上试一试。你可以一边看思维导图,一边对照游戏场景图,最后亲自进入游戏,看看你的平台有没有按规则工作。

01 · 函数

把动作装成一包

给一组动作起个名字。需要它时,再让这一包动作开始工作。

02 · 事件

接收游戏里的消息

有人碰到平台,Touched 就发出“有东西碰到我了”的通知。

03 · 冷却

挂上“请稍等”牌

平台正在变色时,用 busy 暂时拦住新通知,避免忙成一团。

函数的声明名称参数函数体和 end 组成示意
图 4-1:一个函数就像一个动作包。给它起名字,把要做的事放进去,用 end 表示“这一包到这里结束”。

Learning route

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

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

1

先存一个新副本

把上一课的作品另存为 Lesson04。旧作品留好,实验时心里更踏实。

2

看懂今天的任务

先看地图:谁来碰平台?平台会做什么?它什么时候重新准备好?

3

搭好蓝色平台

做一个叫 TouchPad 的扁平方块,把普通 Script 放进它里面。

4

接上“触碰门铃”

认识函数和 Touched。先在 Output 中看看,到底是什么碰到了平台。

5

请角色来试

查找 Humanoid。普通小方块可以碰平台,但不会让它变色。

6

加一块“请稍等”牌

用 busy 控制等待时间。变金色、稍等、恢复蓝色,一轮完成!

7

测试并保存

试角色、试普通方块,再试重复触碰。结束后 Stop,保存自己的新版本。

第一站 · 看看今天要做什么

先看地图:一脚下去,平台要忙哪些事?

想象你正在设计一条障碍路线。前面是跳台,后面是终点,中间有一块蓝色平台。角色踩上去,平台变成金色,像在说:“收到,你来了!”这就是今天的小机关。效果不大,但它用到了很多游戏都会用的办法:等一件事发生,再做出回应。

先不用盯着代码。请沿着思维导图走一圈:角色碰到平台,平台收到触碰通知,然后检查能不能响应。如果可以,它就变色;如果正在忙,就先不接新任务。忙完以后,平台恢复蓝色,重新等下一次接触。把这条路线说顺,后面的代码会好懂很多。

注意,平台不会读心术。它不知道你是故意踩上来,还是不小心滑上来。它只知道“有东西碰到我了”。所以我们要教它做检查,不然一块掉下来的砖头也可能被当成贵宾。游戏规则就是这样:把你心里觉得理所当然的事,清楚地告诉电脑。

图里还有金币和终点旗,它们是在提醒你:今天的方法以后还能拿来做别的机关。现在先把变色做好。金币加分、记录通关这些功能,我们会在后面的课里慢慢加。一次只完成一个小目标,找问题也会轻松得多。

手机上的思维导图可以左右滑动,点一下还能打开原图。不用把整张图背下来。碰到不懂的地方,回到对应的分支看看,再回到游戏里试。地图是帮你找路的,不是让你背诵的。

  • 谁来碰?角色的身体部件,也可能是普通方块。
  • 谁报信?Touched,今天的“触碰门铃”。
  • 谁干活?我们写的 onPartTouched 函数。
  • 先查什么?平台忙不忙,碰到的东西是不是角色身体。
  • 看见什么?平台变金色,Output 留下消息。
  • 忙完怎么办?恢复蓝色,把“请稍等”牌收起来。
Roblox 方块角色踩在蓝色机关上,六个分支对应对象层级、函数、Touched、角色判断、颜色反馈和 busy 冷却。
思维导图 1:跟着“碰到 → 检查 → 变色 → 恢复”找路线。图里的金币和终点旗是以后可以做的玩法。
开口说一说:假装你是蓝色平台。用自己的话说说,角色一碰你,你接下来准备做哪几件事。

第二站 · 先把平台搭好

给机关安个家:方块在外,脚本在里面。

先把上一课的作品另存一个副本,名字里加上 Lesson04。然后在 Workspace 里插入一个 Part。Workspace 可以先理解成游戏场景的“物品清单”,我们的平台就放在这里。把 Part 改名为 TouchPad,注意字母大小写,给物品起清楚的名字,比到处找“Part、Part2、Part3”舒服多了。

用 Scale 把它做成一个扁扁的平台,大小大约是十二乘一乘十二 studs。stud 是 Roblox 里的长度单位,先按这个尺寸试就行。把它放在出生点前面的地面上,让角色几步就能走到。别急着把它摆到高空,今天我们要研究变色,不是研究摔下去有多快。

接着在 Properties 里找到三个开关,都设为 true,也就是开启。Anchored 让平台固定住,免得它被撞跑;CanCollide 让角色能站在它上面;CanTouch 让平台可以发出触碰通知。三个开关各管一件事,固定、能站、能报信,分清楚就不会乱。

把 Color 设成 RGB (46, 116, 181),平台就有了今天的蓝色外衣。RGB 可以想成三个调色旋钮,分别控制红、绿、蓝。现在照着数值设置即可,不需要背数字。后面代码里的 READY_COLOR 也用这组数值,这样“准备好了”就是同一种蓝色。

选中 TouchPad,在它里面添加普通 Script,命名为 TouchHandler。别选 LocalScript。打开这个脚本,先用下面两行小代码做个检查。script 指正在运行的脚本,Parent 指它在 Explorer 里上一层的对象。因为脚本放在平台里面,script.Parent 找到的就是 TouchPad。

点击 Play,再看 Output。Output 是脚本的“留言板”,print 会把消息写到这里。你应该看见 TouchPad。要是看见 ServerScriptService 等别的名字,先 Stop,再把脚本挪回平台里面。路径对了,后面的命令才会交给正确的平台。

先试两行:脚本有没有找到自己的平台?Luau
local touchPad = script.Parent
print(touchPad.Name)
  • Explorer 里应当能展开 Workspace → TouchPad → TouchHandler。
  • 普通 Script 放在 TouchPad 里面,script.Parent 才是这个平台。
  • 先确认 Output 打印 TouchPad,再继续往下做。
  • 改代码或改摆放位置前,先按 Stop。
蓝色 TouchPad 的待机场景:方块角色双脚仍在灰色 Baseplate 上,尚未接触机关。
运行场景 1 · 还没碰到(AI 生成的教学示意,非实机截图):角色站在平台外,TouchPad 是蓝色的。完整脚本接好后,它会等下一次触碰。
找错对象怎么办?先检查脚本放在哪一层。就像寄快递,动作写得再好,地址错了也送不到想要的地方。

第三站 · 认识动作包和门铃

函数是“动作包”,Touched 是“触碰门铃”。

假如每次有人来你家,你都要开门、打招呼、拿拖鞋。总把这些动作一条条重新安排,很麻烦。函数的办法是:把一组动作放在一起,给它起个名字,需要时再叫它出来工作。今天的动作包叫 onPartTouched,名字是在提醒我们:“有部件碰到平台时,要做的事在这里。”

local function 表示我们要创建一个函数。后面跟着它的名字,括号里写它接收的东西,再往下写要做的动作,最后用 end 收尾。你可以把 end 当成包的封口。只把动作包装好,它不会自己动起来;得有人来调用,也就是通知它开始工作。

Touched 是平台上的触碰事件。事件可以理解成游戏发来的消息。有人碰到平台,它就报信:“有东西碰到我了!”这次碰到平台的那个部件,会放进 otherPart 这个名字里。other 的意思是“另一个”,所以它说的是另一个碰过来的部件,不是平台自己。

角色有脚、腿、身体等部件。角色走上来时,收到的 otherPart 可能是一只脚。换成小方块落下来,收到的就是那块方块。参数这个词听着有点正式,其实就是函数这次收到的东西。同一个动作包收到不同的东西,就可以根据情况做不同的检查。

现在看代码最后一行。Connect 像一根线,把触碰门铃和动作包接在一起。Touched 发来通知,onPartTouched 就开始工作。这里写函数名 onPartTouched,不要在名字后再加一对括号。我们要交给门铃的是“等会儿用这个动作包”,不是“现在立刻打开动作包”。

先 Stop,把 TouchHandler 里的旧内容整段换成下面的代码,再 Play。走上平台,看 Output 写了什么。GetFullName 会显示那个部件在物品清单里的完整位置,方便我们找到它。此时平台还不会变色,这是正常的。我们先练会收消息,下一步再让它决定要不要变色。

先接上门铃:打印谁碰到了平台Luau
local touchPad = script.Parent

local function onPartTouched(otherPart)
    print("Touched by:", otherPart:GetFullName())
end

touchPad.Touched:Connect(onPartTouched)
  • local function:创建一个有名字的动作包。
  • otherPart:这次碰到平台的那个部件。
  • end:这一组动作写完了。
  • Touched:Connect(onPartTouched):让触碰通知叫这个函数来工作。
  • 现在只看 Output;平台不变色,先别着急。
触碰事件从物理接触传到处理函数再产生反馈的图示
图 4-2:平台收到触碰消息,把碰来的 otherPart 交给函数。函数照着你写的动作去做。
看到好几条消息?角色有好几个身体部件,它们都可能碰到平台。先观察这些消息,等会儿我们用 busy 让平台有条不紊地工作。

第四站 · 别把砖头当客人

谁来碰我?普通方块先等等,角色请进。

门铃接好了,但问题来了:一块普通砖头掉到平台上,也会发来触碰消息。我们希望角色触碰时变色,砖头触碰时不变色。于是要加一个检查。注意,Touched 负责报信,它不会替我们决定谁能通过。游戏规则还得我们自己写。

Roblox 的角色通常是一个 Model,也就是把身体部件放在一起的一组对象。里面还会有一个 Humanoid,你可以先把它当成角色的小管家,负责角色的走动、生命值等事情。今天我们找这个小管家,判断碰来的身体部件是不是属于一个角色。

想象碰到平台的是角色的一条腿。otherPart 就是这条腿。先看 otherPart.Parent,找到腿在 Explorer 里上一层的角色 Model;再用 FindFirstChildOfClass("Humanoid"),看看里面有没有 Humanoid。这个方法名很长,你可以把它读成:“帮我在这里找一个 Humanoid。”

如果找到了,就把找到的对象记在 humanoid 里。如果没找到,得到的是 nil,它表示“没有找到东西”。下面的 if not humanoid then 可以读成:“如果没找到小管家,就……”接着的 return 表示结束这一次函数工作。普通方块走到这里就被拦住,后面的变色动作也就不会执行。

这里有一个容易猜错的地方:找到 Humanoid,还不能证明对方一定是真人玩家。游戏里的 NPC,也就是电脑控制的角色,也可能有这个小管家。所以本课先学会分清“普通物体”和“带 Humanoid 的角色”。第九课再继续学怎样确认真人玩家,一次多认识一件工具就够了。

如果碰来的是帽子等配件里的 Handle,它的上一层通常是 Accessory,而不是整个角色。这段简单代码只查上一层,通常也会把它拦住。现在先用身体碰平台来测试。下面这段只是检查方法的小片段,用来读懂规则;最终请用下一站的完整代码,不要把几个同名函数拼在一起。

读懂检查方法:没找到 Humanoid 就 returnLuau
local function onPartTouched(otherPart)
    local humanoid = otherPart.Parent:FindFirstChildOfClass("Humanoid")
    if not humanoid then
        return
    end

    print("Confirmed humanoid character")
end
  • 第一步:otherPart 是哪个部件?
  • 第二步:它的 Parent,也就是上一层,是谁?
  • 第三步:这一层里面有没有 Humanoid?
  • nil:没找到;return:这次先到这里结束。
  • 这段是阅读片段,最终运行请换成下一站的完整脚本。
触碰对象分类思维导图:玩家身体与 NPC 身体的父模型可有 Humanoid,普通方块与配件 Handle 的直接父对象通常没有。
思维导图 2:分别看看身体、砖头、NPC 和配件的上一层。找到 Humanoid 说明有角色的小管家,不能直接当作真人玩家的证明。
普通灰色方块落在蓝色 TouchPad 上,角色站在机关外,机关没有变金色。
运行场景 2 · 砖头来“按门铃”(AI 生成的教学示意,非实机截图):普通小方块落到平台上,没找到 Humanoid,于是 return。平台仍是蓝色。测试时,角色要站在平台外。
先猜再看:如果碰来的是角色的一只脚,你觉得 Humanoid 能找到吗?如果换成普通小方块呢?指着地图说出你的理由。

第五站 · 请稍等,我正在忙

让平台忙一小会儿:变金色,再变回蓝色。

现在把检查和变色连起来。下面是完整的 TouchHandler。先 Stop,把这个脚本原来的内容全部换成这一份,别在旧代码后面再粘一份。READY_COLOR 是准备好时的蓝色,ACTIVE_COLOR 是收到有效触碰后的金色。Color3.fromRGB 用三个数字配颜色,就像在调色盘里调出两杯颜料。

平台为什么需要休息?因为角色不是只有一块身体。一只脚碰到、另一条腿又碰到,可能很快就有好几次通知。如果每次都启动变色和等待,平台就像被一群人同时喊名字,忙得不知道该先回应谁。我们需要一块“请稍等”牌,让它一次做完一轮动作。

这块牌叫 busy,意思是“忙”。它只记两种情况:false 表示没在忙,可以接新任务;true 表示正在忙,先别来打扰。只有这两种值的数据叫布尔值,不必被名字吓到。你可以先把它想成一个开关:忙或者不忙,没有“忙了百分之三十”这种选项。

读函数时,先看第一句 if busy then return end。它是在问:“我已经在忙了吗?”如果是,这次通知就到此结束。如果没在忙,再去找 Humanoid。找到以后,马上把 busy 设为 true,挂上“请稍等”牌;然后让平台变金色,并用 print 在 Output 里留一条消息。

接着 task.wait(1.5) 让这次工作等大约一点五秒。等待结束,平台恢复蓝色,最后把 busy 设回 false,收起“请稍等”牌。顺序要记清:先挂牌,再等待;先恢复颜色,再收牌。只挂不收,平台就一直不接新任务了,像一家永远写着“马上回来”的店。

busy 写在函数外面,所以每次触碰都能看到同一块牌。整块平台只有这一块牌,不是每个人各领一块。玩家 A 触发后,玩家 B 在冷却时走上来,也要等这轮结束。游戏里把这种暂时不接重复任务的办法叫 debounce,你记住“防止短时间重复执行”就抓住重点了。

等待时间不用拿秒表较真,它是大约一点五秒。平台变回蓝色后,先走开,再走上来,制造一次新接触。一直站在上面,并不保证每过一点五秒就再触发一次。还有,Play 时看到的变化属于测试中的游戏,Stop 后会回到编辑状态,这很正常。

完整 TouchHandler:整段替换后再 PlayLuau
local touchPad = script.Parent
local READY_COLOR = Color3.fromRGB(46, 116, 181)
local ACTIVE_COLOR = Color3.fromRGB(242, 184, 75)
local busy = false

local function onPartTouched(otherPart)
    if busy then return end

    local humanoid = otherPart.Parent:FindFirstChildOfClass("Humanoid")
    if not humanoid then return end

    busy = true
    touchPad.Color = ACTIVE_COLOR
    print(otherPart.Parent.Name, "activated TouchPad")
    task.wait(1.5)
    touchPad.Color = READY_COLOR
    busy = false
end

touchPad.Touched:Connect(onPartTouched)
  • 检查 busy:正在忙,就 return。
  • 检查 Humanoid:没找到,也 return。
  • busy=true:挂上“请稍等”牌。
  • 变金色、print 消息、task.wait(1.5)。
  • 恢复蓝色,再 busy=false:重新接待下一次有效触碰。
角色站上 TouchPad 后,整块机关从蓝色变为金色,展示一轮有效触碰反馈。
运行场景 3 · 收到啦!(AI 生成的教学示意,非实机截图):角色碰到平台,平台变金色。Output 会出现角色名字和 activated TouchPad,意思是“启动了 TouchPad”。约一点五秒后,平台变回蓝色。
Roblox 机关冷却思维导图:蓝色 ready 状态 busy=false,角色触碰后变金色 busy=true;新触碰被忽略,等待后恢复蓝色并解锁。
思维导图 3:蓝色等通知 → 挂牌变金色 → 等一会儿 → 恢复蓝色并收牌。一块平台共用一个 busy。
防重复触发 debounce 的处理流程图
图 4-3:平台忙的时候,新的触碰先不处理。等这一轮结束,再接下一次有效触碰。
先做稳定,再加花样:今天保持 Baseplate 在下面,先让变色和恢复都成功。平台消失、开门等效果,可以以后再给它升级。

第六站 · 给你的平台出几道题

当一回测试员:平台真的按规则工作吗?

看到平台变金色,确实挺开心。但测试员还要多问几句:普通方块碰到会怎样?连续走上去会怎样?恢复蓝色后还能用吗?我们给平台出几道题,每做一道,先说出自己猜的结果,再进游戏检查。猜错也有用,它会告诉你哪一步还没弄明白。

第一题,角色走上蓝色平台。你应该看到它变金色,Output 出现一条有效消息,然后平台变回蓝色。第二题,让普通小方块落到平台上。这个小方块的 Anchored 要关闭,CanTouch 要开启,并放在平台上方。Play 后让它真的落下来,角色站远一点,免得你自己也碰到平台。

不要只在编辑时把两个固定方块摆得相互穿进去,就认为完成了触碰测试。今天要观察的是运动带来的真实接触,所以角色要走上去,小方块要落下来。画面看着碰在一起,和物理系统发来一次新通知,是两件需要分别检查的事。

第三题,在平台变金色时制造新的接触。它还在忙,不该重新开始一轮等待。第四题,等它变蓝,走开再走回来,应该能再次启动。要看颜色,也要看 Output:颜色只告诉你眼前是什么样,消息能帮你判断函数有没有又执行一轮。

还有一道双人加分题:两位玩家先后碰同一块平台。A 先碰,B 趁平台还是金色时再碰。因为他们共用一个 busy,B 不会启动新的一轮。可以请老师带你用 Studio 的双人测试来验证。两个人一起发现问题,比一个人对着屏幕猜来猜去有意思多了。

下面的四张游戏场景图是 AI 生成的教学示意,帮助你提前想象结果,并不是实机截图。最后的裁判还是你自己的 Playtest。完成后按 Stop,保存 Lesson04。想换颜色或等待时间?每次只改一个地方,再试一次。这样就算出了问题,也容易找到是哪一步惹的祸。

当一回测试员:平台真的按规则工作吗?
给平台出的题你先猜一猜进入游戏后看什么
角色第一次碰蓝色平台找到了 Humanoid,可以开始变金色、出现有效消息,再变蓝色
普通小方块落到平台上没找到 Humanoid,这次结束平台仍为蓝色,没有有效启动消息
平台忙的时候又有新接触busy 是 true,先不接待继续当前这一轮,不重新等待
变蓝以后走开,再走回来平台不忙了,可以再开始再完成一次变金色和恢复
两位玩家在同一冷却内先后碰A 已经启动,B 这次先等等整块平台只运行当前这一轮
青色上衣与紫色上衣的两位角色先后踏上同一个金色 TouchPad,演示整块机关共用 busy 冷却。
运行场景 4 · 请排队!(AI 生成的教学示意,非实机截图):青色上衣的 A 先触发,紫色上衣的 B 在冷却时再碰。两人共用一个 busy,所以 B 不会让平台重新开始一轮。
想一想下一版:如果两个人各有自己的“请稍等”牌,会有什么不同?今天先把共用一块牌的版本测好,再带着这个问题去学后面的课。

Homework

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

1 给终点铺一块特别的地板

复制一块平台,改名 FinishPad,放在安全的终点位置。把 Anchored、CanCollide、CanTouch 都开启,再给它放入自己的普通 Script。

2 换一杯“绿色颜料”

把脚本命名为 FinishHandler,将 ACTIVE_COLOR 改成自己喜欢的绿色。READY_COLOR 仍设为蓝色,把等待时间改成大约两秒。

3 请测试员来验收

检查角色碰到会变绿,等一会儿会恢复;普通方块不启动;忙时不重复启动。先把颜色反馈做好,加分和通关记录留到后面的课。

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

Exit questions

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

函数已经写好了,为什么不会自己工作?

写好函数只是把动作包装好。要调用它,或者让事件来通知它,里面的动作才会执行。

Connect 后面为什么写 onPartTouched,不加一对括号?

我们要把整个函数交给事件,等触碰发生再调用。加括号会变成现在就调用,不是我们这里想做的事。

otherPart 是整个人吗?

不是。它是这次碰到平台的那个部件,可能是脚或腿,也可能是落下来的普通方块。

找到了 Humanoid,就一定是真人玩家吗?

不一定,NPC 也可能有 Humanoid。今天先识别带这个“小管家”的角色,第九课再学确认真人玩家。

busy=true 的时候,平台在说什么?

“请稍等,我正在忙。”新触碰先 return,等平台恢复颜色、busy 变回 false,再接下一次任务。

A 先踩上去,B 马上也踩上去,会各变一次色吗?

本课的平台共用一个 busy。A 开始的一轮还没结束,B 的新触碰会被拦住,不会再启动一轮。

我给平台画上金币图案,就会自动加分吗?

不会。外观可以自己设计,但加分还要写对应的规则。今天的平台只负责变色、留言、等待和恢复。

Explore further

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

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