iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0
Software Development

Roblox Studio AI 協作開發大全系列 第 9

第 9 章:第一次讓 Assistant 寫 Script

  • 分享至 

  • xImage
  •  

本章目標

第三部開始,AI Adventure Island 要從「場景裡有互動元件」進入「互動背後有遊戲邏輯」。

第 8 章你已經建立了第一批互動入口:

  • NPC 有 ProximityPrompt
  • 寶箱有 ProximityPrompt
  • 水晶可以用 Touched 做最小回饋。

但你還沒有真正理解 Assistant 產生的 Script。

這一章要做的事很單純:讓 Crystal_01Crystal_03 成為第一批由 Script 控制的可收集物。

玩家碰到水晶時:

  • Script 判斷碰到水晶的是不是玩家。
  • Output 印出玩家名稱與水晶名稱。
  • 水晶暫時變透明並停用觸碰。
  • 幾秒後水晶恢復。

本章不做完整分數。

本章不做背包。

本章不做任務進度。

這些都會在後面章節逐步加入。

本章的重點是讀懂第一個 Script:

物件在哪裡
Script 放在哪裡
事件何時觸發
function 做了什麼
Output 如何驗證
錯誤如何回到 Assistant 修正

Assistant 將生成的 Script 插入選取物件。

圖 9-1 Assistant 可把 Script 插入 DataModel;執行前應先確認程式內容、父層位置與 server/client 執行環境。

Context Pack

本章依據以下 Roblox 官方文件撰寫:

官方 scripting 文件把 Script 定義得很直接:Script 是純文字檔,用 Luau 替遊戲加入自訂、動態行為。

官方 script locations 文件則提醒:在 Roblox 裡,Script 的位置很重要。因為 Roblox 遊戲預設是 multiplayer,程式可能跑在 server,也可能跑在 client。

本章只使用 server-side Script,並放在:

ServerScriptService

原因是:

  • 這是伺服器端遊戲邏輯。
  • 玩家不應該直接控制水晶是否被收集。
  • ServerScriptService 的內容不會複製到 client。
  • 對第一個 Script 來說,位置清楚比架構複雜更重要。

Output 是本章另一個重點。

在你還不熟 Luau 時,print() 和 Output 是最直接的觀察工具。

本章會把 Output 當成 AI 生成後的第一個驗證點。

開場情境

目前你的 Explorer 大致有:

Workspace
  AdventureIsland
    Collectibles
      Crystal_01
      Crystal_02
      Crystal_03
    Interactables
      Chest_Starter
    NPCs
      NPC_QuestGiver_Placeholder
    World
      Blockout_Parts
      Visuals
      ProceduralModels

ServerScriptService
  InteractionPrototype

第 8 章的 InteractionPrototype 可能已經有水晶碰撞 prototype。

這章會把水晶收集行為整理成更清楚的 Script。

建議命名為:

CrystalCollectionService

雖然現在它還不是完整 service 架構,但這個名稱比 ScriptCrystalScriptTouchScript 更清楚。

本章要保留一個界線:

現在只處理水晶收集行為。
NPC、寶箱、任務、分數、UI 都先不混進來。

這是學習 Script 時最重要的控制。

如果第一個 Script 同時做太多事,讀者會不知道自己是在學事件、資料、UI、任務,還是在修 AI 亂生成的架構。

第一個 Prompt

請在 Assistant 輸入:

【Ch09 主任務|建立第一支 Script】
我正在製作 Roblox Studio 專案 AI Adventure Island。

目前 Workspace.AdventureIsland.Collectibles 裡有:
- Crystal_01
- Crystal_02
- Crystal_03

請幫我建立第一個正式可讀的 server Script,用來處理水晶收集 prototype。

要求:
1. 在 ServerScriptService 建立 Script,名稱為 CrystalCollectionService。
2. Script 只處理 Crystal_01 到 Crystal_03 的 Touched 行為。
3. 玩家碰到水晶時:
   - 確認觸碰的是玩家角色。
   - 在 Output 印出玩家名稱與水晶名稱,例如 "Wolke collected Crystal_01"。
   - 將該水晶 Transparency 設為 1。
   - 將該水晶 CanTouch 設為 false,避免短時間重複觸發。
   - 等待 5 秒。
   - 將 Transparency 設回 0。
   - 將 CanTouch 設回 true。
4. 使用 Players:GetPlayerFromCharacter() 判斷玩家。
5. 使用 WaitForChild() 取得 AdventureIsland 和 Collectibles。
6. 不要建立 leaderstats、背包、任務、UI、RemoteEvent 或 DataStore。
7. 請在程式中加入少量清楚註解,讓初學者能看懂。

完成後請:
- 貼出完整 Script。
- 解釋 Script 應該放在哪裡。
- 逐段解釋 local 變數、function、Touched:Connect、print、task.wait。
- 告訴我 Playtest 時 Output 應該看到什麼。

這個 prompt 的目標不是讓 Assistant 寫最多功能。

它的目標是讓 Assistant 寫一段可教學、可讀、可測的 Script。

注意幾個限制:

  • 不建立分數。
  • 不建立 UI。
  • 不建立 RemoteEvent。
  • 不建立 DataStore。
  • 只處理三顆水晶。

這些限制是本書的核心方法。

AI 可以一次生成很多功能,但你要把學習順序切小。

Assistant 可能產生的結果

Assistant 可能產生類似這段 Script:

local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")

local adventureIsland = Workspace:WaitForChild("AdventureIsland")
local collectibles = adventureIsland:WaitForChild("Collectibles")

local RESPAWN_SECONDS = 5

local function onCrystalTouched(crystal, otherPart)
	local character = otherPart.Parent
	local player = Players:GetPlayerFromCharacter(character)

	if not player then
		return
	end

	if not crystal.CanTouch then
		return
	end

	print(player.Name .. " collected " .. crystal.Name)

	crystal.Transparency = 1
	crystal.CanTouch = false

	task.wait(RESPAWN_SECONDS)

	crystal.Transparency = 0
	crystal.CanTouch = true
end

for _, crystal in collectibles:GetChildren() do
	if crystal:IsA("BasePart") then
		crystal.CanTouch = true
		crystal.Touched:Connect(function(otherPart)
			onCrystalTouched(crystal, otherPart)
		end)
	end
end

你的結果不一定完全相同。

但它應該具備這些元素:

Players service
Workspace service
WaitForChild()
RESPAWN_SECONDS
onCrystalTouched()
Players:GetPlayerFromCharacter()
print()
Transparency
CanTouch
task.wait()
Touched:Connect()

如果 Assistant 直接建立 leaderstatsRemoteEventScreenGuiDataStoreService,先不要接受。

你可以要求它縮小範圍:

請把 Script 縮回水晶收集 prototype。不要做分數、UI、RemoteEvent 或 DataStore。

本章的好 Script 應該短到你可以逐行讀完。

元件拆解

Script 放在哪裡

本章的 Script 應該放在:

ServerScriptService
  CrystalCollectionService

官方文件說明,ServerScriptService 是 server-only Script container,內容不會複製到玩家 client。這讓它適合放重要遊戲邏輯。

Script 的 Properties 視窗顯示 RunContext 設定。

圖 9-2 除了 Script 放置位置,也要檢查 RunContext;執行環境錯誤時,程式可能完全不跑,或只在錯誤的一側執行。

水晶收集是 server-side 行為。

原因是:

  • 玩家是否收集到水晶應該由 server 判斷。
  • 水晶是否暫時消失應該讓所有玩家看見。
  • 後面加分數、任務、存檔時,也會需要 server authority。

如果 Script 放在錯誤地方,可能發生:

  • Script 根本不執行。
  • Script 只在 client 執行。
  • Script 找不到 server-only 物件。
  • 多人遊戲時狀態不一致。

初學者常以為「有寫 Script 就會跑」。

Roblox 不是這樣。

Script 的位置是行為的一部分。

取得 Services 與物件

程式一開始通常會取得需要的 services:

local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")

game:GetService() 會取得 Roblox 內建 service。

本章用到兩個:

  • Players:用來判斷觸碰水晶的是不是玩家角色。
  • Workspace:用來找到場景中的 AdventureIsland

接著取得本章需要的資料夾:

local adventureIsland = Workspace:WaitForChild("AdventureIsland")
local collectibles = adventureIsland:WaitForChild("Collectibles")

WaitForChild() 的意思是等待指定 child 出現,再繼續執行。

這比直接寫:

local collectibles = Workspace.AdventureIsland.Collectibles

更穩。

在 Roblox 中,物件載入和複製有時機問題。即使本章跑在 server,用 WaitForChild() 也能讓第一個 Script 更不容易因為找不到物件而出錯。

本章你不需要理解所有 replication 細節。

先記住:

Script 要操作某個物件,先清楚取得它。

local 變數與常數

這行:

local RESPAWN_SECONDS = 5

是本章第一個簡單常數。

local 表示這個變數只在目前 Script 範圍內使用。

RESPAWN_SECONDS 用大寫,是一種常見寫法,用來表示這個值像設定值,不應該在流程中隨意改來改去。

如果之後想把水晶恢復時間從 5 秒改成 10 秒,只要改這裡:

local RESPAWN_SECONDS = 10

不要把 5 散落在整段程式裡。

這是第一次接觸「可維護」的寫法。

AI 生成的程式能跑,不代表好維護。

你要開始學會要求 Assistant 把重要數值拉成清楚名稱。

function

這段是事件發生後要執行的邏輯:

local function onCrystalTouched(crystal, otherPart)
	local character = otherPart.Parent
	local player = Players:GetPlayerFromCharacter(character)

	if not player then
		return
	end

	if not crystal.CanTouch then
		return
	end

	print(player.Name .. " collected " .. crystal.Name)

	crystal.Transparency = 1
	crystal.CanTouch = false

	task.wait(RESPAWN_SECONDS)

	crystal.Transparency = 0
	crystal.CanTouch = true
end

function 是一段可以被呼叫的程式。

這裡命名為:

onCrystalTouched

這個名稱很好,因為它說明了觸發情境:水晶被碰到時。

參數有兩個:

crystal
otherPart

crystal 是哪一顆水晶。

otherPart 是碰到水晶的 Part。這個 Part 可能是玩家角色的一部分,也可能不是玩家。

所以程式先做判斷:

local character = otherPart.Parent
local player = Players:GetPlayerFromCharacter(character)

if not player then
	return
end

GetPlayerFromCharacter() 用來從角色 Model 找到對應的 Player。

如果找不到 player,就代表這次碰撞不是玩家造成的,function 直接 return

這是第一個安全觀念:

不要假設每次 Touched 都是玩家。

Touched:Connect

最後這段會替每顆水晶接上事件:

for _, crystal in collectibles:GetChildren() do
	if crystal:IsA("BasePart") then
		crystal.CanTouch = true
		crystal.Touched:Connect(function(otherPart)
			onCrystalTouched(crystal, otherPart)
		end)
	end
end

collectibles:GetChildren() 取得 Collectibles 裡的所有 child。

for _, crystal in ... do 代表逐一處理每個 child。

crystal:IsA("BasePart") 是檢查它是不是可以被觸碰的 3D part 類型。

然後這一行最重要:

crystal.Touched:Connect(function(otherPart)
	onCrystalTouched(crystal, otherPart)
end)

可以讀成:

當 crystal 的 Touched event 發生時,
呼叫這個 function,
並把碰到它的 otherPart 傳進來。

這就是事件驅動。

不是程式一直問「玩家有沒有碰到水晶」。

而是 Roblox 偵測到碰撞後,觸發 Touched,再執行你連接的 function。

Output 與 print

這行是本章的第一個驗證點:

print(player.Name .. " collected " .. crystal.Name)

當玩家碰到水晶時,Output 應該出現類似:

Wolke collected Crystal_01

官方 Output 文件說明,Output 會顯示 errors、engine messages、print()warn()

本章請打開 Output,並建議啟用:

Show Context
Show Source

這樣你會更容易知道訊息來自 server 還是 client,以及哪個 Script 行號。

對 AI 生成工作流來說,Output 是你和 Assistant 溝通的證據。

不要只說:

水晶壞了。

要說:

Playtest 時碰到 Crystal_01,Output 沒有印出訊息。
或 Output 顯示 ServerScriptService.CrystalCollectionService 第 12 行錯誤。

這會讓 Assistant 修正得更準。

Playtest

第一次用 Output 驗證 Script

現在進入 Play mode。

測試步驟:

1. 打開 Output。
2. 確認 Output 已清空。
3. 玩家走向 Crystal_01。
4. 讓角色碰到 Crystal_01。
5. 觀察 Output。
6. 等待 5 秒。
7. 確認 Crystal_01 是否恢復。
8. 重複測 Crystal_02 和 Crystal_03。

預期結果:

PlayerName collected Crystal_01
PlayerName collected Crystal_02
PlayerName collected Crystal_03

視覺上:

  • 水晶被碰到後應該暫時消失。
  • 消失期間不應該連續觸發一堆 Output。
  • 5 秒後水晶恢復。

如果水晶沒有消失,但 Output 有訊息,代表事件成功,視覺狀態可能沒改對。

如果水晶消失,但 Output 沒有訊息,代表可能沒有執行到 print(),或 Output filter 隱藏了訊息。

如果完全沒有反應,先檢查:

  • Script 是否在 ServerScriptService
  • Script 是否 Enabled=true
  • AdventureIsland 名稱是否正確。
  • Collectibles 名稱是否正確。
  • 水晶是否是 BasePart
  • 水晶 CanTouch 是否為 true。

不要一開始就重寫整段 Script。

先確認哪個假設錯了。

修正 Prompt

如果 Script 沒有執行,用:

【Ch09 修正 1|診斷水晶沒有輸出】
我 Playtest 後碰到 Crystal_01,Output 完全沒有訊息。

目前 Script 名稱是 CrystalCollectionService,位置在 ServerScriptService。

請幫我檢查可能原因:
1. Script 是否應該放在 ServerScriptService。
2. Script 是否 Enabled。
3. 是否有正確使用 Workspace:WaitForChild("AdventureIsland")。
4. 是否有正確取得 Collectibles。
5. 是否有替 Crystal_01 到 Crystal_03 連接 Touched event。

請不要新增 leaderstats、UI、RemoteEvent 或 DataStore。
請只修正這個水晶收集 prototype。

如果 Output 有錯誤,用:

【Ch09 修正 2|分析水晶 Script 錯誤】
Playtest 時 Output 顯示這個錯誤:

###
貼上完整錯誤訊息,包含 Script 名稱與行號
###

這是目前 CrystalCollectionService 的程式:

###
貼上目前 Script
###

請:
1. 解釋錯誤原因。
2. 指出是哪一行造成。
3. 修正 Script。
4. 保持功能範圍不變:只處理 Crystal_01 到 Crystal_03 的 Touched prototype。
5. 不要新增其他系統。

如果水晶重複觸發,用:

【Ch09 修正 3|限制水晶重複觸發】
玩家碰到 Crystal_01 時,Output 連續印出很多次。

請在 CrystalCollectionService 裡加入最小 debounce。
要求:
1. 每顆水晶被收集後,立刻 CanTouch=false。
2. 5 秒後才恢復 CanTouch=true。
3. 不要使用全域單一 debounce,避免 Crystal_01 影響 Crystal_02。
4. 請解釋每顆水晶如何各自管理狀態。

如果 Assistant 生成太複雜,用:

【Ch09 修正 4|簡化水晶 Script】
請把這段 Script 簡化成第 9 章教學用版本。

保留:
- Players:GetPlayerFromCharacter()
- Touched:Connect()
- print()
- Transparency
- CanTouch
- task.wait(5)

移除或不要使用:
- leaderstats
- DataStore
- RemoteEvent
- UI
- 任務系統
- 背包系統

請貼出簡化後完整 Script,並逐段解釋。

修 bug 時,把 Output 當作證據。

AI 不在你的 Studio 裡看 Playtest 結果。你要把錯誤訊息、目前 Script、預期行為一起提供。

工程整理

完成本章後,建議 Explorer 結構如下:

Workspace
  AdventureIsland
    Collectibles
      Crystal_01
      Crystal_02
      Crystal_03

ServerScriptService
  CrystalCollectionService

如果第 8 章留下 InteractionPrototype,現在有兩種做法:

做法 A:把水晶相關程式搬到 CrystalCollectionService,InteractionPrototype 只保留 NPC/Chest prototype。
做法 B:如果 InteractionPrototype 只剩水晶程式,改名為 CrystalCollectionService。

不要同時留下兩段水晶 Touched 程式。

否則你可能會看到:

  • Output 印兩次。
  • 水晶狀態互相覆蓋。
  • 一段 Script 修好了,另一段仍然造成錯誤。

本章整理清單:

Script name: CrystalCollectionService
Location: ServerScriptService
Scope: Crystal_01 到 Crystal_03
Behavior: touch -> print -> hide -> wait -> restore
Not included: score, backpack, quest, UI, save
Verified by: Output message and visual disappear/restore

這份整理會成為第 10 章的起點。

第 10 章會開始處理玩家資料與狀態。到時候你會把「玩家碰到水晶」從 Output 訊息推進到真正的數值變化。

本章總結

這一章,你第一次讓 Assistant 寫出正式可讀的 Script-driven 行為。

你學到:

  • Script 是 Luau 程式,用來替遊戲加入動態行為。
  • Script 放置位置會影響是否執行,以及跑在 server 還是 client。
  • ServerScriptService 適合放 server-side 遊戲邏輯。
  • game:GetService() 用來取得 Roblox services。
  • WaitForChild() 用來穩定取得場景物件。
  • Touched:Connect() 把事件和 function 接起來。
  • Players:GetPlayerFromCharacter() 可以判斷碰撞是否來自玩家。
  • print() 和 Output 是第一個驗證工具。
  • AI 生成 Script 後,作者必須用 Playtest 和 Output 驗證,而不是只看程式是否像樣。

到這裡,AI Adventure Island 已經有第一個真正由 Script 驅動的遊戲行為。

下一章,我們會在這個基礎上建立玩家資料與狀態:讓收集水晶不只是印出訊息,而是能累積成玩家可見、可管理的數值。


關於 Wolke

嗨!我是 Wolke,曾任 Google Developer Expert(GDE,2019–2023)LINE API Expert

我熱衷於研究 AI Agent、n8n 自動化工作流與全端開發架構,致力於將 AI 技術轉化為真正能落地的生產力工具。

如果你喜歡這篇文章,歡迎透過以下方式與我交流:

📚 技術著作
《實用的 Gemini API 開發點子書》:帶你運用 Gemini App、Google AI Studio、Gemini CLI 與 Antigravity IDE,打造 AI Agent 與實用產品。

📝 技術部落格
歡迎追蹤我的 Medium,我會持續分享 Agentic Automation、架構設計與實際開發的踩坑心得。

🎤 技術講座與合作
我持續受邀至技術社群及研討會,分享 AI Agent、自動化工作流、DevOps 與全端開發實戰。

我曾於 DevOpsDays Taipei 2026 主講「不再只是寫腳本!讓 AI 代理人成為你的 SRE 最佳夥伴」工作坊。

如果你的企業、社群或學校正在尋找相關主題講者,歡迎私訊聯繫,洽談講座與工作坊合作!

🎮 我的 Roblox 遊戲

🎁 免費贈送 OpenAI 或 Claude AI 額度

為了鼓勵大家實際動手打造自己的 Roblox 體驗,我每個月會開放:

  • 10 個名額
  • 每人 50 點 AI 額度
  • 名額送完為止

參加方式:

  1. 訂閱本系列文章。
  2. 分享任一篇系列文章。
  3. 私訊分享截圖及你的 AI 帳號 Email。

確認完成後,我會邀請你加入並設定 50 點額度。名額有限,歡迎把握機會!


上一篇
第 8 章:讓場景有互動
系列文
Roblox Studio AI 協作開發大全9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言