Maçlar, zamanlayıcıların tükenmesi veya tek bir oyuncunun kalması gibi birkaç koşulda sona erebilir.
Yenilmiş oyuncuları yönet
Şu anda, mağlup edilen oyuncular arenada yeniden doğuyor. Bunun yerine, bir sonraki eşleşmebeklemek için lobiye geri gönderin.
- PlayerManager'da, respawnPlayerInLobby() adlı yerel bir işlev oluşturun. Bu işlevde takip edilenyapın:
- oyuncuyeniden doğma konumunu lobiSpawn'a ayarlayın.
- Karakteri Player:LoadCharacter() ile yeniden yükle. Unutma, LoadCharacter() oyuncuyu doğdukları yerde yeniden yaratır ve sahip oldukları herhangi bir aleti kaldırır.
Anonim işlevleri kullan
Anonim işlevler, belirli durumlar altında gelişmiş senaryolarda yaygın olarak kullanılır.Onları tanımlamadan önce, senaryonuzun karşılaşabileceği bir durumu anlamak önemlidir.
Bunu düşünün: Mağlup oyuncuları lobiye ışıtmak için, yeniden doğma işlevinin oyuncunun Öldü etkinliğine bağlanması gerekecektir.Ancak bir sorun var.Etkinliği geçmişte olduğu gibi bağlarsanız, oyuncunun adını Died etkinliğinden almanın bir yolu yoktur.Senaryo, mağlup bir oyuncuyu aktif oyunları izleyen tablodan kaldırmak için bu isme ihtiyaç duyar.
Öldürme olayını tetikleyen oyuncunun adını almak için anonim bir işlev kullanın. Anonim işlevler adına sahip değildir ve ayrı olarak yerine doğrudan Connect() içinde oluşturulabilir.
Örnek anonim işlev, sözdizimini gösteren aşağıdadır.
myPlayer.Died:Connect(function()
print(player)
end)
Ölen olayı kodlayın
Bu işlev için, bir oyuncunun karakteri öldüğünde, onları yeniden doğuran işlevi tetikleyeceklerdir.
Oyuncunun Öldü etkinliğine erişmek için, PlayerManager > preparePlayer() , oyuncunun insansız için bir değişken ekleyin.
local function preparePlayer(player, whichSpawn)player.RespawnLocation = whichSpawnplayer:LoadCharacter()local character = player.Character or player.CharacterAdded:Wait()local sword = playerWeapon:Clone()sword.Parent = characterlocal humanoid = character:WaitForChild("Humanoid")endDied etkinliğine bağlanan anonim bir işlev oluşturun.humanoid.Died:Connect() yazarak başlayın.Sonra, içinde , yaz, otomatik tamamlanması için bas ve fazladan parantezleri sil.
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()end)Anonim işlevde, respawnPlayerInLobby() 'yi arayın. player , oyuncunun bir eşleşmegirmek üzere hazırlandığı depolayan bir değişken geçirin.
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()respawnPlayerInLobby(player)end)Bir sunucu başlat ve bir eşleşmeoyna.Bir oyuncu öldüğünde, lobide yeniden doğduklarını test edin.Oyuncuları yenmek için, onlara doğru yürüyün ve lobide yeniden doğduklarını onaylayana kadar silahınızı kullanın.
Oyuncu2'ye Saldırma Oyuncu2, yeniden doğduktan sonra lobide
Not, istenirse test etmenin de farklı yolları vardır.
- Bir oyuncuyu öldürmek için, Sunucu > Çıktı penceresi > Komut çubuğunda kopyala ve yapıştır: workspace.Player1.Humanoid.Health = 0 .Komutu çalıştırmak için Enter basın.Diğer oyuncuları kaldırmak için Player2, Player3 vb. kullanın
- OyunSettings > matchDuration daha uzun bir süre ayarlamak, tüm oyuncuları bulmak ve çıkarmak için daha fazla zaman verebilir.
- Daha hızlı testler yapmak için, GameSettings > minimumPlayers 'yi 2 gibi daha küçük bir sayıya değiştirin.
Oyunu oyun
Şimdi yenilmiş oyuncular yeniden doğdu, oyunu bitirmek için çalışmaya başla.MaçSonu etkinliğini oluşturmayı hatırlıyor musunuz? Zamanlayıcı tükendiğinde veya bir kazanan bulunduğunda ateşlenecek.
Diğer senaryolara hangi koşulun oyunu bitirdiğini söylemek için, TimerUp ve FoundWinner için değişkenlerle bir tablo oluşturun.Maç bitim etkinliği ateşlendiğinde, diğer kodların yanıt verebilmesi için bir değişken olarak geçecektir.
GameSettings'te, boş bir modül tablosu olan endStates adlı boş bir tablo oluşturun.
local GameSettings = {}-- Oyun DeğişkenleriGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- Oyunun bitirolası yolları.GameSettings.endStates = {}return GameSettingsTimerUp ve FoundWinner adlı iki değişken oluşturun. Her birini adlarına uyan bir dizeye ayarlayın. Bu dizeler kodu test etmek için kullanılacaktır.
GameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}
Bir zamanlayıcı ile bitir
Zamanlayıcı sona erdiğinde, Maç Sonu etkinliğini ateşleyin ve eşleşen son durum değişkenini gönderin.Bu şekilde, bu olayı dinleyen diğer kodlar da buna göre yanıt verebilir.Etkinliklerin sinyalleri ateşlerken, dinleme kriptleri tarafından alınan verileri de gönderebileceğini unutmayın, örneğin TimerUp veya FoundWinner.
In GameManager , while true do döngüsünde, çizgi matchEnd.Event:Wait() bulun. Çizginin başında, local endState = ekleyin.
while true dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.updateStatus("Get ready!")task.wait(gameSettings.transitionTime)matchManager.prepareGame()local endState = matchEnd.Event:Wait()endDoğru durumun alındığını onaylamak için, endState içeren bir yazıcı ifadesi ekleyin.
while true dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.updateStatus("Get ready!")task.wait(gameSettings.transitionTime)matchManager.prepareGame()local endState = matchEnd.Event:Wait()print("Game ended with: " .. endState)endMatchManager'da, bulun ve baskı ifadesini kaldır.Sonra, maç bitim etkinliğini ateşlemek için matchEnd:Fire() yazın ve gameSettings.endStates.TimerUp geçirin.
-- Değerlerlocal displayValues = ReplicatedStorage:WaitForChild("DisplayValues")local timeLeft = displayValues:WaitForChild("TimeLeft")-- Maç süresini izlemek için kullanılacak yeni bir zamanlayıcı nesnesi oluşturur.local myTimer = timer.new()-- Yerel Fonksiyonlarlocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endBir eşleşmeyi test edin. Zamanlayıcı tükendikten sonra, yazıcı ifadesinin TimerUp değişkenine depolanan dizeyi içerdiğinden emin olun.
Sorun giderme ipuçları
Bu noktada, mesaj görüntülenmedi, aşağıdan birini deneyin.
- Son durum değişkenlerinin her yerde çağrıldığından emin olun, burada olduğu gibi kesinlikle yazıldılar: gameSettings.endStates.TimerUp .
- Nokta operatörünün yerine nokta operatörünü kullanmak suretiyle :( virgül operatörü) ile çalıştığınızdan emin olun, örneğin .
Kazanan bir eşleşmekodla
Sonra, senaryonun kazanan oyuncuları tanımlaması, kaybeden oyuncuları kaldırması ve zamanlayıcıyı durdurma gibi temizlik yapması gerekir.Maçlar ayrıca bir oyuncu kaldığında da sona erecek.FoundWinner koşulunun yerine getirildiğini görmek için, bir eşleşmeoyuncuları izleyen tabloda kalan sayıyı kontrol eden bir işleve ihtiyacınız olacak.
Oyuncu sayısını kontrol et
Maçlar, sadece bir oyuncu kaldığında sona erecek.Bunu kontrol etmek için, senaryo bir turda oyuncuları izlemelidir.Bir oyuncu kaldığında, bir kazanan atanabilir.
Oyun Yöneticisinde, aşağıdaki değişkenleri tanımlayın:
- ModülScripts klasörü
- OyunAyarları modülü - Son durum değişkenlerine erişmek için kullanılır
- Etkinlik klasörü ve MaçSonu etkinliği - Ateş etkinliği
local PlayerManager = {}-- Hizmetlerlocal Players = game:GetService("Players")local ServerStorage = game:GetService("ServerStorage")local ReplicatedStorage = game:GetService("ReplicatedStorage")-- Modüllerlocal moduleScripts = ServerStorage:WaitForChild("ModuleScripts")local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))-- Etkinliklerlocal events = ServerStorage:WaitForChild("Events")local matchEnd = events:WaitForChild("MatchEnd")Üstünde respawnPlayerInLobby() , yeni bir yerel işlev adında checkPlayerCount() ekleyin.
-- Oyuncu Değişkenlerilocal activePlayers = {}local playerWeapon = ServerStorage.Weaponlocal function checkPlayerCount()endlocal function respawnPlayerInLobby(player)Bu işlev içinde, bir kazanan kontrol etmek için bir if then ifadesi kullanın. Bu ifade içinde:
- activePlayers tablosunun boyutunun 1 olup olmadığını kontrol edin.
- Eğer öyleyse, ateş et matchEnd ve geç gameSettings.endStates.FoundWinner .
local function checkPlayerCount()if #activePlayers == 1 thenmatchEnd:Fire(gameSettings.endStates.FoundWinner)endend
Bir oyuncuyu kaldır
Oyuncular kaldırılana kadar doğru bir sayı tutulamaz.Bir oyuncu yenildiğinde, oyuncuları oyuncu tablosundan kaldırarak doğru bir oyuncu sayısı tutun.Sonra, aktif oyuncu tablosunun boyutunu kontrol ederek bir kazanan olup olmadığını görün.
altında, adlı yeni yerel bir işlev oluşturun ve bir parametre ile adlandırılmış .
local function checkPlayerCount()if #activePlayers == 1 thenmatchEnd:Fire(gameSettings.endStates.FoundWinner)endendlocal function removeActivePlayer(player)endOyuncuyu activePlayers tablosunda bulmak için, bir for döngüsü kullanarak onun üzerinden dolaşın.Sonra, isimle eşleşen bir oyuncu fonksiyona geçtiğinde çalışan bir if ifadesi ekleyin.
local function removeActivePlayer(player)for playerKey, whichPlayer in activePlayers doif whichPlayer == player thenendendendoyuncukaldırmak için, if ifadesinde:
- Ara table.remove() . Eşzamanlama içinde, activePlayers , bakmak için tabloyu geç ve playerKey - tableden kaldırmak için oyuncu.
- playersLeft nesnesinin değerini #activePlayers olarak ayarlayın.
- checkPlayerCount() koşarak kazanan bir oyuncu kontrol edin.
local function removeActivePlayer(player)for playerKey, whichPlayer in activePlayers doif whichPlayer == player thentable.remove(activePlayers, playerKey)playersLeft.Value = #activePlayerscheckPlayerCount()endendend
Etkinlikleri ve testi bağla
Az önce oluşturulan işlevi kullanmak için, oyuncunun Died etkinliğine bağlı olan anonim işlevden çağırın.
Bul preparePlayer() . Died etkinliği bağlantısıyla anonim işlevde, çağır removeActivePlayer() . Sonra, oyuncuyu parametre olarak geçir.
humanoid.Died:Connect(function()respawnPlayerInLobby(player)removeActivePlayer(player)end)Kazanan bir oyuncu bulunup bulunmadığını görmek için, bir test sunucusu başlatın.Sadece bir oyuncu kaldığında Çıktı penceresinde FoundWinner'ı görmelisiniz.
Testi sürdür ve maçın bitirizin ver. Yeni bir maç başladığında Çıktı penceresinde bir hata görünür:
Bu hata, zamanlayıcının durdurulmadığı için, bunun bir sonraki bölümde düzeltileceği.
Saati durdur
Bir maç kazanan bir oyuncu ile sona erdiğinde, zamanlayıcı da durmalıdır.Süre dolmadan önce zamanlayıcıyı durdurmak için, maç bitiş etkinliği herhangi bir zamanda durdurulduğunda zamanlayıcı durdurun.Bu, etkinlikler oluşturmanın avantajlarından biridir.Senaryo nedeni ve etkisi ilişkilerini yazmak için çok sayıda durumda yeniden kullanılabilirler.
Maç Yöneticisinde, yeni bir yerel işlev oluştur stopTimer() . İçeri, zamanlayıcıyı durdurmak için myTimer:stop() yaz.
-- Maç süresini izlemek için kullanılacak yeni bir zamanlayıcı nesnesi oluşturur.local myTimer = timer.new()-- Yerel Fonksiyonlarlocal function stopTimer()myTimer:stop()endlocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endMaç bitince zamanlayıcıyı durdurmak için, maç biti etkinliğini stopTimer() 'ye bağlayın.
-- Modül İşlevlerifunction MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerTest önceki hata artık bir sunucu başlatarak görünmediğini kontrol et.Tek oyuncu hariç hepsini ortadan kaldır ve ardından maç bitince birkaç saniye bekleyin.
Sonraki adımlar
İki kazanma koşulu bitmiş olsa da, oyun döngüsünü bitirmek için hala bazı görevler kaldı.durum, kazanan oyuncu asla lobiye ışınlanmaz.Bir sonraki ders, maçın oyunculara nasıl son verdiğini gösterip oyunu sıfırlayacak ve sonunda tüm döngüyü bitireceksiniz.
Tamamlanmış senaryolar
Aşağıda, çalışmanızı kontrol etmek için bitmiş senaryolar bulunmaktadır.
Oyuncu Yöneticisi senaryosu
local PlayerManager = {}
-- Hizmetler
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Modüller
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- Etkinlikler
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
-- Harita Değişkenleri
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- Değerler
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
-- Oyuncu Değişkenleri
local activePlayers = {}
local playerWeapon = ServerStorage.Weapon
-- Yerel Fonksiyonlar
local function checkPlayerCount()
if #activePlayers == 1 then
matchEnd:Fire(gameSettings.endStates.FoundWinner)
end
end
local function removeActivePlayer(player)
for playerKey, whichPlayer in activePlayers do
if whichPlayer == player then
table.remove(activePlayers, playerKey)
playersLeft.Value = #activePlayers
checkPlayerCount()
end
end
end
local function respawnPlayerInLobby(player)
player.RespawnLocation = lobbySpawn
player:LoadCharacter()
end
local function onPlayerJoin(player)
player.RespawnLocation = lobbySpawn
end
local function preparePlayer(player, whichSpawn)
player.RespawnLocation = whichSpawn
player:LoadCharacter()
local character = player.Character or player.CharacterAdded:Wait()
local sword = playerWeapon:Clone()
sword.Parent = character
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
respawnPlayerInLobby(player)
removeActivePlayer(player)
end)
end
-- Modül İşlevleri
function PlayerManager.sendPlayersToMatch()
local arenaSpawns = spawnLocations:GetChildren()
for playerKey, whichPlayer in Players:GetPlayers() do
table.insert(activePlayers, whichPlayer)
local spawnLocation = table.remove(arenaSpawns, 1)
preparePlayer(whichPlayer, spawnLocation)
end
playersLeft.Value = #activePlayers
end
-- Etkinlikler
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager
OyunAyarları scripti
local GameSettings = {}-- Oyun DeğişkenleriGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- Oyunun bitirolası yolları.GameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}return GameSettings
GameManager senaryosu
-- Hizmetlerlocal ServerStorage = game:GetService("ServerStorage")local Players = game:GetService("Players")-- Modül Kodlarılocal moduleScripts = ServerStorage:WaitForChild("ModuleScripts")local matchManager = require(moduleScripts:WaitForChild("MatchManager"))local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))-- Etkinliklerlocal events = ServerStorage:WaitForChild("Events")local matchEnd = events:WaitForChild("MatchEnd")while true dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.updateStatus("Get ready!")task.wait(gameSettings.transitionTime)matchManager.prepareGame()local endState = matchEnd.Event:Wait()print("Game ended with: " .. endState)end
MaçYöneticisi skripti
local MatchManager = {}
-- Hizmetler
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Modül Kodları
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local timer = require(moduleScripts:WaitForChild("Timer"))
-- Etkinlikler
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
-- Değerler
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local timeLeft = displayValues:WaitForChild("TimeLeft")
-- Maç süresini izlemek için kullanılacak yeni bir zamanlayıcı nesnesi oluşturur.
local myTimer = timer.new()
-- Yerel Fonksiyonlar
local function stopTimer()
myTimer:stop()
end
local function timeUp()
matchEnd:Fire(gameSettings.endStates.TimerUp)
end
local function startTimer()
print("Timer started")
myTimer:start(gameSettings.matchDuration)
myTimer.finished:Connect(timeUp)
while myTimer:isRunning() do
-- +1 eklemek, zamanlayıcının 0 yerine 1'de sona ermesini sağlar.
timeLeft.Value = (myTimer:getTimeLeft() + 1) // 1
-- Bekleme süresini ayarlamayarak, daha doğru döngüleme sağlar
task.wait()
end
end
-- Modül İşlevleri
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager