ตรวจจับการโจมตีด้วยเลเซอร์

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

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

การโค้งรัศมีเพื่อค้นหาการชนกัน

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

เรย์คาสต์จาก A ไปยัง B ชนกับผนัง

ค้นหาตำแหน่งของเมาส์

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

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

  2. ที่ด้านบนของสคริปต์ ประกาศคงที่ชื่อ MAX_MOUSE_DISTANCE ด้วยค่า 1000

  3. สร้างฟังก์ชันที่เรียกว่า getWorldMousePosition


    local tool = script.Parent
    local MAX_MOUSE_DISTANCE = 1000
    local function getWorldMousePosition()
    end
    local function toolEquipped()
    tool.Handle.Equip:Play()
    end
    local function toolActivated()
    tool.Handle.Activate:Play()
    end
    -- เชื่อมต่อเหตุการณ์กับฟังก์ชันที่เหมาะสม
    tool.Equipped:Connect(toolEquipped)
    tool.Activated:Connect(toolActivated)
  4. ใช้ฟังก์ชัน GetMouseLocation ของ UserInputService เพื่อรับตำแหน่งเมาส์ 2D ของผู้เล่นบนหน้าจอกำหนดสิ่งนี้ให้กับตัวแปรที่ชื่อ mouseLocation


    local UserInputService = game:GetService("UserInputService")
    local tool = script.Parent
    local MAX_MOUSE_DISTANCE = 1000
    local function getWorldMousePosition()
    local mouseLocation = UserInputService:GetMouseLocation()
    end

ตอนนี้ตำแหน่งเมาส์ 2D เป็นที่รู้จักแล้ว คุณสมบัติ X และ Y สามารถใช้เป็นพารามิเตอร์สำหรับฟังก์ชัน ซึ่งสร้าง 3D จากหน้าจอสู่โลกเกม

  1. ใช้คุณสมบัติ X และ Y ของ mouseLocation เป็นอาร์กิวเมนต์สำหรับฟังก์ชัน ViewportPointToRay()กำหนดสิ่งนี้ให้กับตัวแปรชื่อ screenToWorldRay

    local function getWorldMousePosition()
    local mouseLocation = UserInputService:GetMouseLocation()
    -- สร้างลําแสงจากตําแหน่งเมาส์ 2D
    local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    end

ถึงเวลาที่จะใช้ฟังก์ชัน Raycast เพื่อตรวจสอบว่ารังสีชนกับวัตถุหรือไม่สิ่งนี้ต้องใช้ตําแหน่งเริ่มต้นและเวกเตอร์ทิศทาง: ในตัวอย่างนี้คุณจะใช้คุณสมบัติที่มาจากและทิศทางของ screenToWorldRay

ความยาวของเวกเตอร์ทิศทางกำหนดระยะที่ลำแสงจะเดินทางไปได้ลำแสงต้องยาวเท่ากับ MAX_MOUSE_DISTANCE ดังนั้นคุณจะต้องคูณเวกเตอร์ทิศทางด้วย MAX_MOUSE_DISTANCE

  1. ประกาศตัวแปรชื่อ directionVector และกำหนดมูลค่าของ screenToWorldRay.Direction คูณด้วย MAX_MOUSE_DISTANCE


    local function getWorldMousePosition()
    local mouseLocation = UserInputService:GetMouseLocation()
    -- สร้างลําแสงจากตําแหน่งเมาส์ 2D
    local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    -- เวกเตอร์ทิศทางหน่วยของรังสีที่คูณด้วยระยะสูงสุด
    local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
  2. เรียกฟังก์ชัน Raycast ของพื้นที่ทำงานโดยส่งคุณสมบัติ Origin ของ screenToWorldRay เป็นอาร์กิวเมนต์แรกและ directionVector เป็นอาร์กิวเมนต์ที่สองกำหนดสิ่งนี้ให้กับตัวแปรชื่อ raycastResult


    local function getWorldMousePosition()
    local mouseLocation = UserInputService:GetMouseLocation()
    -- สร้างลําแสงจากตําแหน่งเมาส์ 2D
    local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    -- เวกเตอร์ทิศทางหน่วยของรังสีที่คูณด้วยระยะสูงสุด
    local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
    -- เรย์คาสต์จากจุดกำเนิดของรังสีไปสู่ทิศทางของมัน
    local raycastResult = workspace:Raycast(screenToWorldRay.Origin, directionVector)

ข้อมูลการชนกัน

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

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

คุณสมบัติ ตำแหน่ง จะเป็นตำแหน่งของวัตถุที่เมาส์เลื่อนอยู่เหนือหากเมาส์ไม่ได้ลอยอยู่เหนือวัตถุใดๆ ในระยะ MAX_MOUSE_DISTANCE , raycastResult จะเป็น nil

  1. สร้างคำสั่ง if เพื่อตรวจสอบว่า raycastResult มีอยู่หรือไม่

  2. หาก raycastResult มีค่า, ส่งค่า ตำแหน่ง ของมันกลับ

  3. หาก raycastResult เป็น nil แล้วค้นหาจุดสิ้นสุดของ raycastคำนวณตำแหน่ง 3D ของเมาส์โดยเพิ่ม screenToWorldRay.Origin และ directionVector รวมกัน


local function getWorldMousePosition()
local mouseLocation = UserInputService:GetMouseLocation()
-- สร้างลําแสงจากตําแหน่งเมาส์ 2D
local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
-- เวกเตอร์ทิศทางหน่วยของรังสีที่คูณด้วยระยะสูงสุด
local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
-- เรย์คาสต์จากจุดกำเนิดของรังสีไปสู่ทิศทางของมัน
local raycastResult = workspace:Raycast(screenToWorldRay.Origin, directionVector)
if raycastResult then
-- ส่งคืนจุดแยกที่ 3D
return raycastResult.Position
else
-- ไม่มีวัตถุถูกโจมตีดังนั้นจึงคำนวณตำแหน่งในตอนท้ายของรังสี
return screenToWorldRay.Origin + directionVector
end
end

ยิงไปที่เป้าหมาย

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

  1. ประกาศคงที่ที่เรียกว่า MAX_LASER_DISTANCE ที่ด้านบนของสคริปต์และกำหนดให้กับ 500 หรือช่วงที่คุณเลือกสำหรับเลเซอร์บลาสเตอร์


    local UserInputService = game:GetService("UserInputService")
    local tool = script.Parent
    local MAX_MOUSE_DISTANCE = 1000
    local MAX_LASER_DISTANCE = 500
  2. สร้างฟังก์ชันที่เรียกว่า fireWeapon ภายใต้ฟังก์ชัน getWorldMousePosition

  3. โทร getWorldMousePosition และกำหนดผลลัพธ์ให้กับตัวแปรชื่อ mousePosition นี่จะเป็นตำแหน่งเป้าหมายสําหรับการโค้งรังสี


    -- ไม่มีวัตถุถูกโจมตีดังนั้นจึงคำนวณตำแหน่งในตอนท้ายของรังสี
    return screenToWorldRay.Origin + directionVector
    end
    end
    local function fireWeapon()
    local mouseLocation = getWorldMousePosition()
    end
    local function toolEquipped()
    tool.Handle.Equip:Play()
    end

ครั้งนี้เวกเตอร์ทิศทางสำหรับฟังก์ชันการโค้งรัศมีจะแทนที่ทิศทางจากตำแหน่งเครื่องมือของผู้เล่นไปยังตำแหน่งเป้าหมาย

  1. ประกาศตัวแปรชื่อ เป้าหมายทิศทาง และคำนวณเวกเตอร์ทิศทางโดยการหักตำแหน่งเครื่องมือออกจาก mouseLocation

  2. ปรับเวกเตอร์โดยใช้คุณสมบัติ หน่วย ของมัน สิ่งนี้ทำให้มันมีขนาด 1 ซึ่งทำให้ง่ายต่อการคูณด้วยระยะในภายหลัง


    local function fireWeapon()
    local mouseLocation = getWorldMousePosition()
    -- คำนวณเวกเตอร์ทิศทางปกติและคูณด้วยระยะทางเลเซอร์
    local targetDirection = (mouseLocation - tool.Handle.Position).Unit
    end
  3. ประกาศตัวแปรชื่อ directionVector และกำหนดให้มันมี targetDirection คูณด้วย MAX_LASER_DISTANCE


    local targetDirection = (mouseLocation - tool.Handle.Position).Unit
    -- ทิศทางในการยิงอาวุธที่คูณด้วยระยะสูงสุด
    local directionVector = targetDirection * MAX_LASER_DISTANCE
    end

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

  1. ดำเนินการต่อฟังก์ชัน fireWeapon และประกาศตัวแปรที่เรียกว่า weaponRaycastParams กำหนดวัตถุ RaycastParams ใหม่ให้กับมัน

  2. สร้างตารางที่มีตัวอักษรท้องถิ่นของผู้เล่น และกำหนดให้เป็นคุณสมบัติ

  3. เรย์คาสต์จากตําแหน่งจัดการเครื่องมือของผู้เล่นในทิศทางไปที่ directionVectorอย่าลืมเพิ่ม weaponRaycastParams เป็นอาร์กิวเมนต์ในครั้งนี้กำหนดสิ่งนี้ให้กับตัวแปรที่ชื่อ weaponRaycastResult


local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local tool = script.Parent
local MAX_MOUSE_DISTANCE = 1000
local MAX_LASER_DISTANCE = 500
local function getWorldMousePosition()

local function fireWeapon()
local mouseLocation = getWorldMousePosition()
-- คำนวณเวกเตอร์ทิศทางปกติและคูณด้วยระยะทางเลเซอร์
local targetDirection = (mouseLocation - tool.Handle.Position).Unit
-- ทิศทางในการยิงอาวุธคูณด้วยระยะสูงสุด
local directionVector = targetDirection * MAX_LASER_DISTANCE
-- เพิกเฉยตัวละครของผู้เล่นเพื่อป้องกันไม่ให้พวกเขาทำลายตัวเอง
local weaponRaycastParams = RaycastParams.new()
weaponRaycastParams.FilterDescendantsInstances = {Players.LocalPlayer.Character}
local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
end

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

  1. ประกาศตัวแปรว่างเปล่าชื่อ hitPosition

  2. ใช้คำสั่ง ถ้า เพื่อตรวจสอบว่า weaponRaycastResult มีค่าหรือไม่ หากวัตถุถูกโจมตีให้กำหนด weaponRaycastResult.Position ให้กับ hitPosition


    local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
    -- ตรวจสอบว่ามีวัตถุใดถูกโจมตีระหว่างตำแหน่งเริ่มต้นและสิ้นสุดหรือไม่
    local hitPosition
    if weaponRaycastResult then
    hitPosition = weaponRaycastResult.Position
    end
  3. หาก weaponRaycastResult ไม่มีค่าใดๆ ให้คำนวณตำแหน่งสุดท้ายของการโค้งรัศมีโดยเพิ่มตำแหน่ง **** ของด้ามจับเครื่องมือกับ directionVectorกำหนดนี้ให้กับ hitPosition .


    local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
    -- ตรวจสอบว่ามีวัตถุใดถูกโจมตีระหว่างตำแหน่งเริ่มต้นและสิ้นสุดหรือไม่
    local hitPosition
    if weaponRaycastResult then
    hitPosition = weaponRaycastResult.Position
    else
    -- คำนวณตำแหน่งสุดท้ายตามระยะเลเซอร์สูงสุด
    hitPosition = tool.Handle.Position + directionVector
    end
    end
  4. นําทางไปยังฟังก์ชัน toolActivated และโทรฟังก์ชัน fireWeapon เพื่อให้เลเซอร์ยิงในแต่ละครั้งที่เครื่องมือถูกเปิดใช้งาน


    local function toolActivated()
    tool.Handle.Activate:Play()
    fireWeapon()
    end

ตรวจสอบวัตถุที่โดน

เพื่อหาว่าวัตถุที่ถูกโจมตีโดยเลเซอร์เป็นส่วนหนึ่งของตัวละครของผู้เล่นหรือเพียงแค่เป็นส่วนหนึ่งของทิวทัศน์ คุณจะต้องมองหา Humanoid เพราะทุกตัวละครมีหนึ่ง

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

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

  1. เพิ่มโค้ดที่ไฮไลต์ด้านล่างไปยังคําสั่ง weaponRaycastResult ถ้า เพื่อตรวจสอบว่าตัวละครถูกโจมตีหรือไม่


    -- ตรวจสอบว่ามีวัตถุใดถูกโจมตีระหว่างตำแหน่งเริ่มต้นและสิ้นสุดหรือไม่
    local hitPosition
    if weaponRaycastResult then
    hitPosition = weaponRaycastResult.Position
    -- การโจมตีตัวอย่างจะเป็นลูกของโมเดลตัวละคร
    -- หากพบหุ่นยนต์ในโมเดลแล้วมันอาจเป็นตัวละครของผู้เล่น
    local characterModel = weaponRaycastResult.Instance:FindFirstAncestorOfClass("Model")
    if characterModel then
    local humanoid = characterModel:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    print("Player hit")
    end
    end
    else
    -- คำนวณตำแหน่งสุดท้ายตามระยะเลเซอร์สูงสุด
    hitPosition = tool.Handle.Position + directionVector
    end

ตอนนี้เลเซอร์บลาสเตอร์ควรพิมพ์ Player hit ไปยังหน้าต่างเอาต์พุตทุกครั้งที่การดำเนินการรังสีโจมตีผู้เล่นคนอื่น

ทดสอบกับผู้เล่นหลายคน

ต้องมีผู้เล่นสองคนเพื่อทดสอบว่ารังสีอาวุธกำลังค้นหาผู้เล่นคนอื่นหรือไม่ดังนั้นคุณจึงต้องเริ่มต้นเซิร์ฟเวอร์ท้องถิ่น

  1. เลือกแท็บ ทดสอบ ใน Studio

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

  3. บนไคลเอนต์เดียว ทดสอบการยิงผู้เล่นอีกคนด้วยอาวุธโดยคลิกที่พวกเขาการโจมตี "ผู้เล่น" ควรแสดงในออกในแต่ละครั้งที่ผู้เล่นถูกยิง

คุณสามารถค้นหาข้อมูลเพิ่มเติมเกี่ยวกับแท็บ ทดสอบ ที่นี่

ค้นหาตำแหน่งเลเซอร์

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

  1. สร้าง ModuleScript ที่ชื่อว่า LaserRenderer ซึ่งเป็นบุตรของ StarterPlayerScripts ภายใต้ StarterPlayer

  2. เปิดสคริปต์และเปลี่ยนชื่อตารางโมดูลเป็นชื่อของสคริปต์ LaserRenderer

  3. ประกาศตัวแปรชื่อ SHOT_DURATION ด้วยค่า 0.15 นี่จะเป็นระยะเวลา (ในวินาที) ที่เลเซอร์สามารถมองเห็นได้

  4. สร้างฟังก์ชันของ LaserRenderer ชื่อ createLaser ด้วยพารามิเตอร์สองตัวที่เรียกว่า toolHandle และ endPosition


    local LaserRenderer = {}
    local SHOT_DURATION = 0.15 -- เวลาที่เลเซอร์สามารถมองเห็นได้
    -- สร้างลำแสงเลเซอร์จากตําแหน่งเริ่มต้นไปยังตําแหน่งสิ้นสุด
    function LaserRenderer.createLaser(toolHandle, endPosition)
    end
    return LaserRenderer
  5. ประกาศตัวแปรชื่อ startPosition และตั้งค่าคุณสมบัติ ตำแหน่ง ของ toolHandle เป็นค่าของมันนี่จะเป็นตำแหน่งของเลเซอร์บลาสเตอร์ของผู้เล่น

  6. ประกาศตัวแปรชื่อ laserDistance และหัก endPosition จาก startPosition เพื่อหาความแตกต่างระหว่างสองเวกเตอร์ใช้คุณสมบัติ ความเข้ม ของสิ่งนี้เพื่อรับความยาวของลำแสงเลเซอร์


    function LaserRenderer.createLaser(toolHandle, endPosition)
    local startPosition = toolHandle.Position
    local laserDistance = (startPosition - endPosition).Magnitude
    end
  7. ประกาศตัวแปร laserCFrame เพื่อเก็บตำแหน่งและทิศทางของลำแสงเลเซอร์ตำแหน่งจะต้องเป็นจุดกลางของจุดเริ่มต้นและจุดสิ้นสุดของลำแสงใช้ CFrame.lookAt เพื่อสร้างใหม่ CFrame ที่ตั้งอยู่ที่ startPosition และหันไปทาง endPositionคูณสิ่งนี้ด้วย CFrame ใหม่ที่มีค่าแกน Z เป็นครึ่งของลบ laserDistance เพื่อรับจุดกลาง


    function LaserRenderer.createLaser(toolHandle, endPosition)
    local startPosition = toolHandle.Position
    local laserDistance = (startPosition - endPosition).Magnitude
    local laserCFrame = CFrame.lookAt(startPosition, endPosition) * CFrame.new(0, 0, -laserDistance / 2)
    end

สร้างชิ้นส่วนเลเซอร์

ตอนนี้คุณรู้แล้วว่าควรสร้างลำแสงเลเซอร์ที่ไหน คุณต้องเพิ่มลำแสงเอง ซึ่งสามารถทำได้ง่ายด้วยชิ้นส่วนนีออน

  1. ประกาศตัวแปร laserPart และกำหนดให้มันเป็นตัวอย่างใหม่ Part

  2. ตั้งค่าคุณสมบัติต่อไปนี้ของ laserPart :

    1. ขนาด : Vector3.new(0.2, 0.2, ระยะเลเซอร์)
    2. CFrame : ลาเซอร์CFrame
    3. ถูกยึด : จริง
    4. CanCollide : ไม่ใช่
    5. สี : Color3.fromRGB(225, 0, 0) (สีแดงสดใส)
    6. วัสดุ : Enum.Material.Neon
  3. พ่อ laserPart ไปยัง พื้นที่ทำงาน .

  4. เพิ่มส่วนให้บริการ Debris เพื่อให้มันถูกลบหลังจากจำนวนวินาทีในตัวแปร SHOT_DURATION


    function LaserRenderer.createLaser(toolHandle, endPosition)
    local startPosition = toolHandle.Position
    local laserDistance = (startPosition - endPosition).Magnitude
    local laserCFrame = CFrame.lookAt(startPosition, endPosition) * CFrame.new(0, 0, -laserDistance / 2)
    local laserPart = Instance.new("Part")
    laserPart.Size = Vector3.new(0.2, 0.2, laserDistance)
    laserPart.CFrame = laserCFrame
    laserPart.Anchored = true
    laserPart.CanCollide = false
    laserPart.Color = Color3.fromRGB(225, 0, 0)
    laserPart.Material = Enum.Material.Neon
    laserPart.Parent = workspace
    -- เพิ่มลำแสงเลเซอร์ในบริการกำจัดเศษซากที่จะถูกลบและทำความสะอาด
    Debris:AddItem(laserPart, SHOT_DURATION)
    end

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

  1. ที่ด้านบนของสคริปต์ ToolController ประกาศตัวแปรชื่อ LaserRenderer และต้องการสคริปต์โมดูล LaserRenderer ที่อยู่ใน PlayerScripts


    local UserInputService = game:GetService("UserInputService")
    local Players = game:GetService("Players")
    local LaserRenderer = require(Players.LocalPlayer.PlayerScripts.LaserRenderer)
    local tool = script.Parent
  2. ที่ด้านล่างของฟังก์ชัน fireWeapon เรียกฟังก์ชัน LaserRenderer createLaser โดยใช้จัดการเครื่องมือและ hitPosition เป็นอาร์กิวเมนต์


    -- คำนวณตำแหน่งสุดท้ายตามระยะเลเซอร์สูงสุด
    hitPosition = tool.Handle.Position + directionVector
    end
    LaserRenderer.createLaser(tool.Handle, hitPosition)
    end
  3. ทดสอบอาวุธโดยคลิกที่ปุ่มเล่น ลำแสงเลเซอร์ควรมองเห็นได้ระหว่างอาวุธและเมาส์เมื่อเครื่องมือถูกเปิดใช้งาน

ให้คะแนน

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

  1. ประกาศตัวแปรที่ด้านบนของ ToolController ที่เรียกว่า FIRE_RATE นี่จะเป็นเวลาขั้นต่ำระหว่างแต่ละยิงให้ค่าที่คุณเลือก; ตัวอย่างนี้ใช้เวลา 0.3 วินาที

  2. ประกาศตัวแปรอื่นที่อยู่ด้านล่างเรียกว่า timeOfPreviousShot ด้วยค่า 0 สิ่งนี้จะบันทึกครั้งล่าสุดที่ผู้เล่นยิงและจะได้รับการอัปเดตในแต่ละยิง


    local MAX_MOUSE_DISTANCE = 1000
    local MAX_LASER_DISTANCE = 300
    local FIRE_RATE = 0.3
    local timeOfPreviousShot = 0
  3. สร้างฟังก์ชันชื่อ canShootWeapon โดยไม่มีพารามิเตอร์ฟังก์ชันนี้จะดูว่าผ่านไปกี่นาทีนับตั้งแต่การยิงครั้งก่อนและคืนค่าเป็นจริงหรือเท็จ


    local FIRE_RATE = 0.3
    local timeOfPreviousShot = 0
    -- ตรวจสอบว่าผ่านไปเวลาเพียงพอแล้วนับตั้งแต่ยิงครั้งล่าสุด
    local function canShootWeapon()
    end
    local function getWorldMousePosition()
  4. ภายในฟังก์ชันประกาศตัวแปรชื่อ เวลาปัจจุบัน และกำหนดให้มันเป็นผลลัพธ์ของการเรียกใช้ฟังก์ชัน tick()สิ่งนี้จะส่งคืนเวลาที่ผ่านไปเท่าใดในวินาทีตั้งแต่วันที่ 1 มกราคม 1970 (วันที่มีการใช้กันอย่างแพร่หลายเพื่อคำนวณเวลา)

  5. ลบ timeOfPreviousShot จาก currentTime และส่งคืน ปลอม หากผลลัพธ์เล็กกว่า FIRE_RATE มิฉะนั้นส่งคืน จริง


    -- ตรวจสอบว่าผ่านไปเวลาเพียงพอแล้วนับตั้งแต่ยิงครั้งล่าสุด
    local function canShootWeapon()
    local currentTime = tick()
    if currentTime - timeOfPreviousShot < FIRE_RATE then
    return false
    end
    return true
    end
  6. ในตอนท้ายของฟังก์ชัน fireWeapon อัปเดต timeOfPreviousShot ทุกครั้งที่อาวุธถูกยิงโดยใช้ tick


    hitPosition = tool.Handle.Position + directionVector
    end
    timeOfPreviousShot = tick()
    LaserRenderer.createLaser(tool.Handle, hitPosition)
    end
  7. ภายในฟังก์ชัน toolActivated สร้างคำสั่ง ถ้า และโทร canShootWeapon เพื่อตรวจสอบว่าอาวุธสามารถยิงได้หรือไม่


    local function toolActivated()
    if canShootWeapon() then
    tool.Handle.Activate:Play()
    fireWeapon()
    end
    end

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

ทำลายผู้เล่น

ลูกค้าไม่สามารถทำลายลูกค้าอื่นโดยตรง; เซิร์ฟเวอร์ต้องรับผิดชอบในการออกความเสียหายเมื่อผู้เล่นถูกโจมตี

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

  1. สร้างโฟลเดอร์ ใน ReplicatedStorage ชื่อว่า อีเวนต์ .

  2. ใส่อีเวนต์ระยะไกลลงในโฟลเดอร์กิจกรรมและตั้งชื่อว่า DamageCharacter

  3. ใน ToolController สร้างตัวแปรในตอนเริ่มต้นของสคริปต์สำหรับ ReplicatedStorage และโฟลเดอร์กิจกรรม


    local UserInputService = game:GetService("UserInputService")
    local Players = game:GetService("Players")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local LaserRenderer = require(Players.LocalPlayer.PlayerScripts.LaserRenderer)
    local tool = script.Parent
    local eventsFolder = ReplicatedStorage.Events
    local MAX_MOUSE_DISTANCE = 1000
    local MAX_LASER_DISTANCE = 500
  4. เปลี่ยนคำสั่งพิมพ์ "Player hit" ใน fireWeapon ด้วยบรรทัด Luau เพื่อยิงเหตุการณ์ระยะไกล DamageCharacter ด้วยตัวแปร characterModel เป็นอาร์กิวเมนต์


    local characterModel = weaponRaycastResult.Instance:FindFirstAncestorOfClass("Model")
    if characterModel then
    local humanoid = characterModel:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    eventsFolder.DamageCharacter:FireServer(characterModel)
    end
    end
    else
    -- คำนวณตำแหน่งสุดท้ายตามระยะเลเซอร์สูงสุด
    hitPosition = tool.Handle.Position + directionVector
    end

เซิร์ฟเวอร์ต้องสร้างความเสียหายให้กับผู้เล่นที่ถูกโจมตีเมื่อเหตุการณ์ถูกยิง

  1. ใส่ สคริปต์ ใน ServerScriptService และตั้งชื่อว่า ServerLaserManager

  2. ประกาศตัวแปรชื่อ LASER_DAMAGE และตั้งค่าเป็น 10 หรือค่าที่คุณเลือก

  3. สร้างฟังก์ชันชื่อ damageCharacter ที่มีพารามิเตอร์สองตัวที่เรียกว่า playerFired และ characterToDamage

  4. ภายในฟังก์ชันค้นหา Humanoid ของตัวละครและลบ LASER_DAMAGE ออกจากสุขภาพของมัน

  5. เชื่อมฟังก์ชัน damageCharacter กับอีเวนต์ระยะไกล DamageCharacter ในโฟลเดอร์อีเวนต์


    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local eventsFolder = ReplicatedStorage.Events
    local LASER_DAMAGE = 10
    function damageCharacter(playerFired, characterToDamage)
    local humanoid = characterToDamage:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    -- ลบสุขภาพออกจากตัวละคร
    humanoid.Health -= LASER_DAMAGE
    end
    end
    -- เชื่อมต่อเหตุการณ์กับฟังก์ชันที่เหมาะสม
    eventsFolder.DamageCharacter.OnServerEvent:Connect(damageCharacter)
  6. ทดสอบเบลาสเตอร์ด้วยผู้เล่น 2 คนโดยเริ่มเซิร์ฟเวอร์ท้องถิ่นเมื่อคุณยิงผู้เล่นคนอื่น สุขภาพของพวกเขาจะลดลงตามจํานวนที่กำหนดไว้ LASER_DAMAGE

แสดงลำแสงเลเซอร์ของผู้เล่นอื่น

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

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

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

ไคลเอนต์ของนักยิง

ก่อนอื่น ไคลเอนต์ต้องบอกเซิร์ฟเวอร์ว่ามันได้ยิงเลเซอร์และให้ตำแหน่งสิ้นสุด

  1. ใส่ อีเวนต์ระยะไกล ในโฟลเดอร์อีเวนต์ใน ReplicatedStorage และตั้งชื่อว่า LaserFired

  2. ค้นหาฟังก์ชัน fireWeapon ในสคริปต์ ToolController เมื่อสิ้นสุดฟังก์ชัน ให้ยิงเหตุการณ์ระยะไกล LaserFired โดยใช้ hitPosition เป็นอาร์กิวเมนต์


    hitPosition = tool.Handle.Position + directionVector
    end
    timeOfPreviousShot = tick()
    eventsFolder.LaserFired:FireServer(hitPosition)
    LaserRenderer.createLaser(tool.Handle, hitPosition)
    end

เซิร์ฟเวอร์

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

  1. ในสคริปต์ ServerLaserManager สร้างฟังก์ชันชื่อ playerFiredLaser เหนือ damageCharacter ด้วยพารามิเตอร์สองตัวที่ชื่อ playerFired และ endPosition

  2. เชื่อมฟังก์ชันกับอีเวนต์ระยะไกล LaserFired


    -- แจ้งให้ลูกค้าทั้งหมดทราบว่ามีการยิงเลเซอร์เพื่อให้พวกเขาสามารถแสดงเลเซอร์ได้
    local function playerFiredLaser(playerFired, endPosition)
    end

    -- เชื่อมต่อเหตุการณ์กับฟังก์ชันที่เหมาะสม
    eventsFolder.DamageCharacter.OnServerEvent:Connect(damageCharacter)
    eventsFolder.LaserFired.OnServerEvent:Connect(playerFiredLaser)

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

  1. สร้างฟังก์ชัน getPlayerToolHandle เหนือฟังก์ชัน playerFiredLaser ด้วยพารามิเตอร์ชื่อว่า player

  2. ใช้รหัสต่อไปนี้เพื่อค้นหาตัวละครของผู้เล่นสำหรับอาวุธและส่งคืนวัตถุจัดการ


    local LASER_DAMAGE = 10
    -- ค้นหาตัวจัดการของเครื่องมือที่ผู้เล่นกําลังถือ
    local function getPlayerToolHandle(player)
    local weapon = player.Character:FindFirstChildOfClass("Tool")
    if weapon then
    return weapon:FindFirstChild("Handle")
    end
    end
    -- แจ้งให้ลูกค้าทั้งหมดทราบว่ามีการยิงเลเซอร์เพื่อให้พวกเขาสามารถแสดงเลเซอร์ได้
    local function playerFiredLaser(playerFired, endPosition)

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

  1. ในฟังก์ชัน playerFiredLaser โทรไปที่ฟังก์ชัน getPlayerToolHandle ด้วย playerFired เป็นอาร์กิวเมนต์และกำหนดค่ามูลค่าให้กับตัวแปรชื่อว่า toolHandle

  2. หากเครื่องมือ toolHandle มีอยู่ ให้ยิงอีเวนต์ LaserFired สำหรับลูกค้าทั้งหมดที่ใช้ playerFired และ toolHandle และ endPosition เป็นอาร์กิวเมนต์


    -- แจ้งให้ลูกค้าทั้งหมดทราบว่ามีการยิงเลเซอร์เพื่อให้พวกเขาสามารถแสดงเลเซอร์ได้
    local function playerFiredLaser(playerFired, endPosition)
    local toolHandle = getPlayerToolHandle(playerFired)
    if toolHandle then
    eventsFolder.LaserFired:FireAllClients(playerFired, toolHandle, endPosition)
    end
    end

เรนเดอร์บนไคลเอนต์

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

  1. สร้าง สคริปท้องถิ่น ใน StarterPlayerScripts ที่เรียกว่า ClientLaserManager

  2. ภายในสคริปต์ต้องใช้โมดูล LaserRenderer

  3. สร้างฟังก์ชันชื่อ createPlayerLaser ด้วยพารามิเตอร์ playerWhoShot , toolHandle และ endPosition

  4. เชื่อมฟังก์ชันกับอีเวนต์ระยะไกล LaserFired ในโฟลเดอร์อีเวนต์

  5. ในฟังก์ชันใช้คำสั่ง ถ้า เพื่อตรวจสอบว่า playerWhoShot ไม่เท่ากับ LocalPlayer

  6. ภายในคำสั่ง if เรียกฟังก์ชัน createLaser จากโมดูล LaserRenderer โดยใช้ toolHandle และ endPosition เป็นอาร์กิวเมนต์


    local Players = game:GetService("Players")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local LaserRenderer = require(script.Parent:WaitForChild("LaserRenderer"))
    local eventsFolder = ReplicatedStorage.Events
    -- แสดงเลเซอร์ของผู้เล่นอีกคน
    local function createPlayerLaser(playerWhoShot, toolHandle, endPosition)
    if playerWhoShot ~= Players.LocalPlayer then
    LaserRenderer.createLaser(toolHandle, endPosition)
    end
    end
    eventsFolder.LaserFired.OnClientEvent:Connect(createPlayerLaser)
  7. ทดสอบเบลาสเตอร์ด้วยผู้เล่น 2 คนโดยเริ่มเซิร์ฟเวอร์ท้องถิ่นตำแหน่งแต่ละไคลเอนต์บนด้านต่างๆ ของมอนิเตอร์ของคุณเพื่อให้คุณสามารถมองเห็นทั้งสองหน้าต่างได้พร้อมกันเมื่อคุณยิงบนไคลเอนต์เดียวคุณควรเห็นเลเซอร์บนไคลเอนต์อื่น

เอฟเฟกต์เสียง

เอฟเฟกต์เสียงการยิงปัจจุบันเล่นเฉพาะบนไคลเอนต์ที่ยิงกระสุนเท่านั้นคุณจะต้องย้ายโค้ดเพื่อเล่นเสียงเพื่อให้ผู้เล่นคนอื่นได้ยินเช่นกัน

  1. ในสคริปต์ ToolController ค้นหาฟังก์ชัน toolActivated และลบบรรทัดที่เล่นเสียงเปิดใช้งาน


    local function toolActivated()
    if canShootWeapon() then
    fireWeapon()
    end
    end
  2. ที่ด้านล่างของฟังก์ชัน createLaser ใน LaserRenderer ประกาศตัวแปรชื่อ ยิงเสียง และใช้วิธี FindFirstChild() ของ toolHandle เพื่อตรวจสอบเสียง เปิดใช้งาน

  3. ใช้คำสั่ง ถ้า เพื่อตรวจสอบว่ามี shootingSound หรือไม่; ถ้ามีให้โทรไปที่ฟังก์ชัน เล่น ของมัน


    laserPart.Parent = workspace
    -- เพิ่มลำแสงเลเซอร์ในบริการกำจัดเศษซากที่จะถูกลบและทำความสะอาด
    Debris:AddItem(laserPart, SHOT_DURATION)
    -- เล่นเสียงการยิงของอาวุธ
    local shootingSound = toolHandle:FindFirstChild("Activate")
    if shootingSound then
    shootingSound:Play()
    end
    end

รักษารีโมทโดยใช้การตรวจสอบ

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

การตรวจสอบคือกระบวนการตรวจสอบว่ามูลค่าที่ส่งไปยังเซิร์ฟเวอร์มีความเป็นจริง ในกรณีนี้เซิร์ฟเวอร์จะต้อง:

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

ไคลเอนต์

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

  1. ใน ToolController นำทางไปยังบรรทัดที่ DamageCharacter รีโมทอีเวนต์ถูกเรียกในฟังก์ชัน fireWeapon

  2. เพิ่ม hitPosition เป็นอาร์กิวเมนต์


    if characterModel then
    local humanoid = characterModel:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    eventsFolder.DamageCharacter:FireServer(characterModel, hitPosition)
    end
    end

เซิร์ฟเวอร์

ตอนนี้ไคลเอนต์กำลังส่งพารามิเตอร์เพิ่มเติมผ่านอีเวนต์ระยะไกล DamageCharacter ดังนั้น ServerLaserManager จะต้องปรับเพื่อยอมรับมัน

  1. ในสคริปต์ ServerLaserManager เพิ่มพารามิเตอร์ hitPosition ให้กับฟังก์ชัน damageCharacter


    function damageCharacter(playerFired, characterToDamage, hitPosition)
    local humanoid = characterToDamage:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    -- ลบสุขภาพออกจากตัวละคร
    humanoid.Health -= LASER_DAMAGE
    end
    end
  2. ด้านล่างฟังก์ชัน getPlayerToolHandle สร้างฟังก์ชันชื่อ isHitValid ที่มีพารามิเตอร์สามตัว: playerFired , characterToDamage และ hitPosition


    end
    local function isHitValid(playerFired, characterToDamage, hitPosition)
    end

การตรวจสอบครั้งแรกจะเป็นระยะห่างระหว่างตําแหน่งที่โจมตีและตัวละครที่โจมตี

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


    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local eventsFolder = ReplicatedStorage.Events
    local LASER_DAMAGE = 10
    local MAX_HIT_PROXIMITY = 10
  2. ในฟังก์ชัน isHitValid คำนวณระยะห่างระหว่างตัวละครและตำแหน่งการโจมตีหากระยะเวลาใหญ่กว่า MAX_HIT_PROXIMITY จากนั้นจะส่งคืน เท็จ


    local function isHitValid(playerFired, characterToDamage, hitPosition)
    -- ตรวจสอบระยะห่างระหว่างตัวละครที่โจมตีและตำแหน่งที่โจมตี
    local characterHitProximity = (characterToDamage.HumanoidRootPart.Position - hitPosition).Magnitude
    if characterHitProximity > MAX_HIT_PROXIMITY then
    return false
    end
    end

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

  1. คัดลอกโค้ดด้านล่างเพื่อดำเนินการตรวจสอบนี้ คืน true ในตอนท้ายของฟังก์ชัน: ปิด


    local function isHitValid(playerFired, characterToDamage, hitPosition)
    -- ตรวจสอบระยะห่างระหว่างตัวละครที่โจมตีและตำแหน่งที่โจมตี
    local characterHitProximity = (characterToDamage.HumanoidRootPart.Position - hitPosition).Magnitude
    if characterHitProximity > 10 then
    return false
    end
    -- ตรวจสอบว่ายิงผ่านผนังหรือไม่
    local toolHandle = getPlayerToolHandle(playerFired)
    if toolHandle then
    local rayLength = (hitPosition - toolHandle.Position).Magnitude
    local rayDirection = (hitPosition - toolHandle.Position).Unit
    local raycastParams = RaycastParams.new()
    raycastParams.FilterDescendantsInstances = {playerFired.Character}
    local rayResult = workspace:Raycast(toolHandle.Position, rayDirection * rayLength, raycastParams)
    -- หากตัวอย่างถูกโจมตีที่ไม่ใช่ตัวละครแล้วเพิกเฉยการยิง
    if rayResult and not rayResult.Instance:IsDescendantOf(characterToDamage) then
    return false
    end
    end
    return true
    end
  2. ประกาศตัวแปรในฟังก์ชัน damageCharacter ที่เรียกว่า validShot กำหนดให้กับมันผลของการโทรไปที่ฟังก์ชัน isHitValid ด้วยสามอาร์กิวเมนต์: playerFired , characterToDamage และ hitPosition

  3. ในคำสั่ง if ด้านล่างเพิ่มตัวประกอบ และ เพื่อตรวจสอบว่า validShot เป็น จริง


    function damageCharacter(playerFired, characterToDamage, hitPosition)
    local humanoid = characterToDamage:FindFirstChildWhichIsA("Humanoid")
    local validShot = isHitValid(playerFired, characterToDamage, hitPosition)
    if humanoid and validShot then
    -- ลบสุขภาพออกจากตัวละคร
    humanoid.Health -= LASER_DAMAGE
    end
    end

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

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

รหัสสุดท้าย

ตัวควบคุมเครื่องมือ


local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LaserRenderer = require(Players.LocalPlayer.PlayerScripts.LaserRenderer)
local tool = script.Parent
local eventsFolder = ReplicatedStorage.Events
local MAX_MOUSE_DISTANCE = 1000
local MAX_LASER_DISTANCE = 500
local FIRE_RATE = 0.3
local timeOfPreviousShot = 0
-- ตรวจสอบว่าผ่านไปเวลาเพียงพอแล้วนับตั้งแต่ยิงครั้งล่าสุด
local function canShootWeapon()
local currentTime = tick()
if currentTime - timeOfPreviousShot < FIRE_RATE then
return false
end
return true
end
local function getWorldMousePosition()
local mouseLocation = UserInputService:GetMouseLocation()
-- สร้างลําแสงจากตําแหน่งเมาส์ 2D
local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
-- เวกเตอร์ทิศทางหน่วยของรังสีที่คูณด้วยระยะสูงสุด
local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
-- เรย์คาสต์จากจุดเริ่มต้นของ roy ไปยังทิศทางของมัน
local raycastResult = workspace:Raycast(screenToWorldRay.Origin, directionVector)
if raycastResult then
-- ส่งคืนจุดแยกที่ 3D
return raycastResult.Position
else
-- ไม่มีวัตถุถูกโจมตีดังนั้นจึงคำนวณตำแหน่งในตอนท้ายของรังสี
return screenToWorldRay.Origin + directionVector
end
end
local function fireWeapon()
local mouseLocation = getWorldMousePosition()
-- คำนวณเวกเตอร์ทิศทางปกติและคูณด้วยระยะทางเลเซอร์
local targetDirection = (mouseLocation - tool.Handle.Position).Unit
-- ทิศทางในการยิงอาวุธที่คูณด้วยระยะสูงสุด
local directionVector = targetDirection * MAX_LASER_DISTANCE
-- เพิกเฉยตัวละครของผู้เล่นเพื่อป้องกันไม่ให้พวกเขาทำลายตัวเอง
local weaponRaycastParams = RaycastParams.new()
weaponRaycastParams.FilterDescendantsInstances = {Players.LocalPlayer.Character}
local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
-- ตรวจสอบว่ามีวัตถุใดถูกโจมตีระหว่างตำแหน่งเริ่มต้นและสิ้นสุดหรือไม่
local hitPosition
if weaponRaycastResult then
hitPosition = weaponRaycastResult.Position
-- การโจมตีตัวอย่างจะเป็นลูกของโมเดลตัวละคร
-- หากพบหุ่นยนต์ในโมเดลแล้วมันอาจเป็นตัวละครของผู้เล่น
local characterModel = weaponRaycastResult.Instance:FindFirstAncestorOfClass("Model")
if characterModel then
local humanoid = characterModel:FindFirstChildWhichIsA("Humanoid")
if humanoid then
eventsFolder.DamageCharacter:FireServer(characterModel, hitPosition)
end
end
else
-- คำนวณตำแหน่งสุดท้ายตามระยะเลเซอร์สูงสุด
hitPosition = tool.Handle.Position + directionVector
end
timeOfPreviousShot = tick()
eventsFolder.LaserFired:FireServer(hitPosition)
LaserRenderer.createLaser(tool.Handle, hitPosition)
end
local function toolEquipped()
tool.Handle.Equip:Play()
end
local function toolActivated()
if canShootWeapon() then
fireWeapon()
end
end
tool.Equipped:Connect(toolEquipped)
tool.Activated:Connect(toolActivated)

เลเซอร์เรนเดอร์


local LaserRenderer = {}
local Debris = game:GetService("Debris")
local SHOT_DURATION = 0.15 -- เวลาที่เลเซอร์สามารถมองเห็นได้
-- สร้างลำแสงเลเซอร์จากตําแหน่งเริ่มต้นไปยังตําแหน่งสิ้นสุด
function LaserRenderer.createLaser(toolHandle, endPosition)
local startPosition = toolHandle.Position
local laserDistance = (startPosition - endPosition).Magnitude
local laserCFrame = CFrame.lookAt(startPosition, endPosition) * CFrame.new(0, 0, -laserDistance / 2)
local laserPart = Instance.new("Part")
laserPart.Size = Vector3.new(0.2, 0.2, laserDistance)
laserPart.CFrame = laserCFrame
laserPart.Anchored = true
laserPart.CanCollide = false
laserPart.Color = Color3.fromRGB(255, 0, 0)
laserPart.Material = Enum.Material.Neon
laserPart.Parent = workspace
-- เพิ่มลำแสงเลเซอร์ในบริการกำจัดเศษซากที่จะถูกลบและทำความสะอาด
Debris:AddItem(laserPart, SHOT_DURATION)
-- เล่นเสียงการยิงของอาวุธ
local shootingSound = toolHandle:FindFirstChild("Activate")
if shootingSound then
shootingSound:Play()
end
end
return LaserRenderer

ผู้จัดการเลเซอร์เซิร์ฟเวอร์


local ReplicatedStorage = game:GetService("ReplicatedStorage")
local eventsFolder = ReplicatedStorage.Events
local LASER_DAMAGE = 10
local MAX_HIT_PROXIMITY = 10
-- ค้นหาตัวจัดการของเครื่องมือที่ผู้เล่นกําลังถือ
local function getPlayerToolHandle(player)
local weapon = player.Character:FindFirstChildOfClass("Tool")
if weapon then
return weapon:FindFirstChild("Handle")
end
end
local function isHitValid(playerFired, characterToDamage, hitPosition)
-- ตรวจสอบระยะห่างระหว่างตัวละครที่โจมตีและตำแหน่งที่โจมตี
local characterHitProximity = (characterToDamage.HumanoidRootPart.Position - hitPosition).Magnitude
if characterHitProximity > MAX_HIT_PROXIMITY then
return false
end
-- ตรวจสอบว่ายิงผ่านผนังหรือไม่
local toolHandle = getPlayerToolHandle(playerFired)
if toolHandle then
local rayLength = (hitPosition - toolHandle.Position).Magnitude
local rayDirection = (hitPosition - toolHandle.Position).Unit
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {playerFired.Character}
local rayResult = workspace:Raycast(toolHandle.Position, rayDirection * rayLength, raycastParams)
-- หากตัวอย่างถูกโจมตีที่ไม่ใช่ตัวละครแล้วเพิกเฉยการยิง
if rayResult and not rayResult.Instance:IsDescendantOf(characterToDamage) then
return false
end
end
return true
end
-- แจ้งให้ลูกค้าทั้งหมดทราบว่ามีการยิงเลเซอร์เพื่อให้พวกเขาสามารถแสดงเลเซอร์ได้
local function playerFiredLaser(playerFired, endPosition)
local toolHandle = getPlayerToolHandle(playerFired)
if toolHandle then
eventsFolder.LaserFired:FireAllClients(playerFired, toolHandle, endPosition)
end
end
function damageCharacter(playerFired, characterToDamage, hitPosition)
local humanoid = characterToDamage:FindFirstChildWhichIsA("Humanoid")
local validShot = isHitValid(playerFired, characterToDamage, hitPosition)
if humanoid and validShot then
-- ลบสุขภาพออกจากตัวละคร
humanoid.Health -= LASER_DAMAGE
end
end
-- เชื่อมต่อเหตุการณ์กับฟังก์ชันที่เหมาะสม
eventsFolder.DamageCharacter.OnServerEvent:Connect(damageCharacter)
eventsFolder.LaserFired.OnServerEvent:Connect(playerFiredLaser)

ผู้จัดการเลเซอร์ลูกค้า


local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LaserRenderer = require(Players.LocalPlayer.PlayerScripts:WaitForChild("LaserRenderer"))
local eventsFolder = ReplicatedStorage.Events
-- แสดงเลเซอร์ของผู้เล่นอีกคน
local function createPlayerLaser(playerWhoShot, toolHandle, endPosition)
if playerWhoShot ~= Players.LocalPlayer then
LaserRenderer.createLaser(toolHandle, endPosition)
end
end
eventsFolder.LaserFired.OnClientEvent:Connect(createPlayerLaser)