Blaster davranışını uygulama, birinci şahıs nişancı oyunlarında bir patlama mekanizmasını programlama sürecidir. Oyuncular bir tıklama veya bir düğmeye basarak patlayabilirken, tatmin edici ve doğru bir patlama davranışı oluşturmak önemlidir çünkü bu, oyuncuların genel oyun deneyimlerini artırır.
örnek lazer tag oyunu referans alarak, bu öğretici bölümünde iki farklı blaster türü için blaster davranışını uygulamanın arkasındaki scriptler hakkında bilgi edineceksiniz. Bu bölümde aşağıdaki konulara rehberlik edilecektir:
- Oyuncuların patlama düğmesine bastıklarında bunu tespit etme.
- Oyuncunun patlama düğmesine yakın zamanda basıp basmadığını kontrol etme.
- Sunucuya patlamayı başlatan kişinin kim olduğunu, nereden geldiğini ve her lazer ışınının son varış noktasını bildiren patlama verilerini oluşturma.
- Patlama verilerini sunucuya bildirerek, patlamanın başka bir oyuncuyla çarpışması durumunda uygun eylemleri gerçekleştirmesini sağlama.
- Her patlama arasında blaster'ı sıfırlayarak, blaster'ın tekrar patlayabilmesi için yeterli soğuma süresi tanıma.
Bu bölümü tamamladıktan sonra, blaster'ın patlamalarının diğer oyuncularla çarpıştığını tespit etmesini sağlayan scriptler hakkında bilgi edinecek ve ardından her blaster türüne göre ilgili sağlık miktarını düşüreceksiniz.
Oyuncu girişini kontrol etme
Blaster davranışını uygulamanın ilk adımı, bir oyuncunun patlama düğmesine bastığında dinlemektir. Oyuncuların patlama düğmesine basmak için kullandıkları giriş türü, oyuna erişmek için kullandıkları cihaza bağlıdır. Örneğin, örnek lazer tag oyunu fare ve klavye kontrollerini, oyun kumandalarını ve dokunmatik kontrolleri destekler. Bu giriş türlerinin her birini ReplicatedStorage ⟩ UserInputHandler içinde görebilirsiniz.
Bu istemci scripti, ContextActionService kullanarak MouseButton1 ve ButtonR2'yi patlama eylemine bağlar. Bu, bir oyuncu sol fare düğmesine veya bir oyun kumandasının R2 düğmesine her bastığında, blaster'dan bir lazer ışınının patlamasını tetikler. HUDGui'nin mobil cihazlarda patlama için bir düğme içerdiğini ve scriptin ilerleyen kısımlarında buna bağlandığını unutmayın.
ContextActionService:BindAction("_", onBlasterActivated, false,
Enum.UserInputType.MouseButton1,
Enum.KeyCode.ButtonR2
)onBlasterActivated() tanımında Enum.UserInputState.Begin kullanımına dikkat etmek önemlidir. Bir blaster seçmek gibi birçok kullanıcı arayüzü etkileşimi, fare düğmesi yukarı kalktıktan sonra (Enum.UserInputState.End) gerçekleşmez, bu da kullanıcılara etkileşimden kaçınmak için son bir şans tanır. Ancak, bir patlama mekanizması, düğmeye basıldığı anda gerçekleşmediği sürece duyarlı hissettirmiyor.
Bunu göstermek için, Enum.UserInputState.Begin'i Enum.UserInputState.End olarak değiştirebilir ve ardından oyun testini yaparak patlamanın duyarlılığının oyunun oynanışını nasıl etkilediğini görebilirsiniz. Örneğin, oyuncular düğmeyi basılı tutabiliyorsa ve patlama tetiklenmiyorsa, bu diğer oyuncuları etiketlerken deneyimlerini nasıl değiştirebilir?
local function onBlasterActivated(_actionName: string,
inputState: Enum.UserInputState, _inputObject: InputObject)
if inputState == Enum.UserInputState.End then -- güncellenmiş satır, lütfen geri değiştirin
attemptBlastClient()
end
endOyuncunun patlayıp patlayamayacağını kontrol etme
UserInputHandler bir düğme basışını veya ekran dokunuşunu tespit ettikten sonra, ReplicatedStorage ⟩ Blaster ⟩ attemptBlastClient'i çağırarak oyuncunun patlayıp patlayamayacağını kontrol eder. Örnek lazer tag oyunundaki çoğu kontrol gibi, bu işlem iki kez gerçekleşir: önce istemcide, sonra sunucuda. attemptBlastClient, ardından ReplicatedStorage ⟩ Blaster ⟩ canLocalPlayerBlast'i çağırarak blasterStateClient oyuncu niteliğinin basit bir kontrolünü gerçekleştirir:
local function canLocalPlayerBlast(): boolean
return localPlayer:GetAttribute(PlayerAttribute.blasterStateClient) == BlasterState.Ready
endReplicatedStorage ⟩ Blaster ⟩ BlasterState'i incelediğinizde, oyunun üç blaster durumu olduğunu görebilirsiniz: Ready, Blasting ve Disabled. Bu durumların her birinin etkisini görmek için oyunu test edebilir, Players hizmeti altında oyuncunuzu seçebilir ve ardından Properties penceresinde blasterStateClient niteliğini gözlemleyebilirsiniz. Blaster'ınızı seçerken Disabled, çoğu zaman Ready ve düğmeye bastıktan sonra bir saniyeden daha kısa bir süre için Blasting olarak görüntülendiğini fark edin.
Bu küçük gecikme, tıkladığınız kadar hızlı patlayamamanızı sağlar. Örneğin, fonksiyonu her zaman true dönecek şekilde değiştirirseniz, herhangi bir gecikme olmadan blaster'ınızı hızlı bir şekilde patlatabilirsiniz ki bu lazer tag oyun deneyimi için gerçekçi değildir.
local function canLocalPlayerBlast(): boolean
return true -- güncellenmiş satır, lütfen geri değiştirin
endPatlama verilerini oluşturma
Oyuncunun blaster'ının Ready durumunda olduğunu doğruladıktan sonra, attemptBlastClient ReplicatedStorage ⟩ attemptBlastClient ⟩ blastClient'i çağırır. blastClient'in attığı ilk adım, blasterStateClient oyuncu niteliğini Blasting olarak ayarlamaktır; bu, daha önceki hızlı ateş durumunu önler.
Sonraki adım, patlama verilerini oluşturmaktır. ReplicatedStorage ⟩ Blaster ⟩ BlastData'yı gözden geçirirseniz, her patlamanın üç bilgi parçasından oluştuğunu görebilirsiniz:
- Patlamayı başlatan oyuncu.
- Patlamanın başlangıç noktasını temsil eden bir DataType.CFrame.
- Eğer başka bir oyuncuya çarparsa, her lazer ışınının son varış noktasını ve çarpılan oyuncuyu içeren bir RayResult tablosu.
Bu verileri oluşturmak için, blastClient ReplicatedStorage ⟩ attemptBlastClient ⟩ blastClient ⟩ generateBlastData'yi çağırır; aşağıda gözden geçirebilirsiniz.
local function generateBlastData(): BlastData.Type
local blasterConfig = getBlasterConfig()
local rayDirections = getDirectionsForBlast(
currentCamera.CFrame, blasterConfig)
local rayResults = castLaserRay(
localPlayer, currentCamera.CFrame.Position, rayDirections)
local blastData: BlastData.Type = {
player = localPlayer,
originCFrame = currentCamera.CFrame,
rayResults = rayResults,
}
return blastData
endBu fonksiyon, oyuncunun blaster türünü almak için getBlasterConfig kullanarak başlar. Örnek, geniş, yatay bir yayılma ile birkaç ışın üreten bir blaster ve tek bir ışın üreten başka bir blaster türü sağlar. Bu yapılandırmaları ReplicatedStorage ⟩ Instances ⟩ LaserBlastersFolder içinde bulabilirsiniz.
Fonksiyon, patlama için başlangıç noktası olarak currentCamera.CFrame'i kullanır ve bunu getDirectionsForBlast'a geçirir. Bu noktada, kod artık blaster ile ilgili değil, lazer ışını ile ilgilidir; lazer ışını hakkında daha fazla bilgi edineceğiniz çarpışmaları tespit etme bölümüne geçeceksiniz. Son olarak, rayResults tablosunu oluşturduktan sonra, generateBlastData patlama verilerini blastClient'e döndürmek için ihtiyaç duyduğu tüm bilgilere sahiptir.
Sunucuya bildirme
blastClient patlama için tam verilere sahip olduğunda, iki olayı tetikler:
local laserBlastedBindableEvent = ReplicatedStorage.Instances.LaserBlastedBindableEvent
local laserBlastedEvent = ReplicatedStorage.Instances.LaserBlastedEvent
laserBlastedBindableEvent:Fire(blastData)
laserBlastedEvent:FireServer(blastData)BindableEvent, patlamayı diğer istemci scriptlerine bildirir. Örneğin, ReplicatedStorage ⟩ FirstPersonBlasterVisuals bu olayı, patlama animasyonu ve soğuma çubuğu gibi görsel efektleri ne zaman göstereceğini bilmek için kullanır. Benzer şekilde, RemoteEvent, sunucu scriptlerine patlamayı bildirir ve bu, ServerScriptService ⟩ LaserBlastHandler içinde patlamayı işlemeye başlar.
local function onLaserBlastedEvent(playerBlasted: Player, blastData: BlastData.Type)
local validatedBlastData = getValidatedBlastData(playerBlasted, blastData)
if not validatedBlastData then
return
end
if not canPlayerBlast(playerBlasted) then
return
end
blastServer(playerBlasted)
processTaggedPlayers(playerBlasted, blastData)
for _, replicateToPlayer in Players:GetPlayers() do
if playerBlasted == replicateToPlayer then
continue
end
replicateBlastEvent:FireClient(replicateToPlayer, playerBlasted, blastData)
end
endHile yapmayı önlemek için, sunucu her istemcinin gönderdiği verileri doğrulamak zorundadır. Bu kontroller şunları içerir:
- BlastData bir tablo mu? Bir Class.CFrame ve başka bir rayResults tablosu içeriyor mu?
- Oyuncunun bir blaster'ı var mı?
- Oyuncunun bir karakteri ve dünyada bir konumu var mı?
- Patlama verilerini gönderdikten sonra, oyuncu lazer ışınını patlattığı yerden aşırı bir mesafeye mi hareket etti?
Bu son kontrol bir yargı çağrısı içerir ve sunucu gecikmesi ile oyuncu hareket hızı göz önüne alındığında, kendi oyununuz için aşırı değerlerin ne olacağına karar verebilirsiniz. Bu yargı çağrısını nasıl yapacağınızı göstermek için, getValidatedBlastData içinde bir print ifadesi ekleyebilir ve oyunu test edebilirsiniz.
local distanceFromCharacterToOrigin = blastData.originCFrame.Position - rootPartCFrame.Position
print(distanceFromCharacterToOrigin.Magnitude) -- güncellenmiş satır, lütfen kaldırın
if distanceFromCharacterToOrigin.Magnitude > ToleranceValues.DISTANCE_SANITY_CHECK_TOLERANCE_STUDS then
warn(`Player {player.Name} failed an origin sanity check while blasting`)
return
endHareket ederken ve patlarken, çıktıyı not edin. Şöyle bir şey görünebilir:
1.9019629955291748
3.1549558639526367
2.5742883682250977
4.8044586181640625
2.6434271335601807ReplicatedStorage ⟩ PlayerStateHandler ⟩ togglePlayerMovement içinde oyuncuların hareket hızını artırırsanız, tekrar test ettiğinizde, patlamalar arasında aşırı hareket nedeniyle birçok başarısız kontrol ile karşılaşabilirsiniz.
local ENABLED_WALK_SPEED = 60 -- güncellenmiş satır, lütfen geri değiştirinSunucu daha sonra şunları yapar:
- rayResults'ı doğrular.
- Oyuncunun patlayıp patlayamayacağını kontrol eder.
- Blaster durumunu sıfırlar.
- Etiketlenmiş oyuncuların sağlıklarını azaltır.
- Diğer tüm oyunculara patlamayı çoğaltarak, üçüncü şahıs görsellerini görmelerini sağlar.
Bu sunucu işlemleri hakkında daha fazla bilgi için, öğreticinin çarpışmaları tespit etme bölümüne bakın.
Blaster'ı sıfırlama
Örnek lazer tag oyununda, blaster'lar bir ısı mekanizması kullanır. Belirli bir patlama sayısından sonra yeniden yüklemek yerine, her patlama arasında "soğuma" süresine ihtiyaç duyarlar. Bu aynı soğuma gecikmesi, istemci (blastClient) ve sunucu (blastServer) üzerinde gerçekleşir; sunucu gerçek bilgi kaynağı olarak hareket eder.
local blasterConfig = getBlasterConfig(player)
local secondsBetweenBlasts = blasterConfig:GetAttribute("secondsBetweenBlasts")
task.delay(secondsBetweenBlasts, function()
local currentState = player:GetAttribute(PlayerAttribute.blasterStateServer)
if currentState == BlasterState.Blasting then
player:SetAttribute(PlayerAttribute.blasterStateServer, BlasterState.Ready)
end
end)secondsBetweenBlasts niteliği, ReplicatedStorage ⟩ Instances ⟩ LaserBlastersFolder içindeki blaster yapılandırmasının bir parçasıdır. secondsBetweenBlasts gecikmesi geçtikten sonra, oyuncu tekrar patlayabilir ve tüm süreç tekrar başlar. Oyuncunun tekrar ne zaman patlayabileceğini anlamasına yardımcı olmak için, oyun bir soğuma çubuğu içerir.
Bu noktada, oyuncular doğabilir ve yeniden doğabilir, nişan alabilir ve patlayabilir, ancak oyun hala her patlamanın sonuçlarını belirlemelidir. Öğreticinin bir sonraki bölümünde, blaster'ın patlamanın başka bir oyuncuya çarptığını tespit etme yeteneğini programlamayı ve ardından blaster ayarlarına göre uygun miktarda oyuncu sağlığını azaltmayı öğreneceksiniz.