Lazerlerle Görünüm Takibi

*Bu içerik, yapay zekâ (beta) kullanılarak çevrildi ve hatalar içerebilir. Sayfayı İngilizce görüntülemek için buraya tıkla.

Bu öğretici, lazeri Oyuncu Aletlerini Oluşturma blasterinden nasıl kullanacağınızı öğretecek ve bir oyuncuya vurup vurmadığını tespit edecek.

Çarpışma Bulmak için Raycasting

Raycasting başlangıç pozisyonundan itibaren belirli bir yöne doğru görünmez bir ray oluşturur. Eğer ışın kaynağının yolunun üstünde nesneler veya arazi ile çarpışırsa, çarpışma konusunda ara bilgisi döndürür. Bu, konum ve çarpıştığı nesne gibi yolunuzun üzerindeki nesneleri içerir.

Duvarla çarpışan A'dan B'ye ışınlanma kasti

Farenin Konumunu Bulma

Lazer atışlanmadan önce, oyuncunun nereye nişan alacağını ilk olarak bilmelisiniz. Bu, oyuncunun 2D mouse'ının ekranda doğrudan kamera tarafından ileriye gönderilmiş yerinde raycasting yaparak bulunabilir. Oyun dünyasındaki fareçarpışacaktır.

  1. Oyuncu Araçları Oluşturucu içindeki AraçKontrolörü scriptini açın. Eğer oyunu tamamlamadıysanız, Blaster modelini indirebilir ve StarterPack'e kaydederken kullanabilirsiniz.

  2. Skriptinizin başında, 1000 ile bir konum belirleyin.

  3. getWorldMousePosition adında bir işlev oluştur.


    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
    -- Olayları uygun işlevlere bağlayın
    tool.Equipped:Connect(toolEquipped)
    tool.Activated:Connect(toolActivated)
  4. Ekranda oyuncunun 2D mouse konumunu almak için UserInputService 의 GetMouseLocation işlevini kullanın. Bu, mouseLocation adlı değişkeni atayın.


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

Şimdi 2D fare konumu biliniyor, onun X ve Y özellikleri Class.Camera:ViewportPointToRay() fonksiyonu için parametre olarak kullanılabilir, bu da ekrandanı 3D oyun dünyasına oluşturan bir 1> Datatype.Ray1> oluşturur.

  1. X ve Y özelliklerini kullanırken mouseLocation ile bir 1> Class.Camera:ViewportPointToRay()|ViewportPointToRay()1> işlevi için bir argüman olarak kullanın. Bu, 4> screenToWorldRay4> adlı bir değişkeni kullanarak atayın.

local function getWorldMousePosition()
local mouseLocation = UserInputService:GetMouseLocation()
-- 2D fare konumundan bir ışın oluştur
local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
end

Raycast'ı kullanarak objeye ışınlanıp ışınlanmadığını kontrol etme zamanı geldi. Bu, bir başlangıç ​​pozisyonu ve yön vektörü gerektirir: Bu ö例mde, Raycast 'in orijinal ve yön özelliklerini kullanacaksınız.

Yön vektörünün uzunluğu, ışının seyahat etmesi için ne kadar uzun olacağını belirler. Işın MAX_MOUSE_DISTANCE uzunluğundan olmalıdır, bu yüzden yön vektörünü MAX_MOUSE_DISTANCE ile çarpmalısınız.

  1. directionVector adında bir değişkeni ilan et ve screenToWorldRay.Direction ile çarpan MAX_MOUSE_DISTANCE değerine sahip.


    local function getWorldMousePosition()
    local mouseLocation = UserInputService:GetMouseLocation()
    -- 2D fareLocation'inden bir ray oluştur
    local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    -- Işının maksimum mesafeyle çarpan birimi direktörü
    local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
  2. Çalışma alanındaki Raycast işlevini çağırın, screenToWorldRaynın ilk argümanı olarak screenToWorldRay özelliğini kullanarak ortak olarak verin ve 2>raycastResult2> olarak ikinci olarak. Bu, 5>raycastResult5> adlı değişkeni


    local function getWorldMousePosition()
    local mouseLocation = UserInputService:GetMouseLocation()
    -- 2D fareLocation'inden bir ray oluştur
    local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    -- Işının maksimum mesafeyle çarpan birimi direktörü
    local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
    -- Ray'in yönüne doğru uzay kayışı
    local raycastResult = workspace:Raycast(screenToWorldRay.Origin, directionVector)

Çarpışma Bilgisi

Raycast operasyonu bir raya vurulan bir nesneyi bulursa, bir RaycastResult döndürür, bu, ray ve nesne arasındaki çarpışma hakkında bilgi içerir.

RaycastResult ÖzelliğiAçıklama
Oyuncu InstancesıIşının kesiştiği BasePart veya Terrain hücre.
PozisyonÇarpışma nerede gerçekleşir; genellikle bir noktanın yüzeyinde doğrudan bir noktadır.
MalzemeÇarpışma noktasındaki malzeme.
NormalKesişmiş yüzün normal vektörü. Bu, yüzün hangi yönde olduğunu belirlemek için kullanılabilir.

Pozisyon özelliği, farenin üzerinde durduğu nesnenin pozisyonu olacaktır. Eğer fare MAX_MOUSE_DISTANCE içinde herhangi bir nesneye değilse, raycastResult nil olacaktır.

  1. raycastResult ile ilgili olup olmadığını kontrol etmek için bir if oluşturun.

  2. Eğer raycastResult bir değeri varsa, onun Position özelliğini döndür.

  3. Eğer raycastResult boşsa, ışınlanmanın sonunu bulun. screenToWorldRay.Origin ile ışınlanmanın 3D konumunu hesaplayın, directionVector ile birlikte.


local function getWorldMousePosition()
local mouseLocation = UserInputService:GetMouseLocation()
-- 2D fareLocation'inden bir ray oluştur
local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
-- Işının maksimum mesafeyle çarpan birimi direktörü
local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
-- Ray'in yönüne doğru uzay kayışı
local raycastResult = workspace:Raycast(screenToWorldRay.Origin, directionVector)
if raycastResult then
-- 3D kesişim noktasını iade edin
return raycastResult.Position
else
-- Hiçbir nesneye vurulmadığı için, ışının sonundaki pozisyonu hesaplayın
return screenToWorldRay.Origin + directionVector
end
end

Hedefe Doğru Ateşleniyor

Artık 3D mouse pozisyonu biliniyor, bir lazerın doğru yönünü vurmak için kullanılabilir bir hedef pozisyonu . Bir ikinci ışın oyuncunun silahından hedef pozisyonuna kullanılabilir Raycast işlevi kullanılır.

  1. Scriptinizin üstündeki MAX_LASER_DISTANCE değerini ilan et ve onu 500 veya lazer makinesi için seçtiğin menziliye atla.


    local UserInputService = game:GetService("UserInputService")
    local tool = script.Parent
    local MAX_MOUSE_DISTANCE = 1000
    local MAX_LASER_DISTANCE = 500
  2. fireWeapon adında bir işlev oluşturun getWorldMousePosition işlevi altında.

  3. getWorldMousePosition çağırın ve sonucu mousePosition değişkenine atayın. Bu, raycast için hedef pozisyonu olacaktır.


    -- Hiçbir nesneye vurulmadığı için, ışının sonundaki pozisyonu hesaplayın
    return screenToWorldRay.Origin + directionVector
    end
    end
    local function fireWeapon()
    local mouseLocation = getWorldMousePosition()
    end
    local function toolEquipped()
    tool.Handle.Equip:Play()
    end

Bu sefer, raycast işlevinin yön vektörü, oyuncunun alet pozisyonundan hedef konumuna yönü temsil edecektir.

  1. Hedef Yönü adındaki bir değişkeni ilan edin ve araç pozisyonunu mouseLocation 'den çıkararak yön vektörünü hesaplayın.

  2. Vektörü normalize etmek için onun Unit özelliğini kullanın. Bu, onu daha sonra uzunluğa çarpanmak için kolaylıkla 1 büyüklüğünde yapar.


    local function fireWeapon()
    local mouseLocation = getWorldMousePosition()
    -- Normal bir yön vektörü hesaplayın ve lazer mesafesi ile çarpan
    local targetDirection = (mouseLocation - tool.Handle.Position).Unit
    end
  3. Bir çeşyayı DirectionVector adında ilan et ve targetDirection ile çarpan MAX_LASER_DISTANCE değerine sahip ol.


    local targetDirection = (mouseLocation - tool.Handle.Position).Unit
    -- Silahı ateş etmenin yönü, maksimum mesafe ile çarpan
    local directionVector = targetDirection * MAX_LASER_DISTANCE
    end

Bir RaycastParams nesnesi, raycast için ek göstergeleri depolamak için kullanılabilir. It will be used in your laser blaster to make sure the raycast doesn't accidentally collide with the player firing the weapon. Any parts included in the FilterDescendantsInstances property

  1. fireWeapon işlevini devam ettirin ve bir değişken olan SilahRaycastParams 'yi ilan edin. Yeni bir RaycastParams nesline atın.

  2. oyuncuyerel karakterini içeren bir tab oluştur ve weaponRaycastParams.FilterDescendantsInstances özelliğine atla.

  3. oyuncualet kolu pozisyonundan, bir yönde directionVector 'e doğru şekilde weaponRaycastParams ekleyin. Bu sefer weaponRaycastParams olarak bir argüman ekleyin. Bu değişkeni 2> silahRaycastResult2> olarak atayın.


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()
-- Normal bir yön vektörü hesaplayın ve lazer mesafesi ile çarpan
local targetDirection = (mouseLocation - tool.Handle.Position).Unit
-- Silahı ateş etmenin yönü maksimum mesafe ile çarpan bir mesafe arttırılır
local directionVector = targetDirection * MAX_LASER_DISTANCE
-- oyuncukarakterini görmezden gelin, onların kendilerine zarar vermesini önleyin
local weaponRaycastParams = RaycastParams.new()
weaponRaycastParams.FilterDescendantsInstances = {Players.LocalPlayer.Character}
local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
end

Son olarak, raycast operasyonunun bir değer döndürdüğünden emin olmalısınız. Eğer bir değer döndürülürse, bir obje silahın yanında oluşturulur ve bir lazer oluşturulur. Hiçbir şey döndürülmediyse, lazer oluşturmak için son pozisyon hesaplanmalıdır.

  1. Boş bir değer oluşturarak hitPosition adında bir boş değer ilan edin.

  2. Bir if ifadesini kullanarak weaponRaycastResult ın bir değeri olup olmadığını kontrol edin. Eğer bir nesne vurulursa, weaponRaycastResult.Position ın 1> hitPosition1> ına atın.


    local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
    -- Başlangıç ve son pozisyonları arasında herhangi bir nesneye vurulup vurulmadığını kontrol edin
    local hitPosition
    if weaponRaycastResult then
    hitPosition = weaponRaycastResult.Position
    end
  3. Eğer weaponRaycastResult hiç değer yoksa, pozyon ı alet başlığı ile birleştirerek directionVector hesaplayın. Bu değeri 1>hataPosition1> ile atayın.


    local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
    -- Başlangıç ve son pozisyonları arasında herhangi bir nesneye vurulup vurulmadığını kontrol edin
    local hitPosition
    if weaponRaycastResult then
    hitPosition = weaponRaycastResult.Position
    else
    -- Maksimum lazer mesafasına dayanarak son pozisyonu hesap et
    hitPosition = tool.Handle.Position + directionVector
    end
    end
  4. Navigate to the toolActivated function and call the fireWeapon function so that the laser fires each time the tool is activated.


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

Nesne Hit'ini Kontrol Etme

Lazer tarafından vurulan nesnenin bir oyuncunun karakteri parçası olduğunu veya sadece bir manzara parçası olduğunu bulmak için bir Humanoid arayın, her karaktere bir tane var.

İlk olarak, karakter modelini bulmanız gerekir. Eğer karakterin bir kısmı vurulursa, vurulan karakterin ebeveyni olarak karakteri varsayamazsınız. Laser bir vücut bölgesine, bir aksesuara veya bir alete vurabilir, tüm bu bölgeler karakterin hierarjisinde bulunur.

Lazer tarafından vurulan bir nesnenin karakter modeli atalarını bulmak için FindFirstAncestorOfClass kullanabilirsiniz, varsa. Eğer bir model varsa ve bir insanoid içeriyorsa, çoğu durumda bunu bir karakter olarak varsayabilirsiniz.

  1. Bir karakterin vurulup vurulmadığını kontrol etmek için weaponRaycastResultif if statement'ına bir kod ekleyin.


    -- Başlangıç ve son pozisyonları arasında herhangi bir nesneye vurulup vurulmadığını kontrol edin
    local hitPosition
    if weaponRaycastResult then
    hitPosition = weaponRaycastResult.Position
    -- İstek edilen instans bir karakter modelinin bir çocuğu olacaktır
    -- Bir humanoid modelinde bulunursa, muhtemelen bir oyuncu karakteridir
    local characterModel = weaponRaycastResult.Instance:FindFirstAncestorOfClass("Model")
    if characterModel then
    local humanoid = characterModel:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    print("Player hit")
    end
    end
    else
    -- Maksimum lazer mesafasına dayanarak son pozisyonu hesap et
    hitPosition = tool.Handle.Position + directionVector
    end

Şimdi lazer blaster herhangi bir oyuncu tarafından vurulduğunda Player hit çıkış penceresine yazdırmalıdır.

Çok Oyunculu Test

Silah ışınlanma aracının başka oyuncuları bulup bulmadığını test etmek için iki oyuncu gerekli, bu yüzden yerel bir sunucuya başlatmanız gerekir.

  1. Stüdyo'daki Test seklini seçin.

  2. Oyuncuların menüsünü '2 Oyuncu' olarak ayarladığından emin olun ve Başlat düğmesine tıklayarak başlat bir yerel sunucuyu 2 istemcisiyle başlatın. Üç pencere görüntülenir. İlk pencere yerel sunucu olacak, diğer pencereler Player1 ve Player2 için istemciler olacak.

  3. Bir klijüste, diğer oyuncuya silahla tıklayarak test atışını test edin. "Player hit" her oyuncu vurulduğunda çıktıda görüntülenmelidir.

Test buradan sayfasında daha fazlasını öğrenebilirsiniz.

Lazer Konumunu Bulma

Blaster hedefine kırmızı bir ışın atmalıdır. Bunun için kullanılan işlev ModuleScript içine olacaktır, böylece daha sonra başka kodlarda kullanılabilir. İlk olarak, kodun laser ışınının renderlenmesi gereken yerini bulması gerekir.

  1. Bir ModuleScript oluştur, LaserRender adında, StarterPlayerScripts altındaki ebeveyni.

  2. Scripti aç ve modül tablosunu LaserRender isimine yeniden adlandır.

  3. Lazerin görünür olduğu süreyi belirtmek için SHOT_DURATION adlı bir değişkeni kullanın. Bu, lazerin görünür olduğu süreyi (saniye olarak) belirtir.

  4. LaserRender'ın bir işlevini oluştur createLaser ile iki parametreli toolHandle ve endPosition .


    local LaserRenderer = {}
    local SHOT_DURATION = 0.15 -- Lazerin görünür olması için
    -- Bir lazer kaynağından bir başlangıç ​​pozisyonuna kadar bir son pozisyon oluştur
    function LaserRenderer.createLaser(toolHandle, endPosition)
    end
    return LaserRenderer
  5. Bir çeşyayı başlangıç pozisyonu olarak adlandır ve pozyon özelliğini toolHandle olarak değer olarak ayarla. Bu, oyuncunun lazer silahının pozisyonunu olacak.

  6. Lazer mesafesini lazerDistance olarak deklare ve endPosition 'i startPosition 'den çıkararak iki vektör arasındaki farkı bulmak için kullanın. Bu öğünkü 1> Büyüklüğü1> özelliğini kullanarak lazer ışını uzunluğunu elde edebilirsiniz.


    function LaserRenderer.createLaser(toolHandle, endPosition)
    local startPosition = toolHandle.Position
    local laserDistance = (startPosition - endPosition).Magnitude
    end
  7. Bir laserCFrame değişkenini depolamak için lazer ışınının konumunu ve yönünü. Konum, başlangıç ve sonu iletkenin orta noktası olmalıdır. Kullanmak i


    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

Lazer Parçası Oluşturulması

Lazer gücünü oluşturacak yeri biliyorsunuz, şimdi güç için kendi başına eklemelisiniz. Bu, bir Neon parçasıyla kolayca yapılabilir.

  1. Bir değişken laserPart ilan et ve ona yeni bir Part durumatla.

  2. laserPart 'in aşağıdaki özelliklerini ayarlar:

    1. Boyut : Vector3.new(0.2, 0.2, laserDistance)
    2. CFrame : laserCFrame
    3. Sabitlenmiş : doğru
    4. Çarpışabilir miyim : false
    5. Rengi : Color3.fromRGB(225, 0, 0) (güçlü bir kırmızı renk)
    6. Malzeme : Enum.Material.Neon
  3. Ana laserPart Çalışma Alanı .

  4. Parçayı Debris hizmetine ekleyin, böylece SHOT_DURATION değişkeninin miktarından sonra kaldırılır.


    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
    -- Kayıp parçalar hizmetine lazer gecesi ekleyin ve temizle
    Debris:AddItem(laserPart, SHOT_DURATION)
    end

Lazer ışınını oluşturan işlev artık tamamlandı, Araç Kontrolörü olarak adlandırılabilir.

  1. AraçKontrolörü scriptinin yukarı kısmında, LaserRender adında bir değişken ilan et ve PlayerScripts'de bulunan LaserRender Modülü Kısmını gerektir.


    local UserInputService = game:GetService("UserInputService")
    local Players = game:GetService("Players")
    local LaserRenderer = require(Players.LocalPlayer.PlayerScripts.LaserRenderer)
    local tool = script.Parent
  2. fireWeapon işlevinin altında, araç kolu ile LaserRender createLaser işlevini çağırın ve hitPosition ile argeler olarak kullanın.


    -- Maksimum lazer mesafasına dayanarak son pozisyonu hesap et
    hitPosition = tool.Handle.Position + directionVector
    end
    LaserRenderer.createLaser(tool.Handle, hitPosition)
    end
  3. Silahı test etmek için Oyna düğmesine tıklayın. Bir lazer gücü, alet etkinleştirildiğinde silah ve fare arasında görünmelidir.

Silah Ateş Hızını Kontrol Etme

Silahlar, oyuncuların çok fazla hasar vermesini önlemek için her atış arasında bir gecikmeye ihtiyaç duyar. Bu, bir oyuncu son kez ateş ettiğinden beri yeterli süre geçmişかどうか kontrol ederek kontrol edilebilir.

  1. Araç Kontrolcüsü'nün üstünde bir değişken ilan et Ateş Hızı . Bu, her atış arasındaki minimum zaman olacaktır. Ona seçtiğin değer ver; bu örnek 0.3 saniye kullanıyor.

  2. Aşağıdaki timeOfPreviousShot adındaki başka bir değişkeni 0 değerinde aşağıda ilan etmek. Bu, oyuncunun ateş ettiği son kez güncellenir ve her atışla güncellenecek.


    local MAX_MOUSE_DISTANCE = 1000
    local MAX_LASER_DISTANCE = 300
    local FIRE_RATE = 0.3
    local timeOfPreviousShot = 0
  3. Bir parametre olmadan canShootWeapon adında bir işlev oluşturun. Bu işlev, önceki atıştan bu yana kaç saniye olduğunu gözden geçirecek ve geri dönüşümüzü doğru veya yanlış yapacaktır.


    local FIRE_RATE = 0.3
    local timeOfPreviousShot = 0
    -- Önceki atıştan sonra yeterli süre geçmiş olup olmadığını kontrol edin
    local function canShootWeapon()
    end
    local function getWorldMousePosition()
  4. İşlevin içinde currentTime adında bir değişken ilan edin; bu, tick() işlevinin sonucunu atar. Bu, 1. Ocak 1970'den beri (genel olarak kullanılan herhangi bir tarih) itibariyle kaç saniye olduğunu gösterir.

  5. timeOfPreviousShot ‘i currentTime ‘den çıkar ve sonuç FIRE_LETE ‘den daha küçükse 1> false1> ‘i döndür; aksi takdirde 4> true4> döndür.


-- Önceki atıştan sonra yeterli süre geçmiş olup olmadığını kontrol edin
local function canShootWeapon()
local currentTime = tick()
if currentTime - timeOfPreviousShot < FIRE_RATE then
return false
end
return true
end
  1. fireWeapon işlevinin sonunda, silahın ateşlenmesi her seferinde timeOfPreviousShot güncellemeyi gösterir.


    hitPosition = tool.Handle.Position + directionVector
    end
    timeOfPreviousShot = tick()
    LaserRenderer.createLaser(tool.Handle, hitPosition)
    end
  2. toolActivated işlevinin içinde, bir if ifadesini oluşturun ve silahı ateş etmeyi kontrol etmek için canShootWeapon ı arayın.


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

Blaster'ı test ettiğinizde, ne kadar hızlı tıkladığınıza bağlı olarak, her atış arasında daima kısa bir 0.3 saniye gecikme olacağını bulmalısınız.

Oyuncuya Hasar Verme

İstemciler diğer istemcilere doğrudan hasar veremez; sunucunun bir oyuncuya vurduğunda hasar vermeyi sorumlu olması gerekir.

Müşteriler, bir karakterin vurulduğunu söylemek için bir RemoteEvent kullanabilir. Bunlar ReplicatedStorage , bunların herhangi bir müşteri ve sunucu tarafından görüntülenebileceği yer olmalıdır.

  1. Etkinlikler adında ReplicatedStorage içinde bir Dizin Oluştur.

  2. Etkinlikler klasına bir uzaktan etkinliği ekleyin ve ona şu adı verin DamageCharacter .

  3. In ToolController , script'in başlangıcındaki değişkenleri ReplicatedStorage ve Etkinlikler klasörleri için oluşturun.


    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. DamageCharacter uzaktan etkinliğiyle ilgili fireWeapon iletişimini bir Lua satırıyla değiştirerek 1>Player hit1> iletişimini değiştirin.


    local characterModel = weaponRaycastResult.Instance:FindFirstAncestorOfClass("Model")
    if characterModel then
    local humanoid = characterModel:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    eventsFolder.DamageCharacter:FireServer(characterModel)
    end
    end
    else
    -- Maksimum lazer mesafasına dayanarak son pozisyonu hesap et
    hitPosition = tool.Handle.Position + directionVector
    end

Olay başlatıldığında oyuncuya hasar vermesi gerekir.

  1. ServerScriptService'e bir Script kaydeder ve ismini ServerLaserManager olarak değiştirir.

  2. LASER_DAMAGE adında bir değişkeni ilan et ve 10 değerini veya seçimin değerini ayarla.

  3. İki damageCharacter ve karakterToDamage ile adlandırılmış iki parametreli bir işlev oluşturun.

  4. İşlevin içinde, karakterin Humanoid'ini bulun ve sağlığından LASER_DAMAGE azaltın.

  5. Etkinleştirici damageCharacter işlevini Etkinleştirici Karakteri sayfasına bağlayın.


    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
    -- Karakterden sağlığı kaldır
    humanoid.Health -= LASER_DAMAGE
    end
    end
    -- Olayları uygun işlevlere bağlayın
    eventsFolder.DamageCharacter.OnServerEvent:Connect(damageCharacter)
  6. Blaster'ı 2 oyuncu ile birlikte test etmek için bir yerel sunucuyu başlatın. Diğer oyuncuya ateş ettiğinizde, onların sağlığı LASER_DAMAGE ile azalacaktır.

Diğer Oyuncunun Laser Işınlarını Görüntüleme

Mürettebatın silahı ateş ettiği anda silahın görüntüsü laser olarak oluşturulur, böylece sadece mürettebatın silahını görebilir.

Lazer ışını servis器de oluşturulduysa, herkes bunu görebilirdi. Ancak, silahı vuran klien ve sunucu arasında küçük bir gecikme olurdu. Bu, silahı vuran klienin silahı görmesinin arttırıcı olacağını ifade eder. Klien silahı etkisiz hale getirir.

Bu sorunu çözmek için, her klien kendi lazer ışınlarını oluşturacak. Bu, silahı vuran klienin lazer ışınını anında göreceği anlamına gelir. Diğer klienler, bir oyuncunun silahı vurduğunda ve bir ışın göründüğünde arasında bir küçük gecikmeyi deneyecek. Bu en iyi senaryo durumudur: bir klienin

Tüfek Klient

İlk olarak, istemci bir lazeri ateşlediğini söylemelidir ve son pozisyonu sağlamalıdır.

  1. ReplicatedStorage'daki Etkinlikler'e bir Uzaktan Etkinlik Etkinleştirici ekleyin ve ismini LaserFired olarak değiştirin.

  2. Arayın fireWeapon işlevini ArayıcıKontrolör yazılımında bulun. Fonksiyonun sonunda, LaserFired uzaktaki etkinliği 1> hitPosition1> olarak bir argüman olarak ateş edin.


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

Sunucu

Sunucu artık etkinliği almalı ve tüm müşterileri laser ışınının başlangıcını ve sonunu bilmelidir, böylece onu da rendeleyebilirler.

  1. In the ServerLaserManager script, create a function named playerFiredLaser above damageCharacter with two parameters called 1> playerFired1> and 4> endPosition4> .

  2. İşlevi LaserFired uzaktaki etkinliğine bağlayın.


    -- Lazerın ateşlendiğini tüm müşterilerin görebilmesi için bildir
    local function playerFiredLaser(playerFired, endPosition)
    end

    -- Olayları uygun işlevlere bağlayın
    eventsFolder.DamageCharacter.OnServerEvent:Connect(damageCharacter)
    eventsFolder.LaserFired.OnServerEvent:Connect(playerFiredLaser)

Sunucunun lazerin başlangıç pozisyonuna ihtiyacı vardır. Bu, mümkün olduğunca klije gönderilebilir, ancak mümkün olduğunca çok klijeye güvenmekten kaçınmanız gerekir. Karakterin silah tutuş pozisyonu, sunucunun onu bulmasından önce klije olabilir.

  1. Aşağıdaki oyuncu ile ilgili işlevi oluştur playerFiredLaser şunu yap:

  2. Silah için oyuncunun karakterini aramak için aşağıdaki kodu kullanın ve bağlantı nesnesini iade edin.


    local LASER_DAMAGE = 10
    -- Oyuncunun tutduğu aracın etiketini bulun
    local function getPlayerToolHandle(player)
    local weapon = player.Character:FindFirstChildOfClass("Tool")
    if weapon then
    return weapon:FindFirstChild("Handle")
    end
    end
    -- Lazerın ateşlendiğini tüm müşterilerin görebilmesi için bildir
    local function playerFiredLaser(playerFired, endPosition)

Sunucu artık LaserFired uzaktaki etkinliğine FireAllClients çağrabilir ve gerekli bilgileri göndermek için laserı müşterilere göndermek için gereken bilgileri gönderir. Bunun içinde laserı ateşleyen oyuncu (böylece müşterinin laseri iki kat görmediğ

  1. In the playerFiredLaser function, call the getPlayerToolHandle function with playerFired as an argument andassign the value to a variable named 1> toolHandle1> .

  2. Eğer toolHandle 存在sa, playerFired etkinliğini kullanarak tüm müşterileri toolHandle, 1> toolHandle1> ve 4> endPosition4> olarak argüman olarak yanlatın.


    -- Lazerın ateşlendiğini tüm müşterilerin görebilmesi için bildir
    local function playerFiredLaser(playerFired, endPosition)
    local toolHandle = getPlayerToolHandle(playerFired)
    if toolHandle then
    eventsFolder.LaserFired:FireAllClients(playerFired, toolHandle, endPosition)
    end
    end

Clients'ta Rendering

Şimdi FireAllClients çağrıldı, her klienin laser ışınını göndermek için sunucudan bir etkinliği alacak. Her klienin aletinin el ve bir son pozisyon değerini kullanarak lazer ışınını göndermesini gerektiren birazcığı vardır. Laser ışınını ilk yerden

  1. StarterPlayerScripts'in ClientLaserManager adlı oyununun bir Yerel Kod oluştur.

  2. Script içinde, LaserRender modülünü gerektirir.

  3. Aşağıdaki parametrelerle PlayerLaser adında bir işlev oluşturun: playerWhoShot, toolHandle ve 1> endPosition1> .

  4. İşlevi LaserFired olayına uzaktaki etkinliğine bağlayın.

  5. İşlevde, if ifadesini kullanarak LocalPlayer ile eşit olup olmadığını kontrol edin.

  6. if ifadesinin içinde, LaserRender modülünden LaserRender modülüne createLaser işlevini toolHandle ve endPosition olarak argüman olarak çağırın.


    local Players = game:GetService("Players")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local LaserRenderer = require(script.Parent:WaitForChild("LaserRenderer"))
    local eventsFolder = ReplicatedStorage.Events
    -- Başka bir oyuncunun lazerini göster
    local function createPlayerLaser(playerWhoShot, toolHandle, endPosition)
    if playerWhoShot ~= Players.LocalPlayer then
    LaserRenderer.createLaser(toolHandle, endPosition)
    end
    end
    eventsFolder.LaserFired.OnClientEvent:Connect(createPlayerLaser)
  7. Blaster'ı 2 oyuncu ile test etmek için bir yerel sunucuyu başlatarak. Her bir klienin monitörünüzün farklı taraflarında yerini görebilmeniz için. 1 oyuncu üzerinde çektiğinizde lazeri diğer kliende görmelisiniz.

Ses efektleri

Projeleri vuran kliğin sesi etkisi sadece vuran kliğin sesi etkisi olarak kodu hareket ettirmeniz gerekir. Aksi takdirde, diğer oyuncular da duyacaktır.

  1. AraçKontrolörü scriptinde, AçıldığınızAraçlar işlevine gidin ve etkinleştirme sesini çalan satırı kaldırın.


    local function toolActivated()
    if canShootWeapon() then
    fireWeapon()
    end
    end
  2. LaserRender İçindeki createLaser işlevinin altında, shootingSound adında bir değişken ilan et ve Class.Instance:FindFirstChild()|FindFirstChild() yöntemini kullanarak 4>Aktivate4> sesini kontrol etmek için kullan.

  3. Eğer mevcutsa shootingSound değerini kontrol etmek için bir shootingSound ifadesini kullanın; eğer mevcutsa, Oyna işlevini çağırın.


    laserPart.Parent = workspace
    -- Kayıp parçalar hizmetine lazer gecesi ekleyin ve temizle
    Debris:AddItem(laserPart, SHOT_DURATION)
    -- Silahın atış sesini oynat
    local shootingSound = toolHandle:FindFirstChild("Activate")
    if shootingSound then
    shootingSound:Play()
    end
    end

Kurallara Uygunluk Kullanılarak Uzaktan Güvenli Erişim

Eğer sunucu gelen isteklerden gelen verileri kontrol etmiyorsa, bir hacker uzaktan işlevleri ve etkinlikleri kötüye kullanabilir ve bunları kullanarak sahte değerleri sunucuya gönderebilir. Bunu önlemek için sunucu-taraflı doğrulama kullanılmalıdır.

Mevcut formunda, HasarKarakteri uzaktaki etkinliği çok kolay saldırıya maruz kalır. Hacker bu etkinliği kullanarak oyunu oynadığı herhangi bir oyuncuya hasar verebilir.

Geçerlileştirme, sunulan değerlerin gerçek olduğunu doğrulama sürecidir. Bu durumda, sunucunun:

  • Oyuncu ve lazerin vurduğu pozisyon arasındaki mesafeyi belirli bir sınır içinde kontrol edin.
  • Lazerı ateşleyen silah ve vurma pozisyonu arasında raycast yaparak merminin olup olmadığından emin olunur ve hiç duvar geçmez.

Müşteri

Müşteri, uzaktaki bir parçayı ışınlayarak vuran konumu sunmak zorunda, böylece uzaktaki mesafeyi gerçekçi olarak kontrol edebilir.

  1. In ToolController , DamageCharacter uzaktaki etkinliğinin fireWeapon işlevinde başladığı satıra gidin.

  2. Bir hitPosition ile argüman olarak eklenir.


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

Sunucu

ServerLaserManager artı bir parametre gönderiyor, bu yüzden DamageCharacter uzaktaki etkinliği kabul etmek için ServerLaserManager ayarlandı.

  1. In the ServerLaserManager script, add a hitPosition parameter to the damageCharacter function.


    function damageCharacter(playerFired, characterToDamage, hitPosition)
    local humanoid = characterToDamage:FindFirstChildWhichIsA("Humanoid")
    if humanoid then
    -- Karakterden sağlığı kaldır
    humanoid.Health -= LASER_DAMAGE
    end
    end
  2. getPlayerToolHandle işlevinin altında, üç parametre ile isHitValid adında bir işlev oluşturun: playerFired, 1>characterToDamage1> ve 4>hitPosition4> .


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

İlk kontrol, vuruş pozisyonundan karaktere vurulma mesafesi olacaktır.

  1. Kaynağın üst kısmında MAX_HIT_PROXIMITY adında bir değişken ilan edin ve ona bir değer 10 atayın. Bu, etkileşim ve karakter arasındaki maksimum mesafeyi temsil edecektir. Bir tolerans gereklidir, çünkü karakter, etkinliği başlatan müşteriden kaynaklanan biraz yer hareketi olabilir.


    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local eventsFolder = ReplicatedStorage.Events
    local LASER_DAMAGE = 10
    local MAX_HIT_PROXIMITY = 10
  2. In the isHitValid function, hesap etme mesajının karakter ile hit pozisyonu arasındaki mesafeyi hesaplayın. Eğer mesafe MAX_HIT_PROXIMITY ile daha büyükse, false ı döndürün.


    local function isHitValid(playerFired, characterToDamage, hitPosition)
    -- Karakterin vurulduğu ve vurulma pozisyonu arasındaki mesafeyi doğrula
    local characterHitProximity = (characterToDamage.HumanoidRootPart.Position - hitPosition).Magnitude
    if characterHitProximity > MAX_HIT_PROXIMITY then
    return false
    end
    end

İkinci kontrol, silahı ateşleyen ve vurma pozisyonu arasında bir raycast gerektirecektir. Eğer raycast, karakter olmayan bir nesneyi iade ederse, vurma geçersiz olduğundan şüphelenebilirsiniz, çünkü şüpheli bir şey vurma işlemini engelliyordu.

  1. Bu kontrol etyerine getirmek için aşağıdaki kodu kopyalayın. Fonksiyonun sonunda doğru döndürün: eğer sona ulaşırsa, tüm kontroller geçerli olur.


    local function isHitValid(playerFired, characterToDamage, hitPosition)
    -- Karakterin vurulduğu ve vurulma pozisyonu arasındaki mesafeyi doğrula
    local characterHitProximity = (characterToDamage.HumanoidRootPart.Position - hitPosition).Magnitude
    if characterHitProximity > 10 then
    return false
    end
    -- Duvarlar aracılığıyla atış yapmak için kontrol edin
    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)
    -- Bir karakter değilse bir nesneye vurulursa atışı görmezden gel
    if rayResult and not rayResult.Instance:IsDescendantOf(characterToDamage) then
    return false
    end
    end
    return true
    end
  2. Değişkeni damageCharacter fonksiyonuna ilan edin, validShot . üç argümanlı isHitValid ile ilgili sonucunu atın: 2> playerFired2>, 5> characterToDamage5> ve 8> hitPosition8> .

  3. Aşağıdaki ifade içinde, ve operatörlerini ekleyin ki validShotdoğru olup olmadığını kontrol edebilsiniz.


    function damageCharacter(playerFired, characterToDamage, hitPosition)
    local humanoid = characterToDamage:FindFirstChildWhichIsA("Humanoid")
    local validShot = isHitValid(playerFired, characterToDamage, hitPosition)
    if humanoid and validShot then
    -- Karakterden sağlığı kaldır
    humanoid.Health -= LASER_DAMAGE
    end
    end

Şimdi hasar karakteri uzaktaki etkinlik daha güvenli ve çoğu oyuncunun bunu kötüye kullanmasını önleyecek. Not olası bazı kötü niyetli oyuncuların etkinliği etrafında yollar bulması çok yaygındır; uzaktaki etkinlikleri güvenli tutmak sürekli bir çaba.

Lazer kılıcınız şimdi tamamlandı, raycasting kullanan temel bir çarpışma algılama sistemiyle. Kullanıcı Etkileşimi öğretimini deneyin, nasıl lazer kılıcınıza bir yeniden yükleme eylemi ekleyebileceğinizi veya eğlenceli bir oyun haritası oluşturabileceğinizi öğrenin!

Nihai Kod

AraçKontrolörü


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
-- Önceki atıştan sonra yeterli süre geçmiş olup olmadığını kontrol edin
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 fare konumundan bir ışın oluştur
local screenToWorldRay = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
-- Işının maksimum mesafeyle çarpan birimi direktörü
local directionVector = screenToWorldRay.Direction * MAX_MOUSE_DISTANCE
-- Roy'un yönüne doğru uzay ışını
local raycastResult = workspace:Raycast(screenToWorldRay.Origin, directionVector)
if raycastResult then
-- 3D kesişim noktasını iade edin
return raycastResult.Position
else
-- Hiçbir nesneye vurulmadığı için, ışının sonundaki pozisyonu hesaplayın
return screenToWorldRay.Origin + directionVector
end
end
local function fireWeapon()
local mouseLocation = getWorldMousePosition()
-- Normal bir yön vektörü hesaplayın ve lazer mesafesi ile çarpan
local targetDirection = (mouseLocation - tool.Handle.Position).Unit
-- Silahı ateş etmenin yönü, maksimum mesafe ile çarpan
local directionVector = targetDirection * MAX_LASER_DISTANCE
-- oyuncukarakterini görmezden gelin, onların kendilerine zarar vermesini önleyin
local weaponRaycastParams = RaycastParams.new()
weaponRaycastParams.FilterDescendantsInstances = {Players.LocalPlayer.Character}
local weaponRaycastResult = workspace:Raycast(tool.Handle.Position, directionVector, weaponRaycastParams)
-- Başlangıç ve son pozisyonları arasında herhangi bir nesneye vurulup vurulmadığını kontrol edin
local hitPosition
if weaponRaycastResult then
hitPosition = weaponRaycastResult.Position
-- İstek edilen instans bir karakter modelinin bir çocuğu olacaktır
-- Bir humanoid modelinde bulunursa, muhtemelen bir oyuncu karakteridir
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
-- Maksimum lazer mesafasına dayanarak son pozisyonu hesap et
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)

LazerRender


local LaserRenderer = {}
local Debris = game:GetService("Debris")
local SHOT_DURATION = 0.15 -- Lazerin görünür olması için
-- Bir lazer kaynağından bir başlangıç ​​pozisyonuna kadar bir son pozisyon oluştur
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
-- Kayıp parçalar hizmetine lazer gecesi ekleyin ve temizle
Debris:AddItem(laserPart, SHOT_DURATION)
-- Silahın atış sesini oynat
local shootingSound = toolHandle:FindFirstChild("Activate")
if shootingSound then
shootingSound:Play()
end
end
return LaserRenderer

Sunucu Laser Yöneticisi


local ReplicatedStorage = game:GetService("ReplicatedStorage")
local eventsFolder = ReplicatedStorage.Events
local LASER_DAMAGE = 10
local MAX_HIT_PROXIMITY = 10
-- Oyuncunun tutduğu aracın etiketini bulun
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)
-- Karakterin vurulduğu ve vurulma pozisyonu arasındaki mesafeyi doğrula
local characterHitProximity = (characterToDamage.HumanoidRootPart.Position - hitPosition).Magnitude
if characterHitProximity > MAX_HIT_PROXIMITY then
return false
end
-- Duvarlar aracılığıyla atış yapmak için kontrol edin
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)
-- Bir karakter değilse bir nesneye vurulursa atışı görmezden gel
if rayResult and not rayResult.Instance:IsDescendantOf(characterToDamage) then
return false
end
end
return true
end
-- Lazerın ateşlendiğini tüm müşterilerin görebilmesi için bildir
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
-- Karakterden sağlığı kaldır
humanoid.Health -= LASER_DAMAGE
end
end
-- Olayları uygun işlevlere bağlayın
eventsFolder.DamageCharacter.OnServerEvent:Connect(damageCharacter)
eventsFolder.LaserFired.OnServerEvent:Connect(playerFiredLaser)

Müşteri Laser Yöneticisi


local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LaserRenderer = require(Players.LocalPlayer.PlayerScripts:WaitForChild("LaserRenderer"))
local eventsFolder = ReplicatedStorage.Events
-- Başka bir oyuncunun lazerini göster
local function createPlayerLaser(playerWhoShot, toolHandle, endPosition)
if playerWhoShot ~= Players.LocalPlayer then
LaserRenderer.createLaser(toolHandle, endPosition)
end
end
eventsFolder.LaserFired.OnClientEvent:Connect(createPlayerLaser)