Oyun döngüsü; girdiye (genellikle oyun kumandası veya fare ile etkileşime giren oyuncu) yanıt vermek, oyun durumunu güncellemek ve bir butona basıldığında ışığın açılması gibi durumlarda oyuncuya oyun durumunu etkilediğini gösteren çıktılar sağlamak amacıyla yinelenerek (döngü halinde) çalışan bir koddur. Genellikle oyuncunun bir hedefe ulaşması ya da hedefe ulaşılamadan sürenin dolmasına benzer bir hata durumu gibi hallerde oyun bir tamamlanma durumuna ulaştığında döngü sona erer.
Time Trial: Pizza Pursuit eğitimindeki bu adımı tamamlayarak oyun döngüsünü nasıl oluşturacağını ve oyunun tamamlama ve hata durumlarını nasıl tanımlayacağını öğreneceksin.
Aşağıda, Time Trial: Pizza Pursuit’in oyun döngüsü için sözde kod yer almaktadır:
loop:
race:
loop:
SelectNextPickupZone
WaitForPlayerToCompletePickupZone
block:
WaitForFirstPickup
SelectNextDeliveryZone
WaitForPlayerToCompleteDeliveryZone
Bu döngü, geri sayım bittiğinde veya oyunda beklenmeyen bir hata varsa sona erer.
Temel Oyun Döngüsü Oluşturma
game_coordinator_device.verse dosyasını güncellemek için aşağıdaki adımları izle:
private
vesuspends
belirleyicilerine sahipPickupDeliveryLoop() adlı yeni bir metot oluştur. Daha önce
OnBegin()` içinde oluşturulan döngüyü bu yeni metoda taşı.OnBegin<override>()<suspends> : void = SetupZones() PickupDeliveryLoop() PickupDeliveryLoop<private>()<suspends> : void = var PickupLevel : int = 0 loop: if (PickupZone : base_zone = PickupZoneSelectors[PickupLevel].SelectNext[]): PickupZone.ActivateZone() PickupZone.ZoneCompletedEvent.Await() PickupZone.DeactivateZone() else: Print("Can't find next PickupZone to select") return if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() DeliveryZone.ZoneCompletedEvent.Await() DeliveryZone.DeactivateZone() else: Print("Can't find next DeliveryZone to select") return
- Etiket dizisinin uzunluğundan alma seviyelerinin maksimum sayısını belirle ve alma seviyesi maksimum alma seviyesi sayısından büyük olmadığı sürece oyuncu bir alma bölgesini her tamamladığında
PickupLevel
değerini artır.OnBegin<override>()<suspends> : void = SetupZones() PickupDeliveryLoop() PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 var PickupLevel : int = 0 loop: if (PickupZone : base_zone = PickupZoneSelectors[PickupLevel].SelectNext[]): PickupZone.ActivateZone() PickupZone.ZoneCompletedEvent.Await() PickupZone.DeactivateZone() # Alma seviyesini güncelle if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 else: Print("Can't find next PickupZone to select") return
- Teslim bölgesi, oyuncu ilk alımını tamamladıktan sonra etkileşir ancak oyuncu teslim bölgesine gitmeden önce isterse yine eşya alabilecektir. Bunu yapmak için alma bölgesi kodunun ve teslim bölgesi kodunun aynı zamanda gerçekleşmesi gerekir. Bu örnekte
race
eşzamanlılık ifadesi kullanılıyor çünkü:- Oyuncu bir teslimatı tamamladığında teslim bloku, alma bölgesi döngüsünü iptal eder.
- Alma döngüsüyle ilgili bir sorun varsa alma bölgesi döngüsü, teslim blokunu iptal eder.
Ayrıca bölgeyi devre dışı bırakma işleminde ufak bir değişiklik yapman gerekir. Döngünün veya teslim blokunun iptal edilmesi durumunda kod bölgenin tamamlanmasını bekliyorsa
DeactivateZone()
çağrılmamalıdır.Bölge devre dışı bırakma satırı hiçbir zaman yürütülmeyeceği için bölge etkin kalarak bir hata oluşturur.
-
Bunu düzeltmek için
defer
ifadesini kullanabilirsin.defer
,defer
ifadesinin göründüğü kapsam sona erene kadar kendi içerdiği ifadelerin yürütülmesini erteler.defer
; bir kapsamdan normal şekilde ayrılma (fonksiyonun sonu), erken çıkma (dönüş veya kesinti gibi) veya iptal edilen herhangi bir eşzamanlı görev/asenkron ifade (örneğinrace
) gibi nedenlerle program denetimi kapsam dışına aktarıldıktan sonra çalışır. Bu durum, ne olursa olsun en sonda yürütülecek işlemleri kuyruğa almaya benzer. Her birDeactivateZone
çağrısını birdefer
ifadesinde topla ve ilgiliZoneCompletedEvent.Await()
gerçekleşmeden önce taşı.PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 var PickupLevel : int = 0 race: loop: if (PickupZone : base_zone = PickupZoneSelectors[PickupLevel].SelectNext[]): PickupZone.ActivateZone() defer: PickupZone.DeactivateZone() PickupZone.ZoneCompletedEvent.Await() # Alma seviyesini güncelle if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 else: Print("Can't find next PickupZone to select") return block: if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() # PickupDeliveryLoop döngüsünün iptal edildiğinde tüm etkin teslim bölgelerini de devre dışı bırakarak sonlanması için bölge devre dışı bırakmayı geciktiriyoruz. defer: Logger.Print("Deactivating delivery zone.", ?Level:=log_level.Normal) DeliveryZone.DeactivateZone() DeliveryZone.ZoneCompletedEvent.Await() Logger.Print("Delivered", ?Level:=log_level.Normal) else: Logger.Print("Seçilecek bir sonraki DeliveryZone bulunamıyor.", ?Level:=log_level.Error) return # PickupDeliveryLoop döngüsünden doğan hata
- Önceki örnek, teslim bölgesini alma bölgesiyle aynı zamanda etkinleştirir ancak teslim bölgesinin etkinleşmesi ilk alım tamamlanana kadar beklemelidir. Bunu yapmak için bir olay ekle ve teslim bölgesini etkinleşmeden önce olay için beklet.
OnBegin<override>()<suspends> : void = SetupZones() PickupDeliveryLoop() PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 FirstPickupZoneCompletedEvent := event(){} var PickupLevel : int = 0 var IsFirstPickup : logic = true race: loop: if (PickupZone : base_zone = PickupZoneSelectors[PickupLevel].SelectNext[]): PickupZone.ActivateZone() defer: PickupZone.DeactivateZone() PickupZone.ZoneCompletedEvent.Await() # İlk alımdan sonra teslim bölgesini etkinleştirebiliriz. if (IsFirstPickup?): set IsFirstPickup = false FirstPickupZoneCompletedEvent.Signal() # Alma seviyesini güncelle if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 else: Print("Can't find next PickupZone to select") return block: FirstPickupZoneCompletedEvent.Await() if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() # PickupDeliveryLoop döngüsünün iptal edildiğinde tüm etkin teslim bölgelerini de devre dışı bırakarak sonlanması için bölge devre dışı bırakmayı geciktiriyoruz. defer: Logger.Print("Deactivating delivery zone.", ?Level:=log_level.Normal) DeliveryZone.DeactivateZone() DeliveryZone.ZoneCompletedEvent.Await() Logger.Print("Delivered", ?Level:=log_level.Normal) else: Logger.Print("Seçilecek bir sonraki DeliveryZone bulunamıyor.", ?Level := log_level.Error) return # PickupDeliveryLoop döngüsünden doğan hata
- Oyuncunun sürekli olarak eşya alabilmesi ve teslim edebilmesi için oyun bitene kadar bu alma bölgesi/teslim bölgesi yarış ifadesini döngüye al.
OnBegin<override>()<suspends> : void = SetupZones() PickupDeliveryLoop() PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 FirstPickupZoneCompletedEvent := event(){} loop: var PickupLevel : int = 0 var IsFirstPickup : logic = true race: loop: if (PickupZone : base_zone = PickupZones[PickupLevel].SelectNext[]): PickupZone.ActivateZone() defer: PickupZone.DeactivateZone() PickupZone.ZoneCompletedEvent.Await() # Alma seviyesini güncelle if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 else: Print("Can't find next PickupZone to select") return block: FirstPickupZoneCompletedEvent.Await() if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() # PickupDeliveryLoop döngüsünün iptal edildiğinde tüm etkin teslim bölgelerini de devre dışı bırakarak sonlanması için bölge devre dışı bırakmayı geciktiriyoruz. defer: Logger.Print("Deactivating delivery zone.", ?Level:=log_level.Normal) DeliveryZone.DeactivateZone() DeliveryZone.ZoneCompletedEvent.Await() Logger.Print("Delivered", ?Level:=log_level.Normal) else: Logger.Print("Seçilecek bir sonraki DeliveryZone bulunamıyor.", ?Level:=log_level.Error) return # PickupDeliveryLoop döngüsünden doğan hata
-
game_coordinator_device.verse dosyan şu anda böyle görünmelidir:
using { /Verse.org/Simulation } using { /Fortnite.com/Devices } using { /Fortnite.com/Vehicles } using { /Fortnite.com/Characters } using { /Fortnite.com/Playspaces } using { /Verse.org/Random } using { /UnrealEngine.com/Temporary/Diagnostics } using { /UnrealEngine.com/Temporary/SpatialMath } using { /UnrealEngine.com/Temporary/Curves } using { /Verse.org/Simulation/Tags } # Oyun bölgeleri etiketleri pickup_zone_tag<public> := class(tag): pickup_zone_level_1_tag<public> := class(pickup_zone_tag): pickup_zone_level_2_tag<public> := class(pickup_zone_tag): pickup_zone_level_3_tag<public> := class(pickup_zone_tag): delivery_zone_tag<public> := class(tag): log_pizza_pursuit<internal> := class(log_channel){} game_coordinator_device<public> := class(creative_device): DeliveryZoneSelector<private> : tagged_zone_selector = tagged_zone_selector{} var PickupZoneSelectors<private> : []tagged_zone_selector = array{} OnBegin<override>()<suspends> : void = SetupZones() PickupDeliveryLoop() SetupZones<private>() : void = DeliveryZoneSelector.InitZones(delivery_zone_tag{}) PickupZoneLevelTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} set PickupZoneSelectors = for(PickupZoneTag : PickupZoneLevelTags): PickupZone := tagged_zone_selector{} PickupZone.InitZones(PickupZoneTag) PickupZone PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 FirstPickupZoneCompletedEvent := event(){} loop: var PickupLevel : int = 0 var IsFirstPickup : logic = true race: loop: if (PickupZone : base_zone = PickupZones[PickupLevel].SelectNext[]): PickupZone.ActivateZone() defer: PickupZone.DeactivateZone() PickupZone.ZoneCompletedEvent.Await() # Alma seviyesini güncelle if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 else: Print("Can't find next PickupZone to select") return block: FirstPickupZoneCompletedEvent.Await() if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() # PickupDeliveryLoop döngüsünün iptal edildiğinde tüm etkin teslim bölgelerini de devre dışı bırakarak sonlanması için bölge devre dışı bırakmayı geciktiriyoruz. defer: Logger.Print("Deactivating delivery zone.", ?Level:=log_level.Normal) DeliveryZone.DeactivateZone() DeliveryZone.ZoneCompletedEvent.Await() Logger.Print("Delivered", ?Level:=log_level.Normal) else: Logger.Print("Seçilecek bir sonraki DeliveryZone bulunamıyor.", ?Level:=log_level.Error) return # PickupDeliveryLoop döngüsünden doğan hata
Verse dosyalarını kaydet, kodunu derle ve bölümüne oynanış testi uygula.
Bölümüne oynanış testi uyguladığında oyunun başlangıcında ve oyuncu bir eşya aldıktan sonra Eşya Oluşturma Yeri cihazlarından biri etkinleşir. Oyuncu ilk eşyasını aldıktan sonra bu Eşya Oluşturma Yeri cihazı devre dışı kalır ve sonra bir Ele Geçirme Alanı cihazı etkinleşir. Bu döngü sen oyunu manuel olarak sonlandırana kadar devam eder.
Oyun Döngüsü İçin Tamamlama ve Hata Durumları Tanımlama
Temel oyun döngüsünü oluşturduktan sonra oyun döngüsünün tamamlama ve hata durumunu tanımlamalısın. Bu oyunun aşağıdaki koşullarda sona ermesi gerekir:
- Bir geri sayım bittiğinde veya
- Oyun döngüsüyle ilgili bir sorun olduğunda.
Oyunun tamamlama ve hata durumlarını ayarlamak için şu adımları izle:
game_coordinator_device
içindeprivate
belirleyicisine sahip bircountdown_timer
sınıfı örneği oluştur.game_coordinator_device<public> := class(creative_device): @editable EndGame<public> : end_game_device = end_game_device{} var CountdownTimer<private> : countdown_timer = countdown_timer{}
countdown_timer
oluşturucusu için bir oyuncu referansı gerektiğinden bu tek oyunculu oyunda bir oyuncu referansı kaydetmek için isteğe bağlı bir oyuncu değişkeni ekle ve oyuncu referansını almak içinFindPlayer() adlı bir fonksiyon oluştur. Bölgeleri ayarlamadan önce
OnBegin()içinde
FindPlayer()` çağrısı yap.game_coordinator_device<public> := class(creative_device): @editable EndGame<public> : end_game_device = end_game_device{} var CountdownTimer<private> : countdown_timer = countdown_timer{} var MaybePlayer<private> : ?player = false OnBegin<override>()<suspends> : void = FindPlayer() SetupZones() FindPlayer<private>() : void = # Bu bir tek oyunculu deneyim olduğundan ilk oyuncu (dizin 0’daki) # tek kullanılabilir oyuncu olmalıdır. if (FirstPlayer := GetPlayspace().GetPlayers()[0]): set MaybePlayer = option{FirstPlayer} Logger.Print("Player found") else: # Bir oyuncu bulamazsak günlüğe bir hata kaydet. # Her zaman en az bir oyuncu mevcut olduğundan böyle bir durum yaşanmamalıdır. Logger.Print("Geçerli oyuncu bulunamıyor", ?Level := log_level.Error)
- Geri sayım süreölçerinin bitmesini bekleyen ve oyunu sonlandırma cihazını etkinleştiren
HandleCountdownEnd()
adlı bir cihaz oluştur.HandleCountdownEnd<private>(InPlayer : agent)<suspends> : void = CountdownTimer.CountdownEndedEvent.Await() EndGame.Activate(InPlayer)
StartGame()
adlı bir fonksiyon oluştur ve bu fonksiyonuOnBegin()
içindeSetupZones()
fonksiyonundan sonra çağır. Bu fonksiyon şunları yapmalıdır:- Geri Sayım süreölçerini başlatma.
game_coordinator_device<public> := class(creative_device): # Geri sayım süreölçerinin ne kadar süre geri saymaya başlayacağı. @editable InitialCountdownTime<public> : float = 30.0 @editable EndGame<public> : end_game_device = end_game_device{} OnBegin<override>()<suspends> : void = FindPlayer() SetupZones() StartGame() StartGame<private>()<suspends> : void = Logger.Print("Trying to start the game...") <# Başlatıldığında InitialCountdownTime değerinden geri sayacak yeni bir countdown_timer oluşturuyoruz. Countdown_timer arayüzün gösterileceği bir oyuncu bulunmasını gerektirir. Şimdiye kadar geçerli bir oyuncu elde etmiş olmalıyız. #> if (ValidPlayer := MaybePlayer?): Logger.Print("Valid player, starting game...") set CountdownTimer = MakeCountdownTimer(InitialCountdownTime, ValidPlayer) CountdownTimer.StartCountdown() else: Logger.Print("Can't find valid player. Aborting game start", ?Level := log_level.Error)
race
ifadesini kullanarak hem `HandleCountdownEnd(ValidPlayer)Böylece:- Geri sayım sona erdiğinde oyun döngüsü durur veya
- Oyun döngüsü durursa geri sayım iptal edilir.
StartGame<private>()<suspends> : void = Logger.Print("Trying to start the game...") <# Başlatıldığında InitialCountdownTime değerinden geri sayacak yeni bir countdown_timer oluşturuyoruz. Countdown_timer arayüzün gösterileceği bir oyuncu bulunmasını gerektirir. Şimdiye kadar geçerli bir oyuncu elde etmiş olmalıyız. #> if (ValidPlayer := MaybePlayer?): Logger.Print("Valid player, starting game...") set CountdownTimer = MakeCountdownTimer(InitialCountdownTime, ValidPlayer) CountdownTimer.StartCountdown() # Geri sayımın sona ermesini bekleriz. # Aynı zamanda, temel oynanışı oluşturan Alma ve Teslim oyun döngüsünü çalıştırırız. race: HandleCountdownEnd(ValidPlayer) PickupDeliveryLoop() else: Logger.Print("Can't find valid player. Aborting game start", ?Level := log_level.Error)
- Geri Sayım süreölçerini başlatma.
- game_coordinate_device.verse dosyan şu anda böyle görünmelidir:
using { /Verse.org/Simulation } using { /Fortnite.com/Devices } using { /Fortnite.com/Vehicles } using { /Fortnite.com/Characters } using { /Fortnite.com/Playspaces } using { /Verse.org/Random } using { /UnrealEngine.com/Temporary/Diagnostics } using { /UnrealEngine.com/Temporary/SpatialMath } using { /UnrealEngine.com/Temporary/Curves } using { /Verse.org/Simulation/Tags } # Oyun bölgeleri etiketleri pickup_zone_tag<public> := class(tag): pickup_zone_level_1_tag<public> := class(pickup_zone_tag): pickup_zone_level_2_tag<public> := class(pickup_zone_tag): pickup_zone_level_3_tag<public> := class(pickup_zone_tag): delivery_zone_tag<public> := class(tag): log_pizza_pursuit<internal> := class(log_channel){} game_coordinator_device<public> := class(creative_device): # Geri sayım süreölçerinin ne kadar süre geri saymaya başlayacağı. @editable InitialCountdownTime<public> : float = 30.0 @editable EndGame<public> : end_game_device = end_game_device{} DeliveryZoneSelector<private> : tagged_zone_selector = tagged_zone_selector{} var PickupZoneSelectors<private> : []tagged_zone_selector = array{} OnBegin<override>()<suspends> : void = FindPlayer() SetupZones() StartGame() FindPlayer<private>() : void = # Bu bir tek oyunculu deneyim olduğundan ilk oyuncu (dizin 0’daki) # tek kullanılabilir oyuncu olmalıdır. if (FirstPlayer := GetPlayspace().GetPlayers()[0]): set MaybePlayer = option{FirstPlayer} Logger.Print("Player found") else: # Bir oyuncu bulamazsak günlüğe bir hata kaydet. # Her zaman en az bir oyuncu mevcut olduğundan böyle bir durum yaşanmamalıdır. Logger.Print("Geçerli oyuncu bulunamıyor", ?Level := log_level.Error) SetupZones<private>() : void = DeliveryZoneSelector.InitZones(delivery_zone_tag{}) PickupZoneLevelTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} set PickupZoneSelectors = for(PickupZoneTag : PickupZoneLevelTags): PickupZone := tagged_zone_selector{} PickupZone.InitZones(PickupZoneTag) PickupZone StartGame<private>()<suspends> : void = Logger.Print("Trying to start the game...") <# Başlatıldığında InitialCountdownTime değerinden geri sayacak yeni bir countdown_timer oluşturuyoruz. Countdown_timer arayüzün gösterileceği bir oyuncu bulunmasını gerektirir. Şimdiye kadar geçerli bir oyuncu elde etmiş olmalıyız. #> if (ValidPlayer := MaybePlayer?): Logger.Print("Valid player, starting game...") set CountdownTimer = MakeCountdownTimer(InitialCountdownTime, ValidPlayer) CountdownTimer.StartCountdown() # Geri sayımın sona ermesini bekleriz. # Aynı zamanda, temel oynanışı oluşturan Alma ve Teslim oyun döngüsünü çalıştırırız. race: HandleCountdownEnd(ValidPlayer) PickupDeliveryLoop() else: Logger.Print("Can't find valid player. Aborting game start", ?Level := log_level.Error) HandleCountdownEnd<private>(InPlayer : agent)<suspends> : void = CountdownTimer.CountdownEndedEvent.Await() EndGame.Activate(InPlayer) PickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 FirstPickupZoneCompletedEvent := event(){} loop: var PickupLevel : int = 0 var IsFirstPickup : logic = true race: loop: if (PickupZone : base_zone = PickupZoneSelectors[PickupLevel].SelectNext[]): PickupZone.ActivateZone() <# Etkinleştirdiğimiz PickupZone için gereken tek geciktirme (defer) budur. Her dış döngünün sonunda ilk PickupZone bölgesini devre dışı bırakacak veya sonraki herhangi bir PickupZone’u devre dışı bırakacaktır. Bunun nedeni, ifadenin en sonda PickupZone değişkeni daha yeni bir bölgeye bağlandığında değerlendirilmesidir. #> defer: PickupZone.DeactivateZone() PickupZone.ZoneCompletedEvent.Await() Logger.Print("Picked up", ?Level := log_level.Normal) # İlk alımdan sonra teslim bölgesini etkinleştirebiliriz. if (IsFirstPickup?): set IsFirstPickup = false FirstPickupZoneCompletedEvent.Signal() # Alma seviyesini güncelle if (PickupLevel < MaxPickupLevel): set PickupLevel += 1 # Logger.Print("PickupLevel increased to {PickupLevel}", ?Level := log_level.Normal) else: Logger.Print("Seçilecek bir sonraki PickupZone bulunamıyor.", ?Level := log_level.Error) return # PickupDeliveryLoop döngüsünden doğan hata block: FirstPickupZoneCompletedEvent.Await() if (DeliveryZone := DeliveryZoneSelector.SelectNext[]): DeliveryZone.ActivateZone() # PickupDeliveryLoop döngüsünün iptal edildiğinde tüm etkin teslim bölgelerini de devre dışı bırakarak sonlanması için bölge devre dışı bırakmayı geciktiriyoruz. defer: Logger.Print("Deactivating delivery zone.", ?Level := log_level.Normal) DeliveryZone.DeactivateZone() DeliveryZone.ZoneCompletedEvent.Await() Logger.Print("Delivered", ?Level := log_level.Normal) else: Logger.Print("Seçilecek bir sonraki DeliveryZone bulunamıyor.", ?Level := log_level.Error) return # PickupDeliveryLoop döngüsünden doğan hata
- Verse dosyalarını kaydet, kodunu derle ve bölümüne oynanış testi uygula.
Bölümüne oynanış testi uyguladığında oyun önceki bölümdekiyle aynı şekilde çalışır ancak artık geri sayım sona erdiğinde veya oyun döngüsünde bir sorun olduğunda sona erecek bir süreölçer vardır.