Vuruları Tespit Etme

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

Çarpışanları algılamak işlemi, patlamaların oyuncularla çarpıştığında tespit etme sürecidir. Bunun yüksek seviyede bir iş olarak düşünülmesi gerekir:

  1. Bir merminin hedefe vurduğunu fizyiksel olarak test eden bir kontrol.
  2. Blaster'ın hedefe yönlendirildiğine dair anında bir kontrol.

Kullandığınız çarpışma algılama türü deneyiminizin fiziksel oyun gereksinimlerine bağlı olarak değişir. Örneğin, topların belli bir hızda elden bırakması gereken bir dodgeball deneyiminde, topların hareketi hızını değiştirmez veya hava ile etkileşime girmez veya gü

Bu nedenle, bu öğreticiyi kullanarak referans olarak kullanılan örnek lazer etiketi deneyimi size 3D alanındaki şut algılanmasının arkasındaki kodları gösterir, bunların yönlendirme dahil:

  • Mevcut kameradan patlama yönü alınıyor ve oyuncunun blaster yaz.
  • Çıkartma silahlarını patladığında düz bir yoldan atar.
  • Blaster'ın verilerinin kötüye kullanılmasını önlemek için patlamayı doğruluyor.
  • Oyuncunun her tip blaster'ın patlama hasarına göre sağlığını azaltır ve kaç tane ışın oyuncuya vurur.

Bu bölümü tamamladıktan sonra, oynanışgeliştirmek için ek geliştirme konularını keşfedeceksiniz, such as ses, lighting, ve özel efektler.

Patlama Yönünü Al

Bir oyuncunun blaster'ını patladıktan sonra, ReplicatedStorage > Blaster > attemptBlastClient > 1> blastClient1> > 4> generateBlastData4> çağrılar iki işlevi başlatmak için şu iki işlevi çağırır: 7> ray

爆発 verileri oluştur

local rayDirections = getDirectionsForBlast(currentCamera.CFrame, blasterConfig)
local rayResults = castLaserRay(localPlayer, currentCamera.CFrame.Position, rayDirections)

rayDirections için girişler basittir: mevcut kameraposition ve dönme değerleri, ve oyuncunun blaster yaz. Eğer örnek lazer etiketi deneyim sadece tek bir lazer ışını üreten blasterlar veriyorsa, ReplicatedStorage Ancak, örnek, geniş, yatay yayılımı olan birkaç lazer ışını üreten ekstra bir blaster tipi sağlar, getDirectionsForBlast ile her laser ışınının yönünü yayının açısına göre hesaplamak zorundadır:

getDirectionsForBlast alın

if numLasers == 1 then
-- Tek lazerler için, doğrudan nişan alır
table.insert(directions, originCFrame.LookVector)
elseif numLasers > 1 then
-- Birkaç lazer için, onları eşit olarak yatay olarak yayıl
-- merkez etrafında bir aralık lazerSpreadDegrees
local leftAngleBound = laserSpreadDegrees / 2
local rightAngleBound = -leftAngleBound
local degreeInterval = laserSpreadDegrees / (numLasers - 1)
for angle = rightAngleBound, leftAngleBound, degreeInterval do
local direction = (originCFrame * CFrame.Angles(0, math.rad(angle), 0)).LookVector
table.insert(directions, direction)
end
end

Bu konsepti daha da göstermek için, geniş, 垂直 yayılımlı bir üçüncü blaster yazeklediyseniz, yeni bir blaster özelliği oluşturabilirsiniz, örneğin spreadDirection , ardından CFrame hesab


if numLasers == 1 then
table.insert(directions, originCFrame.LookVector)
elseif numLasers > 1 then
local leftAngleBound = laserSpreadDegrees / 2
local rightAngleBound = -leftAngleBound
local degreeInterval = laserSpreadDegrees / (numLasers - 1)
for angle = rightAngleBound, leftAngleBound, degreeInterval do
local direction
if spreadDirection == "vertical" then
direction = (originCFrame * CFrame.Angles(math.rad(angle), 0, 0)).LookVector
else
direction = (originCFrame * CFrame.Angles(0, math.rad(angle), 0)).LookVector
end
table.insert(directions, direction)
end
end
return directions

Sonuçta, rayDirections() işlevi, her lazer ışınının yönünü temsil eden bir tablo Vectors ile döndürür. Eğer yararlıysa, bu verinin göründüğünü bir algı olarak almak için biraz günlük ekleyebilirsiniz.

爆発 verileri oluştur

local rayDirections = getDirectionsForBlast(currentCamera.CFrame, blasterConfig)
for _, direction in rayDirections do -- yeni satır
print(direction) -- yeni satır
end -- yeni satır
local rayResults = castLaserRay(localPlayer, currentCamera.CFrame.Position, rayDirections)

Işınları Yönlendirme

castLaserRay() , ReplicatedStorage > Blaster > 0> attemptBlastClient0> >

Bu bilgi, özellikle ilk kişi nişancı deneyimleri için kullanışlıdır, çünkü oyuncular veya çevreyle çarpışan patlamaları görebilmenizi sağlar. Örneğin, aşağıdaki görüntü, paralel olarak yayılan iki ışını gösterir. Onların nokta değişt

A diagram where Ray A continues through the wall, and Ray B collides with the wall.

The castLaserRay() parameters specify that Raycast() çağrılarının her bir bölümünü Raycast() iletişimine dahil etmesi gerekir. Skript sonra her bir yön için bir ray oluşturur: If a ray hits something, it spawns a ray for each direction in the 1>

Değer, Instance olarak adlandırılır, çünkü bu özelliklerin örnek laser etiketi deneyiminin oyun oynayışı için en krit

castLaserRay() then uses Position and Normal to create a new 0> Datatype.CFrame

castLaserRay

if result then
-- Patlama bir şeye vurdu, oyuncu olup olmadığını kontrol edin.
destination = CFrame.lookAt(result.Position, result.Position + result.Normal)
taggedPlayer = getPlayerFromDescendant(result.Instance)
else
-- Patlama hiçbir şeye vmadı, bu yüzden onun hedefi
-- maksimum mesafesindeki noktayı işaret eder.
local distantPosition = origin + rayDirection * MAX_DISTANCE
destination = CFrame.lookAt(distantPosition, distantPosition - rayDirection)
taggedPlayer = nil
end

Patlamayı Geçerli Kıl

Cheating'i önlemek için, önceki bölüm Blaster'ın İzinsiz Kullanımını Engellemeyi Etkinleştirmeyi açıklar

  1. Önce, getValidatedRayResults çağrıları validateRayResult ile her girişi rayResults tablosundaki müşterinin her girişini kontrol etmek için bir 1> Datatype.CFrame1> ve bir 4> Player4> (veya hiçbiri) olarak (veya hiçbiri) olarak (veya hiçbiri).

  2. Ayrıca, isRayAngleFromOriginValid çağrılarını kullanarak lazer yayınının beklendiği açılara kıyasla kullanıcı tarafından beklendiği açıları karşılaştırır. Bu kod özellikle, ReplicatedStorage kullanımının sunucunun

    Önceki bölümlerdeki blaster doğrulaması gibi, isRayAngleFromOriginValid tolerans değerine bağlı kalarak açılar arasındaki bir "aşırı" farkın ne olduğunu belirlemektedir:

    isRayAngleFromOriginGeçerli

    local claimedDirection = (rayResult.destination.Position - originCFrame.Position).Unit
    local directionErrorDegrees = getAngleBetweenDirections(claimedDirection, expectedDirection)
    return directionErrorDegrees <= ToleranceValues.BLAST_ANGLE_SANITY_CHECK_TOLERANCE_DEGREES

    Roblox, matematikteki en çok katılan bitleri özelleştirmez, bu yüzden sonuç kapsayıcı bir yardımcı işlevi oluşturur, bir dizi deneyimde uygulanabilir:

    getAngleBetweenDirections

    local function getAngleBetweenDirections(directionA: Vector3, directionB: Vector3)
    local dotProduct = directionA:Dot(directionB)
    local cosAngle = math.clamp(dotProduct, -1, 1)
    local angle = math.acos(cosAngle)
    return math.deg(angle)
    end
  3. Bir sonraki kontrol en iyi. getValidatedBlastData , ızınlanmış olan oyuncunun bağlantının kök noktasını doğrulamak için DISTANCE_SANITY_CHECK_TOLERANCE_STUDS kullanırken, isPlayerNearPosition , etiketli oyuncunun

    isPlayerNearPosition

    local distanceFromCharacterToPosition = position - character:GetPivot().Position
    if distanceFromCharacterToPosition.Magnitude > ToleranceValues.DISTANCE_SANITY_CHECK_TOLERANCE_STUDS then
    return false
    end
  4. Son kontrol isRayPathObstructed kullanır bir ray cast operasyonunun çeşitlendirilmiş bir versiyonunu kullanarak ray'in hedefinin bir duvar veya diğer engellemeden arkasında olup olmadığını kontrol etmek için. Örneğin, kötü niyetli bir oyuncu tüm duvarları çevreetiketlemek i

    isRayPathObstructed

    local scaledDirection = (rayResult.destination.Position - blastData.originCFrame.Position)
    scaledDirection *= (scaledDirection.Magnitude - 1) / scaledDirection.Magnitude

Hiçbir anti-exploit stratejisi kapsayıcı değildir, ancak kötü niyetli oyuncuların deneyiminize nasıl yaklaşabileceğini dikkate almak önemlidir, böylece sunucunun şüpheli davranışlarıyla ilgili olarak etkili çekler oluşturabilirsiniz.

Oyuncu Sağlığını Azalt

Bir oyuncunun başka bir oyuncuya etiketlediğini doğruladıktan sonra, özelleştirilmiş laser etiketi deneyiminin ana oyun akışını tamamlamak için son adımlar, etiketlenmiş oyuncunun sağlığını azaltmak, liderlik tablosuartırmak ve oyuncuyu tur içine yeniden oluşturmaktır.

Etiketli oyuncunun sağlığını azaltmaya başlayarak, Spawning and Respawning , özellikle bir karakterin bir

Deneyim, her blaster'ın damagePerHit özelliğindeki hasar değerlerini saklar. Ör

Health , olumsuz değerleri kabul etmez, bu yüzden onPlayerTagged 'in biraz mantığı vardır, ki oyuncu sağlığını yüzde sıfır veya daha üstünde tutmak için. Sağl

Bu sorunla ilgili yaklaşım biraz karışık görünebilir. Örneğin, neden olmasın ki oyuncunun sağlığını sıfıra sadece ifade edeyim ki negatif olsaydı? Sebebi, sağlık değerlerini çevirmez olarak kullanmak zorunda kalmak. Class.Humanoid:TakeDamage() metodunu kullanarak oyuncuların zorluk alanlar

onPlayerTagged

local function onPlayerTagged(playerBlasted: Player, playerTagged: Player, damageAmount: number)
local character = playerTagged.Character
local isFriendly = playerBlasted.Team == playerTagged.Team
-- Müttefik ateşi yasakla
if isFriendly then
return
end
local humanoid = character and character:FindFirstChild("Humanoid")
if humanoid and humanoid.Health > 0 then
-- Negatif sağlıktan kaçın
local damage = math.min(damageAmount, humanoid.Health)
-- TakeDamage, ForceField'ın aktif olduğundan kaynaklanan sağlığın düşürülmesini önler
humanoid:TakeDamage(damage)
if humanoid.Health <= 0 then
-- Oyuncuya etiket için bir puan verildi
Scoring.incrementScore(playerBlasted, 1)
end
end
end

Sıradaki adım liderlik tablosuartırmaktır. Bu, patlama verilerinin yanında patlayan oyuncuyu içermek için gerekli görülmeyebilir gibi görünebilir, ancak bu bilgi olmadan, deneyim oyuncuyu etiketlemek kredi edemez. Son olarak, etiketlenmiş oyuncu, LaserBlastHandler

Bu eğitimin beş bölümü deneyimin çekirdek oyun akışını kapsar, ancak hala keşfetmenin çok sayıda alanı vardır, örneğin:

  • Blaster görüntüleri : See ReplicatedStorage > FirstPersonBlasterVisuals ve 0> ServerScriptService0> > 3> ThirdPersonBlasterVisuals 3> .
  • Ses : See ReplicatedStorage > SoundHandler .
  • Özel Modlar : Bu deneyimi nasıl modifiye edebilirsiniz, böylece zamanın bitmesine izin vermeden en çok puanı alma gibi yeni türdeki hedefleri giriştirmeyi nasıl sağlayabilirsiniz?

Lazer etiketi deneyiminin genişletilmiş oyun mantığı için, ayrıca tekrar kullanılabilir, yüksek kaliteli çevresel kaynaklar için Laser Etiketi şablonunu gözden geçirin.