การทำให้เกมมีความโต้ตอบมักหมายถึงการจัดการคุณสมบัติและแอตทริบิวต์ของวัตถุ:
คุณสมบัติเป็นส่วนหนึ่งของคลาสวัตถุ ตัวอย่างเช่น คุณสมบัติ BasePart.Anchored ควบคุมฟิสิกส์สำหรับส่วน ในเกมกรีฑา คุณอาจต้องการให้ดิสก์หรือหอกยึดทันทีที่ลงพื้นเพื่อให้ผู้เล่นมีตัวชี้วัดทางสายตามว่าได้เคลื่อนที่ไปไกลแค่ไหน
แอตทริบิวต์เป็นเพียงคุณสมบัติที่กำหนดเองที่คุณสร้างขึ้น ตัวอย่างเช่น โครงการอ้างอิง Plant ใช้แอตทริบิวต์ในการตั้งราคาในการซื้อเมล็ดพันธุ์และขนาดสูงสุดของพืชที่กระถางสามารถรองรับได้
ลำดับการทำซ้ำ
ก่อนที่คุณจะเริ่มดึงและจัดการวัตถุ คุณต้องเข้าใจลำดับการทำซ้ำ
เอนจิน Roblox ไม่รับประกันลำดับที่วัตถุ (และการเปลี่ยนแปลงต่อวัตถุ) จะถูกทำซ้ำจากเซิร์ฟเวอร์ไปยังไคลเอนต์ ซึ่งทำให้วิธี Instance:WaitForChild() เป็นสิ่งจำเป็นสำหรับการเข้าถึงวัตถุในสคริปต์ของไคลเอนต์ โดยเฉพาะวัตถุใน Workspace
ตัวอย่างเช่น หากสคริปต์เซิร์ฟเวอร์เปลี่ยนคุณสมบัติของตัวอย่างบางตัวใน Workspace และจากนั้นเรียก RemoteEvent:FireAllClients() การเปลี่ยนแปลงคุณสมัติอาจทำซ้ำไปยังไคลเอนต์ก่อนหรือหลังจากที่ RemoteEvent.OnClientEvent ถูกเรียก ใช้เมธอดและอีเวนต์ที่มีอยู่เพื่อ ตรวจจับการเปลี่ยนแปลง แทนที่จะสมมุติว่าการเปลี่ยนแปลงได้ทำซ้ำแล้ว การเปลี่ยนแปลงของประเภทเดียวกัน เช่น การเปลี่ยนแปลงของแอตทริบิวต์สองรายการ โดยทั่วไปจะ ทำ มาถึงในลำดับ
เมื่อไคลเอนต์เริ่มเล่นเกมในครั้งแรก บางแง่มุมของการทำซ้ำและการดำเนินการสคริปต์จะคาดการณ์ได้:
ไคลเอนต์จะโหลดเนื้อหาของ ReplicatedFirst เช่น หน้าจอโหลด สื่อ และสคริปต์
LocalScripts (และ Scripts ที่มี RunContext เป็น Client) ใน ReplicatedFirst จะทำงาน สคริปต์เหล่านี้สามารถดึงวัตถุจาก ReplicatedFirst ได้อย่างปลอดภัยโดยไม่ใช้ Instance:WaitForChild():
-- ปลอดภัยlocal ReplicatedFirst = game:GetService("ReplicatedFirst")local LoadingScreen = require(ReplicatedFirst.LoadingScreen)สคริปต์เหล่านี้ ไม่สามารถ ดึงวัตถุจากบริการอื่นๆ ได้อย่างปลอดภัย (services.md) เพราะอาจยังไม่โหลด:
-- ไม่ปลอดภัยlocal ReplicatedStorage = game:GetService("ReplicatedStorage")local PickupManager = require(ReplicatedStorage.PickupManager)คุณ สามารถ ใช้ WaitForChild() ในสคริปต์เหล่านี้เพื่อดึงวัตถุจากบริการอื่นๆ แต่การทำเช่นนี้จะทำให้คุณประโยชน์ของการใช้ ReplicatedFirst สูญเสียไป
ไคลเอนต์จะโหลดส่วนที่เหลือของเกมต่อไป
เมื่อมันเสร็จสิ้น ก็จะมีการเรียกอีเวนต์ Loaded และ IsLoaded() จะคืนค่าเป็นจริง
LocalScripts ใน Players.[Player].PlayerScripts (คัดลอกมาจาก StarterPlayerScripts) จะทำงาน เช่นเดียวกับสคริปต์ไคลเอนต์ Scripts ใน ReplicatedStorage สคริปต์เหล่านี้สามารถดึงวัตถุจาก ReplicatedStorage ได้อย่างปลอดภัยโดยไม่ใช้ WaitForChild()
โมเดลของผู้เล่น Character จะถูกสร้างในเกม
LocalScripts ใน Workspace.[Character] (คัดลอกมาจาก StarterCharacterScripts) จะทำงาน
หากเกมของคุณใช้ instance streaming (Workspace.StreamingEnabled) วัตถุบางอย่างหรือส่วนใหญ่ อาจยังไม่โหลดเข้ามาใน Workspace ดังนั้นการใช้ WaitForChild() เพื่อเข้าถึงวัตถุใน Workspace จึงเป็นมาตรการความปลอดภัยที่สำคัญยิ่ง โดยเฉพาะอย่างยิ่ง ให้ดู stream in และ การควบคุมการสตรีมแบบต่อโมเดล เพื่อรับข้อมูลเพิ่มเติมเกี่ยวกับการโหลดและการปรับพฤติกรรมการสตรีม
ดึงวัตถุ
ขั้นตอนแรกในการปรับปรุงคุณสมบัติและแอตทริบิวต์ของวัตถุ คือการอ้างอิงถึงวัตถุ วิธีที่ง่ายที่สุดคือการทำให้สคริปต์เป็นลูกของวัตถุใน Explorer และใช้ script.Parent เพื่ออ้างอิงถึงวัตถุ

local sign = script.Parent
วิธีที่มีความเป็นสากลมากขึ้นคือการดึงวัตถุจาก บริการ โดยใช้วิธีต่างๆ เช่น Instance:FindFirstChild() หรือ Instance:WaitForChild()

local ReplicatedStorage = game:GetService("ReplicatedStorage")local signsFolder = ReplicatedStorage:WaitForChild("Signs")local sign = signsFolder:WaitForChild("InteractiveSign")
ปรับปรุงคุณสมบัติ
คุณสมบัติสามารถเข้าถึงได้ง่าย — เพียงใช้ . หลังจากการอ้างอิงวัตถุ — แม้ว่าถ้าคุณกำลังทำงานกับโมเดล คุณอาจต้องเลือกรายละเอียดเฉพาะแทนที่จะเป็นโมเดลเอง

local ReplicatedStorage = game:GetService("ReplicatedStorage")local chair = ReplicatedStorage:WaitForChild("Chair")chair.LeftArmRest.Size = Vector3.new(10, 1, 10)
สร้างแอตทริบิวต์
แม้ว่าคุณสามารถสร้างแอตทริบิวต์ได้โดยโปรแกรม แต่โซลูชันที่ใช้บ่อยกว่าคือการสร้างด้วยค่าพื้นฐานในอินเทอร์เฟซ Studio จากนั้นคุณสามารถใช้สคริปต์ในการปรับปรุงค่าของพวกเขาเพื่อตอบสนองต่อการกระทำของผู้เล่น

สำหรับข้อมูลเกี่ยวกับการสร้างแอตทริบิวต์ใน Studio โปรดดูที่ แอตทริบิวต์อินสแตนซ์
ตั้งค่าแอตทริบิวต์
ในการปรับปรุงค่าของแอตทริบิวต์ ให้เรียกใช้ Instance:SetAttribute() พร้อมชื่อและค่า
สร้างหรือปรับปรุงแอตทริบิวต์local cabbage = script.Parentcabbage:SetAttribute("Harvestable", true)
หากแอตทริบิวต์ยังไม่มีอยู่ วิธีนี้จะสร้างมันขึ้นมา
ดึงค่าแอตทริบิวต์
ในการดึงค่าของแอตทริบิวต์ที่มีอยู่หนึ่งรายการ ให้เรียกใช้ Instance:GetAttribute() บนสแตนซ์
ดึงค่าของแอตทริบิวต์local cabbage = script.Parentcabbage:SetAttribute("Harvestable", true)local isHarvestable = cabbage:GetAttribute("Harvestable")print(isHarvestable) --> true
ในลักษณะเดียวกัน คุณสามารถดึงแอตทริบิวต์ทั้งหมดได้โดยเรียกใช้ Instance:GetAttributes() วิธีนี้จะส่งกลับดิกชันนารีของคู่คีย์-ค่า
ดึงแอตทริบิวต์ทั้งหมดlocal cabbage = script.Parentlocal cabbageAttributes = cabbage:GetAttributes()print(cabbageAttributes.GrowthRate) --> 2for k, v in cabbageAttributes doprint(k, v)end
ลบแอตทริบิวต์
ในการลบแอตทริบิวต์ ให้ตั้งค่าของมันเป็น nil
ลบแอตทริบิวต์local cabbage = script.Parentcabbage:SetAttribute("GrowthRate", nil)
ตรวจจับการเปลี่ยนแปลง
มีหลายวิธีในการฟังการเปลี่ยนแปลงคุณสมบัติและแอตทริบิวต์:
- อีเวนต์ Instance.AttributeChanged จะฟังการเปลี่ยนแปลงใดๆ ต่อแอตทริบิวต์และส่งชื่อของแอตทริบิวต์ที่เปลี่ยนแปลงเป็นพารามิเตอร์
- วิธี Instance:GetPropertyChangedSignal() ให้คุณฟังการเปลี่ยนแปลงของคุณสมบัติหนึ่งรายการและไม่ส่งพารามิเตอร์
- วิธี Instance:GetAttributeChangedSignal() ให้คุณฟังการเปลี่ยนแปลงของแอตทริบิวต์หนึ่งรายการและไม่ส่งพารามิเตอร์
เนื่องจากข้อมูลที่น้อยมากที่อีเวนต์และวิธีเหล่านี้ส่งเป็นพารามิเตอร์ ทั้งหมดจึงเหมาะอย่างยิ่งสำหรับฟังก์ชันนิรนาม โดยเฉพาะอย่างยิ่ง Instance:GetPropertyChangedSignal() และ Instance:GetAttributeChangedSignal() เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับฟังก์ชันนิรนามและการทำงานกับอีเวนต์ ให้ดูที่ อีเวนต์
ฟังการเปลี่ยนแปลง
local cabbage = script.Parent
-- ฟังก์ชันในท้องถิ่น
local function onAnyPropertyChange(property)
-- ข้ามการเปลี่ยนแปลงของแอตทริบิวต์
if property ~= "Attributes" then
print(property) --> Name
print(cabbage[property]) --> Cabbage1
end
end
local function onAnyAttributeChange(attribute)
print(attribute) --> Grow, GrowthRate
print(cabbage:GetAttribute(attribute)) --> false, 3
end
-- ฟังการเปลี่ยนแปลงและเชื่อมต่อกับฟังก์ชันในท้องถิ่น
cabbage.Changed:Connect(onAnyPropertyChange)
cabbage.AttributeChanged:Connect(onAnyAttributeChange)
-- ฟังการเปลี่ยนแปลงและเชื่อมต่อกับฟังก์ชันนิรนาม
cabbage:GetPropertyChangedSignal("Name"):Connect(function()
print(cabbage.Name) --> Cabbage1
end)
cabbage:GetAttributeChangedSignal("GrowthRate"):Connect(function()
print(cabbage:GetAttribute("GrowthRate")) --> 3
end)
-- ทำให้เกิด Changed และ GetPropertyChangedSignal()
cabbage.Name = "Cabbage1"
-- ทำให้เกิด Changed และ AttributeChanged
cabbage:SetAttribute("Grow", false)
-- ทำให้เกิด Changed, AttributeChanged และ GetAttributeChangedSignal()
cabbage:SetAttribute("GrowthRate", 3)