Ç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:
- Bir merminin hedefe vurduğunu fizyiksel olarak test eden bir kontrol.
- 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ırtable.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 lazerSpreadDegreeslocal leftAngleBound = laserSpreadDegrees / 2local rightAngleBound = -leftAngleBoundlocal degreeInterval = laserSpreadDegrees / (numLasers - 1)for angle = rightAngleBound, leftAngleBound, degreeInterval dolocal direction = (originCFrame * CFrame.Angles(0, math.rad(angle), 0)).LookVectortable.insert(directions, direction)endend
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 thentable.insert(directions, originCFrame.LookVector)elseif numLasers > 1 thenlocal leftAngleBound = laserSpreadDegrees / 2local rightAngleBound = -leftAngleBoundlocal degreeInterval = laserSpreadDegrees / (numLasers - 1)for angle = rightAngleBound, leftAngleBound, degreeInterval dolocal directionif spreadDirection == "vertical" thendirection = (originCFrame * CFrame.Angles(math.rad(angle), 0, 0)).LookVectorelsedirection = (originCFrame * CFrame.Angles(0, math.rad(angle), 0)).LookVectorendtable.insert(directions, direction)endendreturn 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ırprint(direction) -- yeni satırend -- yeni satırlocal 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
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>
- Distance – mesafe, ışın kaynağı ve kesişim noktası arasındaki mesafe.
- Material – Kesişim noktasındaki Enum.Material ile.
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_DISTANCEdestination = CFrame.lookAt(distantPosition, distantPosition - rayDirection)taggedPlayer = nilend
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
Ö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).
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çerlilocal claimedDirection = (rayResult.destination.Position - originCFrame.Position).Unitlocal directionErrorDegrees = getAngleBetweenDirections(claimedDirection, expectedDirection)return directionErrorDegrees <= ToleranceValues.BLAST_ANGLE_SANITY_CHECK_TOLERANCE_DEGREESRoblox, 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:
getAngleBetweenDirectionslocal 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)endBir 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
isPlayerNearPositionlocal distanceFromCharacterToPosition = position - character:GetPivot().Positionif distanceFromCharacterToPosition.Magnitude > ToleranceValues.DISTANCE_SANITY_CHECK_TOLERANCE_STUDS thenreturn falseendSon 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
isRayPathObstructedlocal 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.