การนำพฤติกรรมบลาสเตอร์ไปใช้

*เนื้อหานี้แปลโดยใช้ AI (เวอร์ชัน Beta) และอาจมีข้อผิดพลาด หากต้องการดูหน้านี้เป็นภาษาอังกฤษ ให้คลิกที่นี่

การนำพฤติกรรมบลาสเตอร์ไปใช้ คือกระบวนการเขียนโปรแกรมกลไกการระเบิดในเกมยิงมุมมองบุคคลที่หนึ่ง ในขณะที่ผู้เล่นสามารถระเบิดได้ด้วยการคลิกเดียวหรือกดปุ่ม การสร้างพฤติกรรมการระเบิดที่น่าพอใจและแม่นยำเป็นสิ่งสำคัญเพราะมันช่วยเพิ่มความเพลิดเพลินของผู้เล่นในเกมโดยรวม

โดยใช้ เกมเลเซอร์แท็กตัวอย่าง เป็นข้อมูลอ้างอิง ส่วนนี้ของบทช่วยสอนจะสอนคุณเกี่ยวกับสคริปต์ที่อยู่เบื้องหลังการนำพฤติกรรมบลาสเตอร์ไปใช้สำหรับบลาสเตอร์สองประเภท รวมถึงแนวทางในการ:

  • ตรวจจับเมื่อผู้เล่นกดปุ่มระเบิด
  • ตรวจสอบว่าผู้เล่นสามารถใช้บลาสเตอร์ได้หรือไม่หากพวกเขากดปุ่มระเบิดเมื่อไม่นานมานี้
  • สร้างข้อมูลการระเบิดที่บอกเซิร์ฟเวอร์ว่าใครเป็นผู้เริ่มการระเบิด มันมาจากที่ไหน และจุดหมายปลายทางสุดท้ายของแต่ละลำแสงเลเซอร์คืออะไร
  • แจ้งเซิร์ฟเวอร์เกี่ยวกับข้อมูลการระเบิดเพื่อให้สามารถดำเนินการที่เหมาะสมหากการระเบิดชนกับผู้เล่นคนอื่น
  • รีเซ็ตบลาสเตอร์ระหว่างการระเบิดแต่ละครั้งเพื่อให้บลาสเตอร์มีเวลาพอในการเย็นตัวก่อนที่จะสามารถระเบิดได้อีกครั้ง

หลังจากที่คุณทำส่วนนี้เสร็จแล้ว คุณจะได้เรียนรู้เกี่ยวกับสคริปต์ที่ช่วยให้บลาสเตอร์ตรวจจับเมื่อการระเบิดของมันชนกับผู้เล่นคนอื่น จากนั้นหักจำนวนสุขภาพที่เหมาะสมตามประเภทบลาสเตอร์แต่ละประเภท

ตรวจสอบการป้อนข้อมูลของผู้เล่น

ขั้นตอนแรกในการนำพฤติกรรมบลาสเตอร์ไปใช้คือการฟังเมื่อผู้เล่นกดปุ่มระเบิด ประเภทการป้อนข้อมูลที่ผู้เล่นใช้ในการกดปุ่มระเบิดขึ้นอยู่กับอุปกรณ์ที่พวกเขาใช้ในการเข้าถึงเกม ตัวอย่างเช่น เกมเลเซอร์แท็กตัวอย่างรองรับการควบคุมด้วยเมาส์และคีย์บอร์ด คอนโซลเกม และการควบคุมด้วยการสัมผัส คุณสามารถดูประเภทการป้อนข้อมูลเหล่านี้ได้ใน ReplicatedStorageUserInputHandler

สคริปต์ไคลเอนต์นี้ใช้ ContextActionService เพื่อผูก MouseButton1 และ ButtonR2 กับการกระทำการระเบิด ซึ่งหมายความว่าทุกครั้งที่ผู้เล่นกดปุ่มเมาส์ซ้ายหรือปุ่ม R2 ของคอนโซลเกม จะทำให้เกิดลำแสงเลเซอร์ระเบิดออกจากบลาสเตอร์ โปรดทราบว่า HUDGui มีปุ่มสำหรับการระเบิดบนอุปกรณ์เคลื่อนที่ ซึ่งจะเชื่อมต่อในภายหลังในสคริปต์

UserInputHandler
ContextActionService:BindAction("_", onBlasterActivated, false,
Enum.UserInputType.MouseButton1,
Enum.KeyCode.ButtonR2
)

อีกหมายเหตุที่สำคัญคือการใช้ Enum.UserInputState.Begin ในการกำหนด onBlasterActivated() การโต้ตอบของส่วนติดต่อผู้ใช้หลายอย่าง เช่น การเลือกบลาสเตอร์ในตัวอย่างนี้ จะไม่เกิดขึ้นจนกว่าปุ่มเมาส์จะขึ้น (Enum.UserInputState.End) ซึ่งให้โอกาสสุดท้ายแก่ผู้ใช้ในการหลีกเลี่ยงการโต้ตอบ อย่างไรก็ตาม กลไกการระเบิดจะไม่รู้สึกตอบสนองหากมันเกิดขึ้นในทันทีที่ปุ่มกดลง

เพื่อแสดงให้เห็น คุณสามารถเปลี่ยน Enum.UserInputState.Begin เป็น Enum.UserInputState.End จากนั้นทดสอบการเล่นเพื่อดูว่าความตอบสนองของการระเบิดมีผลต่อการเล่นเกมอย่างไร ตัวอย่างเช่น หากผู้เล่นสามารถกดปุ่มค้างไว้โดยไม่ทำให้เกิดการระเบิด จะเปลี่ยนประสบการณ์ของพวกเขาในการแท็กผู้เล่นคนอื่นอย่างไร?

UserInputHandler
local function onBlasterActivated(_actionName: string,
inputState: Enum.UserInputState, _inputObject: InputObject)
if inputState == Enum.UserInputState.End then -- updated line, be sure to change back
attemptBlastClient()
end
end

ตรวจสอบว่าผู้เล่นสามารถระเบิดได้หรือไม่

หลังจากที่ UserInputHandler ตรวจจับการกดปุ่มหรือการสัมผัสหน้าจอ มันจะเรียก ReplicatedStorageBlasterattemptBlastClient เพื่อตรวจสอบว่าผู้เล่นสามารถระเบิดได้หรือไม่ เช่นเดียวกับการตรวจสอบส่วนใหญ่ในเกมเลเซอร์แท็กตัวอย่าง จะเกิดขึ้นสองครั้ง: ครั้งแรกบนไคลเอนต์ จากนั้นในเซิร์ฟเวอร์ attemptBlastClient จะเรียก ReplicatedStorageBlastercanLocalPlayerBlast เพื่อทำการตรวจสอบง่ายๆ ของแอตทริบิวต์ผู้เล่น blasterStateClient:

canLocalPlayerBlast
local function canLocalPlayerBlast(): boolean
return localPlayer:GetAttribute(PlayerAttribute.blasterStateClient) == BlasterState.Ready
end

หากคุณตรวจสอบ ReplicatedStorageBlasterBlasterState คุณจะเห็นว่าเกมมีสามสถานะบลาสเตอร์: Ready, Blasting, และ Disabled เพื่อดูผลกระทบของแต่ละสถานะเหล่านี้ คุณสามารถทดสอบการเล่นเกม เลือกผู้เล่นของคุณภายใต้บริการ Players จากนั้นสังเกตแอตทริบิวต์ blasterStateClient ในหน้าต่าง Properties สังเกตว่ามันแสดง Disabled ขณะที่คุณเลือกบลาสเตอร์ของคุณ Ready ส่วนใหญ่ของเวลา และ Blasting น้อยกว่าหนึ่งวินาทีหลังจากที่คุณกดปุ่ม

การหยุดชั่วคราวเล็กน้อยนี้ป้องกันไม่ให้คุณสามารถระเบิดได้อย่างรวดเร็วเท่าที่คุณคลิก ตัวอย่างเช่น หากคุณเปลี่ยนฟังก์ชันให้คืนค่าจริงเสมอ คุณสามารถระเบิดบลาสเตอร์ของคุณได้อย่างรวดเร็วโดยไม่มีความล่าช้า ซึ่งไม่สมจริงสำหรับการเล่นเกมเลเซอร์แท็ก

canLocalPlayerBlast
local function canLocalPlayerBlast(): boolean
return true -- updated line, be sure to change back
end

สร้างข้อมูลการระเบิด

หลังจากตรวจสอบว่าบลาสเตอร์ของผู้เล่นอยู่ในสถานะ Ready แล้ว attemptBlastClient จะเรียก ReplicatedStorageattemptBlastClientblastClient ขั้นตอนแรกที่ blastClient ทำคือการตั้งค่าแอตทริบิวต์ผู้เล่น blasterStateClient เป็น Blasting ซึ่งหลีกเลี่ยงกรณีการยิงอย่างรวดเร็วจากก่อนหน้านี้

ขั้นตอนถัดไปคือการสร้างข้อมูลการระเบิด หากคุณตรวจสอบ ReplicatedStorageBlasterBlastData คุณจะเห็นว่าการระเบิดแต่ละครั้งประกอบด้วยข้อมูลสามชิ้น:

  • ผู้เล่นที่เริ่มการระเบิด
  • DataType.CFrame ที่แสดงถึงจุดกำเนิดของการระเบิด
  • ตาราง RayResult ที่มีจุดหมายปลายทางสุดท้ายของแต่ละลำแสงเลเซอร์และผู้เล่นที่ถูกตี หากตีผู้เล่นคนอื่น

เพื่อสร้างข้อมูลนี้ blastClient จะเรียก ReplicatedStorageattemptBlastClientblastClientgenerateBlastData ซึ่งคุณสามารถตรวจสอบได้ด้านล่าง

generateBlastData
local function generateBlastData(): BlastData.Type
local blasterConfig = getBlasterConfig()
local rayDirections = getDirectionsForBlast(
currentCamera.CFrame, blasterConfig)
local rayResults = castLaserRay(
localPlayer, currentCamera.CFrame.Position, rayDirections)
local blastData: BlastData.Type = {
player = localPlayer,
originCFrame = currentCamera.CFrame,
rayResults = rayResults,
}
return blastData
end

ฟังก์ชันนี้เริ่มต้นด้วยการใช้ getBlasterConfig เพื่อดึงประเภทบลาสเตอร์ของผู้เล่น ตัวอย่างนี้มีบลาสเตอร์สองประเภท: หนึ่งที่ผลิตลำแสงหลายลำด้วยการกระจายแนวนอนกว้าง และอีกหนึ่งที่ผลิตลำแสงเดียว คุณสามารถค้นหาการกำหนดค่าของพวกเขาได้ใน ReplicatedStorageInstancesLaserBlastersFolder

ฟังก์ชันนี้ใช้ currentCamera.CFrame เป็นจุดกำเนิดสำหรับการระเบิด โดยส่งไปยัง getDirectionsForBlast ในจุดนี้ โค้ดไม่เกี่ยวกับบลาสเตอร์อีกต่อไป แต่เกี่ยวกับลำแสงเลเซอร์ ซึ่งคุณจะได้เรียนรู้เพิ่มเติมในส่วน ตรวจจับการชน ของบทช่วยสอน สุดท้าย หลังจากสร้างตาราง rayResults generateBlastData ก็มีข้อมูลทั้งหมดที่ต้องการเพื่อส่งคืนข้อมูลการระเบิดไปยัง blastClient

แจ้งเซิร์ฟเวอร์

เมื่อ blastClient มีข้อมูลการระเบิดที่สมบูรณ์ มันจะยิงสองเหตุการณ์:

blastClient
local laserBlastedBindableEvent = ReplicatedStorage.Instances.LaserBlastedBindableEvent
local laserBlastedEvent = ReplicatedStorage.Instances.LaserBlastedEvent
laserBlastedBindableEvent:Fire(blastData)
laserBlastedEvent:FireServer(blastData)

BindableEvent จะแจ้งสคริปต์ไคลเอนต์อื่น ๆ เกี่ยวกับการระเบิด ตัวอย่างเช่น ReplicatedStorageFirstPersonBlasterVisuals ใช้เหตุการณ์นี้เพื่อทราบว่าเมื่อใดควรแสดงเอฟเฟกต์ภาพ เช่น การเคลื่อนไหวของการระเบิดและแถบความเย็น ในทำนองเดียวกัน RemoteEvent จะแจ้งสคริปต์เซิร์ฟเวอร์เกี่ยวกับการระเบิด ซึ่งเริ่มการประมวลผลการระเบิดใน ServerScriptServiceLaserBlastHandler

LaserBlastHandler
local function onLaserBlastedEvent(playerBlasted: Player, blastData: BlastData.Type)
local validatedBlastData = getValidatedBlastData(playerBlasted, blastData)
if not validatedBlastData then
return
end
if not canPlayerBlast(playerBlasted) then
return
end
blastServer(playerBlasted)
processTaggedPlayers(playerBlasted, blastData)
for _, replicateToPlayer in Players:GetPlayers() do
if playerBlasted == replicateToPlayer then
continue
end
replicateBlastEvent:FireClient(replicateToPlayer, playerBlasted, blastData)
end
end

เพื่อช่วยป้องกันการโกง เซิร์ฟเวอร์ต้องตรวจสอบข้อมูลทั้งหมดที่แต่ละไคลเอนต์ส่ง การตรวจสอบเหล่านี้รวมถึง:

  1. BlastData เป็นตารางหรือไม่? มี Class.CFrame และตารางอีกตารางชื่อ rayResults หรือไม่?
  2. ผู้เล่นมีบลาสเตอร์ติดตั้งอยู่หรือไม่?
  3. ผู้เล่นมีตัวละครและตำแหน่งภายในโลกหรือไม่?
  4. หลังจากส่งข้อมูลการระเบิด ผู้เล่นได้เคลื่อนที่ไปยังระยะทางที่มากเกินไปจากจุดที่พวกเขาระเบิดลำแสงเลเซอร์หรือไม่?

การตรวจสอบครั้งสุดท้ายนี้เกี่ยวข้องกับการตัดสินใจ และตามความล่าช้าของเซิร์ฟเวอร์และความเร็วในการเคลื่อนที่ของผู้เล่น คุณอาจตัดสินใจว่าค่าที่แตกต่างกันเป็นค่าที่มากเกินไปสำหรับเกมของคุณเอง เพื่อแสดงให้เห็นถึงวิธีการตัดสินใจนี้ คุณสามารถรับรู้ถึงขนาดทั่วไปของการเปลี่ยนแปลงตำแหน่งโดยการเพิ่มคำสั่งพิมพ์ใน getValidatedBlastData และทดสอบการเล่นเกม

getValidatedBlastData
local distanceFromCharacterToOrigin = blastData.originCFrame.Position - rootPartCFrame.Position
print(distanceFromCharacterToOrigin.Magnitude) -- updated line, be sure to remove
if distanceFromCharacterToOrigin.Magnitude > ToleranceValues.DISTANCE_SANITY_CHECK_TOLERANCE_STUDS then
warn(`Player {player.Name} failed an origin sanity check while blasting`)
return
end

เมื่อคุณเคลื่อนที่และระเบิด ให้สังเกตผลลัพธ์ มันอาจดูเหมือนสิ่งนี้:

1.9019629955291748
3.1549558639526367
2.5742883682250977
4.8044586181640625
2.6434271335601807

หากคุณเพิ่มความเร็วในการเคลื่อนที่สำหรับผู้เล่นใน ReplicatedStoragePlayerStateHandlertogglePlayerMovement จากนั้นทดสอบการเล่นอีกครั้ง คุณจะพบว่ามีการตรวจสอบที่ล้มเหลวมากมายเนื่องจากการเคลื่อนที่มากเกินไประหว่างการระเบิด

togglePlayerMovement
local ENABLED_WALK_SPEED = 60 -- updated line, be sure to change back

เซิร์ฟเวอร์จะทำสิ่งต่อไปนี้:

  • ตรวจสอบ rayResults
  • ตรวจสอบว่าผู้เล่นสามารถระเบิดได้หรือไม่
  • รีเซ็ตสถานะบลาสเตอร์
  • ลดสุขภาพสำหรับผู้เล่นที่ถูกแท็ก
  • ทำซ้ำการระเบิดไปยังผู้เล่นคนอื่นทั้งหมดเพื่อให้พวกเขาสามารถเห็นภาพมุมมองบุคคลที่สาม

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการดำเนินการของเซิร์ฟเวอร์เหล่านี้ โปรดดูที่ส่วน ตรวจจับการชน ของบทช่วยสอน

รีเซ็ตบลาสเตอร์

ในเกมเลเซอร์แท็กตัวอย่าง บลาสเตอร์ใช้กลไกความร้อน แทนที่จะโหลดใหม่หลังจากการระเบิดจำนวนหนึ่ง พวกเขาต้องใช้เวลาในการ "เย็นตัว" ระหว่างการระเบิดแต่ละครั้ง ความล่าช้านี้เกิดขึ้นทั้งในไคลเอนต์ (blastClient) และเซิร์ฟเวอร์ (blastServer) โดยเซิร์ฟเวอร์ทำหน้าที่เป็นแหล่งข้อมูลที่ถูกต้อง

blastServer
local blasterConfig = getBlasterConfig(player)
local secondsBetweenBlasts = blasterConfig:GetAttribute("secondsBetweenBlasts")
task.delay(secondsBetweenBlasts, function()
local currentState = player:GetAttribute(PlayerAttribute.blasterStateServer)
if currentState == BlasterState.Blasting then
player:SetAttribute(PlayerAttribute.blasterStateServer, BlasterState.Ready)
end
end)

แอตทริบิวต์ secondsBetweenBlasts เป็นส่วนหนึ่งของการกำหนดค่าบลาสเตอร์ใน ReplicatedStorageInstancesLaserBlastersFolder หลังจากที่เวลาล่าช้า secondsBetweenBlasts ผ่านไป ผู้เล่นสามารถระเบิดได้อีกครั้ง และกระบวนการทั้งหมดจะทำซ้ำ เพื่อช่วยให้ผู้เล่นเข้าใจเมื่อใดที่พวกเขาสามารถระเบิดได้อีกครั้ง เกมจึงมีแถบความเย็น

ในจุดนี้ ผู้เล่นสามารถเกิดใหม่และเกิดใหม่ เล็งและระเบิด แต่เกมยังต้องกำหนดผลลัพธ์ของการระเบิดแต่ละครั้ง ในส่วนถัดไปของบทช่วยสอน คุณจะได้เรียนรู้วิธีการเขียนโปรแกรมความสามารถให้บลาสเตอร์ตรวจจับเมื่อการระเบิดชนกับผู้เล่นคนอื่น จากนั้นลดจำนวนสุขภาพของผู้เล่นตามการตั้งค่าบลาสเตอร์

©2026 Roblox Corporation. Roblox, โลโก้ Roblox และ Powering Imagination เป็นส่วนหนึ่งของเครื่องหมายการค้าที่จดทะเบียน และไม่ได้จดทะเบียนของเราในสหรัฐฯ และประเทศอื่นๆ