iT邦幫忙

2025 iThome 鐵人賽

DAY 20
0

你有乖乖聽話沒把上次應用單元的檔案丟掉吧?
今天我們要為上一次做跑酷遊戲增添兩項關卡,分別為密碼門與找按鈕。


1. 密碼門

好的我們先把概念理清楚,我們要做一個可以讓玩家透過按下不同物件來輸入密碼的數字鍵,並且要在玩家輸入了指定密碼後將門的CanCollide設為false以及將Transparency設為1,並且在某處藏一個按鈕,當玩家按下按鈕後在玩家的畫面顯示一項UI,該UI會顯示當前密碼為何。

好的現在可以開始製作了,首先打開上次的專案
https://ithelp.ithome.com.tw/upload/images/20250831/20169664X54yZ3mPAW.png

接著建構密碼門關卡的各項模型,這裡你可以自由發揮創意
https://ithelp.ithome.com.tw/upload/images/20250831/20169664uheh7tdJHh.png

場景建置完成後,接著我們要來製作密碼門的模型,這裡我就以最簡單的方式來製作
https://ithelp.ithome.com.tw/upload/images/20250831/201696644lYkcQ78VT.png

接著我們來做各項物件的新增,首先是各個按鈕的文字,這邊要使用一項叫做SurfaceGui的物件,他跟ScreenGui類似,不過顯示的表面是物件的某一面,至於這個表面的位置可以在屬性頁面的Face屬性作更動,如果你看不到你放的UI那通常就是這個屬性把UI顯示到其他面了。
https://ithelp.ithome.com.tw/upload/images/20250831/20169664Ua33G9JycG.png

接下來SurfaceGui裡面的物件就跟ScreenGui的方法一樣,我就不細講了。總之新增好以後,我們要將所有按鈕物件新增一個ClickDetector,然後將密碼門的所有要素 (門、按鈕、輸出顯示)整理到一個Folder裡面,你可以把他們選取起來再按右鍵選擇組合成資料夾
https://ithelp.ithome.com.tw/upload/images/20250831/20169664OSZwe4usM3.png

然後各項物件的名稱也要做更改,這樣才可以避免等等在腳本中無法定義
https://ithelp.ithome.com.tw/upload/images/20250831/20169664VWN9XFcjfA.png

接下來,在Folder中新增一個Script (不可以是Local的),並完成以下定義

local Buttons = {}
local Delete = script.Parent:WaitForChild("Delete")
local Enter = script.Parent:WaitForChild("Enter")
local Output = script.Parent:WaitForChild("Output")
local Door = script.Parent:WaitForChild("Door")

在這邊我不會選擇把所有的數字按鈕定義出來,因為這樣太耗時間了,而且在後續的函式連接也會很麻煩,我採用的是透過for迴圈來取得所有按鈕,再透過過濾來取得所有數字按鈕。

接著定義出for迴圈與最終密碼

local Delete = script.Parent:WaitForChild("Delete")
local Enter = script.Parent:WaitForChild("Enter")
local Output = script.Parent:WaitForChild("Output")
local Door = script.Parent:WaitForChild("Door")

local FinalCode = "5312" --這個是最終密碼

for index, Button in pairs(script.Parent:GetChildren()) do
	if Button:FindFirstChild("ClickDetector") then
		if Button.Name == "Delete" then
            --這邊是過濾出來的按鈕,也就是刪除鍵
            continue --避免迴圈繼續進行,而導致這兩個按鍵也被視為可輸入的數字鍵
        end
        if Button.Name == "Enter" then 
            --而這邊則是確認鍵
            continue
        end
		--這邊是過濾過後的按鈕,也就是數字按鈕
	end
end

接下來,我們還要定義出一個字串變數,這項變數會儲存玩家的輸入

local Delete = script.Parent:WaitForChild("Delete")
local Enter = script.Parent:WaitForChild("Enter")
local Output = script.Parent:WaitForChild("Output")
local Door = script.Parent:WaitForChild("Door")

local FinalCode = "5312"
local InputCode = "" --這邊是玩家的輸入

for index, Button in pairs(script.Parent:GetChildren()) do
	if Button:FindFirstChild("ClickDetector") then
		if Button.Name == "Delete" then

            continue
        end
        if Button.Name == "Enter" then 

            continue
        end

	end
end

當然,你可以直接把Output物件顯示的字當成儲存玩家輸入的變數,但為了嚴謹一點,我還是會在腳本裡多定義一個變數

現在,我們先來做一般數字鍵的按下事件與連接函式

local Delete = script.Parent:WaitForChild("Delete")
local Enter = script.Parent:WaitForChild("Enter")
local Output = script.Parent:WaitForChild("Output")
local Door = script.Parent:WaitForChild("Door")

local FinalCode = "5312"
local InputCode = ""

for index, Button in pairs(script.Parent:GetChildren()) do
	if Button:FindFirstChild("ClickDetector") then
		if Button.Name == "Delete" then

            continue
        end
        if Button.Name == "Enter" then 

            continue
        end
		Button:WaitForChild("ClickDetector").MouseClick:Connect(function(Player) --這個你熟
			InputCode = InputCode..Button.Name --將玩家的輸入儲存到變數,輸入的值就是這項物件的名稱
			Output.SurfaceGui.TextLabel.Text = InputCode --接著把變數值更新到物件上
		end)
	end
end

然後來做刪除鍵

local Delete = script.Parent:WaitForChild("Delete")
local Enter = script.Parent:WaitForChild("Enter")
local Output = script.Parent:WaitForChild("Output")
local Door = script.Parent:WaitForChild("Door")

local FinalCode = "5312"
local InputCode = ""

for index, Button in pairs(script.Parent:GetChildren()) do
	if Button:FindFirstChild("ClickDetector") then
		if Button.Name == "Delete" then
			Button:WaitForChild("ClickDetector").MouseClick:Connect(function(Player)
				InputCode = "" --把儲存的值清空
				Output.SurfaceGui.TextLabel.Text = "" --把顯示的值也清空
			end)
            continue
        end
        if Button.Name == "Enter" then 

            continue
        end
		Button:WaitForChild("ClickDetector").MouseClick:Connect(function(Player)
			InputCode = InputCode..Button.Name
			Output.SurfaceGui.TextLabel.Text = InputCode
		end)
	end
end

最後是確認鍵

local Delete = script.Parent:WaitForChild("Delete")
local Enter = script.Parent:WaitForChild("Enter")
local Output = script.Parent:WaitForChild("Output")
local Door = script.Parent:WaitForChild("Door")

local FinalCode = "5312"
local InputCode = ""

for index, Button in pairs(script.Parent:GetChildren()) do
	if Button:FindFirstChild("ClickDetector") then
		if Button.Name == "Delete" then
			Button:WaitForChild("ClickDetector").MouseClick:Connect(function(Player)
				InputCode = ""
				Output.SurfaceGui.TextLabel.Text = ""
			end)
            continue
        end
        if Button.Name == "Enter" then 
			Button:WaitForChild("ClickDetector").MouseClick:Connect(function(Player)
				if InputCode == FinalCode then --先判斷密碼是否正確
					print("密碼正確")
                    --這邊以下都是更改屬性值,你再熟悉不過了
					Door.CanCollide = false
					Door.Transparency = 1
					task.wait(2) --等個兩秒在回復
					Door.CanCollide = true
					Door.Transparency = 0
				else --那如果密碼不正確
					print("密碼錯誤")
				end
                --然後不論正確錯誤都把輸入值清空
				InputCode = ""
				Output.SurfaceGui.TextLabel.Text = ""
			end)
            continue
        end
		Button:WaitForChild("ClickDetector").MouseClick:Connect(function(Player)
			InputCode = InputCode..Button.Name
			Output.SurfaceGui.TextLabel.Text = InputCode
		end)
	end
end

接著進入遊戲看看是否正確執行
https://media4.giphy.com/media/v1.Y2lkPTc5MGI3NjExZXA5bXd0Z3Y4aDZreGFyeW83N2Zucm11dGIxcDJmZ2JseHhuazF2OCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/Ab1v3abCKhmaOgPkx9/giphy.gif

接下來,我們要製作一個小提示按鈕。照慣例,先把按鈕的模型跟位置放好
https://ithelp.ithome.com.tw/upload/images/20250831/201696648RHqlNSfir.png

然後看你想用哪種觸發方式,反正忘記了可以看昨天的單元,這邊我就一樣用CLickDetector
嘿對然後腳本一樣要新增
https://ithelp.ithome.com.tw/upload/images/20250831/20169664ZwJyTbrPT8.png

各項定義還有函式連接先做好

local Part = script.Parent
local ClickDetector = Part:WaitForChild("ClickDetector")

ClickDetector.MouseClick:Connect(function(Player)

end)

接著,取得玩家的PlayerGui

local Part = script.Parent
local ClickDetector = Part:WaitForChild("ClickDetector")

ClickDetector.MouseClick:Connect(function(Player)
    local PlayerGui = Player.PlayerGui
end)

然後關閉腳本,我們來製作UI
這部分你就自己發揮,我就先做一個簡單的
https://ithelp.ithome.com.tw/upload/images/20250831/2016966494NYts8O3z.png

回到腳本,把我們剛剛新增的UI顯示,然後等待一秒後再隱藏

local Part = script.Parent
local ClickDetector = Part:WaitForChild("ClickDetector")

ClickDetector.MouseClick:Connect(function(Player)
	local PlayerGui = Player.PlayerGui
	PlayerGui.ScreenGui:WaitForChild("TextLabel").Visible = true
	task.wait(1)
	PlayerGui.ScreenGui:WaitForChild("TextLabel").Visible = false
end)

2. 找按鈕

這部分我想要用一個迷宮,讓玩家在迷宮裡找按鈕,玩家找到按鈕後再把玩家傳送到下一關卡的位置

首先先做一個迷宮,你懶的話可以直接用ToolBox的
https://ithelp.ithome.com.tw/upload/images/20250831/20169664tHrxwvGr0b.png

然後放按鈕
https://ithelp.ithome.com.tw/upload/images/20250831/20169664KZME06FpLu.png

接下來進入腳本,然後一樣定義跟事件連接

local Part = script.Parent
local ClickDetector = Part:WaitForChild("ClickDetector")

ClickDetector.MouseClick:Connect(function(Player)

end)

但現在,我們要傳送玩家,回到地點,接著新增一個Part來代表玩家的位置 (記得關碰撞跟隱藏)
https://ithelp.ithome.com.tw/upload/images/20250831/20169664IApHNUip9J.png

然後在腳本裡新增傳送的指令

local Part = script.Parent
local ClickDetector = Part:WaitForChild("ClickDetector")

ClickDetector.MouseClick:Connect(function(Player)
    --說是傳送,其實就只是改變CFrame而已
    Player.Character:WaitForChild("HumanoidRootPart").CFrame = workspace:WaitForChild("PlayerPosition").CFrame
end)

進入遊戲測試
https://media4.giphy.com/media/v1.Y2lkPTc5MGI3NjExbDh0dDE1MGU1c3cyeWpudG5kOGV1MWs0c3Aya280MDEzN2ltcXN3MCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/8eBjIDBpKcgs5osNiW/giphy.gif


拜託不要把這個檔案刪掉欸


上一篇
Day 19: 玩家觸發事件
下一篇
Day 21: 外部變數與Changed事件
系列文
透過Roblox Studio學習Lua語言與基本程式邏輯21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言