Hedef işaretleyiciler, oyuncuyu bir sonraki hedefe veya konuma yönlendirmek için birçok oyunda kullanılır. Bu eğitimde, Harita Göstergesi cihazı ve Verse kullanarak yeniden kullanılabilir bir hedef işaretleyiciyi nasıl yapacağını öğreneceksin.
Kullanılan Verse Dili Özellikleri
-
struct
: Farklı türlerde değişkenleri bir yapı halinde gruplayabilirsin. -
Uzatma metodu: Uzatma metotları, var olan bir sınıfın veya türün üyeleri gibi hareket eden ancak yeni bir tür veya alt sınıf oluşturulmasını gerektirmeyen özel bir fonksiyon türüdür. Bu eğitimde yapı için bir uzatma metodu oluşturacaksın.
-
adlandırılmış bağımsız değişken: Bir fonksiyon çağrısına parametre adı belirtilerek gönderilen bir bağımsız değişken.
Kullanılan Verse API’leri
-
Nesne API’si: Nesne Uygulama Programı Arabirimi (Application Program Interface, API) nesne hareketleri için metotlar sağlar.
-
Düzenlenebilir Özellikler: Hızlı test için hem cihazlara referans vermek hem de değişken değerlerini güncellemek için çeşitli özellikler kullanılır.
Talimatlar
Birden fazla hedefe veya konuma hareket edebilen bir hedef işaretleyici cihazının nasıl kurulacağını öğrenmek için bu adımları takip et. Tam kodlar referans olması için bu kılavuzun sonuna eklenmiştir.
Bölümü Ayarlama
Bu örnekte aşağıdaki nesne ve cihazlar kullanılmaktadır.
-
1 adet Yapı Nesnesi: Harita Göstergesi cihazını hareket ettirmek için kullanılacak olan nesne.
-
1 adet Harita Göstergesi cihazı: Mini haritada ve genel bakış haritasında özel işaretleri görüntüleyecek cihaz.
-
1 adet Oyuncu Doğma Karesi cihazı: Oyuncunun nesnenin yakınında doğması için bu cihazı nesnenin yakınına ekle.
Nesne API’sini Kullanma
Bir cihazı Verse ile hareket ettirmenin ilk adımı, Nesne API’siyle bir nesneyi hareket ettirmektir. Bölümünde bir nesneyi hareket ettirmek için aşağıdaki adımları izle.
-
objective_coordinator_device adlı yeni bir Verse cihazı oluştur.
-
Verse dosyasının üst kısmındaki varsayılan
using
ifadelerinin altına,SpatialMath
modülü için birusing
ifadesi ekle. Bu modül, nesneleri hareket ettirmek için referans vereceğin kodu içerir.using { /UnrealEngine.com/Temporary/SpatialMath }
-
Şu iki düzenlenebilir özelliği ekle:
-
Hareketli nesneye verilen referansı depolamak için
RootProp
adlı bircreative_prop
sabiti. -
Nesnenin hareketleneceği konumu depolamak için
Destination
adlı birtransform
sabiti.
objective_coordinator_device<public> := class<concrete>(creative_device): @editable RootProp<public> : creative_prop = creative_prop{} @editable Destination<public> : transform = transform{}
-
-
Bu kodu çalıştırıp objective_coordinator_device cihazını bölümüne sürüklediğinde bu iki özelliği Ayrıntılar panelinde göreceksin.
-
Bir nesneyi hareket ettiren asıl şey,
TeleportTo[]
metodudur. Bu metodu birif
ifadesi içinde çağırmalısın veTeleportTo[]
başarısız olabilir bir ifade olduğundan parantez yerine köşeli ayraç kullanmalısın.if
ifadesi bir hata bağlamı oluşturur.if(RootProp.TeleportTo[Destination.Translation, Destination.Rotation]): Print("Nesne hareketi başarılı") else: Print("Nesne hareketi başarısız")
-
TeleportTo[]
metodunun bağımsız değişkenleri Aktarma ve Döndürme’dir. Her ikisi de Varış Noktası özelliğinden gelir. -
Editöre geri dönüp İçerik Tarayıcısı’nda Fortnite > Galeriler > Nesneler altındaki bir nesneyi editöre sürükle. Bu kılavuzda Coastal Buoy 02B adlı nesneyi kullanıyoruz ancak Nesneler klasöründeki herhangi bir şeyi kullanabilirsin.
-
Anahat Düzenleyicisi’nde hedef koordinatörü cihazını seç. Ayrıntılar panelinde RootProp bileşenini nesnene ayarla. Bu örnekte RootProp bileşeni Coastal Buoy 02B olarak ayarlanır.
-
Ayrıntılar panelinde Varış Noktası öğesini genişlet. Varış Noktası
transform
türünde olduğundan Ölçek, Döndürme ve Aktarma’dan oluşur. Nesneyi hareket ettirmek için yalnızca Aktarma ayarını değiştirmen gerekir, bu nedenle bu ayarı genişlet. X ile biten alanı 5000.0 olarak ayarla.Kodu test ederken etkisinin fark edilir olması için değerlerde büyük değişiklikler yapmak işe yarar bir yoldur. Küçük değişiklikler, kodunun istediğin gibi çalışıp çalışmadığını görmeni zorlaştırabilir.
using { /Verse.org/Simulation } using { /Fortnite.com/Devices } using { /UnrealEngine.com/Temporary/SpatialMath } objective_coordinator_device<public> := class<concrete>(creative_device): @editable RootProp<public> : creative_prop = creative_prop{} # İşaretleyicinin hareket ettirileceği yer @editable Destination<public> : transform = transform{} OnBegin<override>()<suspends> : void = if(RootProp.TeleportTo[Destination.Translation, Destination.Rotation]): Print("Nesne hareketi başarılı") else: Print("Nesne hareketi başarısız")
-
Verse ve ardından Verse Kodu Oluştur seçeneğine tıkladıktan sonra Oturumu Başlat butonuna tıkla. Son olarak, Oyunu Başlat butonuna tıkla. Şimdi nesne hareket ediyor olmalı.
Üst Öğeler ve Yapılar
Artık bölümünde hareket eden bir nesneye sahipsin ancak asıl amaç, oyuncuların bir ara nokta olarak kullanabilmesi için Harita Göstergesi cihazını hareket ettirmek. Bölümüne bir Yapı Nesnesi ve Harita Göstergesi cihazı ekleyip, Harita Göstergesi cihazını Yapı Nesnesine tutturmak için aşağıdaki adımları izle.
-
Bağlam menüsünü açmak için İçerik Tarayıcısı içinde sağ tıkla.
-
Bağlam menüsünden Blueprint Sınıfı’nı seç.
-
Üst Sınıf Seç penceresinde Yapı Nesnesi’ne tıkla.
-
İçerik Tarayıcısı’nda yeni bir Blueprint Sınıfı görünür. Bu sınıfı BuildingProp olarak yeniden adlandır.
-
Yapı Nesnesini bölümüne sürükle. Bu nesnenin örgüsü yoktur, bu nedenle yalnızca onun dönüştürme aygıtını göreceksin.
-
Anahat Düzenleyicisi’nde, Harita Göstergesi cihazını Yapı Nesnesinin üzerine sürükle. Bu, Yapı Nesnesini Harita Göstergesi cihazının üst öğesi yapar. Şimdi, Yapı Nesnesi hareket ettiğinde Harita Göstergesi cihazı da onunla birlikte hareket edecek.
Verse kullanarak cihaz oluşturmayı zaten biliyorsun ancak kendi cihazı olmayan Verse dosyaları da oluşturabilirsin.
-
Yeni bir Verse dosyası oluştur ve objective_marker olarak adlandır. Bu dosya, cihaz oluşturmayacak. Bunun yerine, daha önce oluşturduğun Verse cihazının kullanımına verilecek olan bir
struct
tanımı içerecek. -
İlk olarak objective_marker adlı bir
struct
bildirerek başla. Bu yapının iki üyesi olacak:RootProp
veMapIndicator
. Bu üyelerin ikisi de@editable
belirleyicisine sahip olmalıdır.objective_marker<public> := struct<concrete>: @editable RootProp<public> : creative_prop = creative_prop{} @editable MapIndicator<public> : map_indicator_device = map_indicator_device{}
Uzatma Metotları ve Adlandırılmış Bağımsız Değişkenler
RootProp
üyesini ve buna tutturulan Harita Göstergesi cihazını hareket ettirecek olan MoveMarker
metodunu bildir. Bu metot, uzatma metotları ve adlandırılmış bağımsız değişkenler olmak üzere iki dil özelliğini getirir.
(Marker : objective_marker).MoveMarker<public>(Transform : transform, ?OverTime : float)<suspends> : void =
-
Uzatma metotları:
MoveMarker()
metodunuobjective_marker
yapısına ekliyorsun. Bir uzatma metodu, bir parantez içinde bir tanımlayıcı ve iki noktayla ayrılan tür kullanılarak bildirilir. Örneğimizde şu şekilde bildiriliyor:(Marker : objective_marker)
. -
Adlandırılmış bağımsız değişken: İkinci bağımsız değişken
?OverTime
,MoveMarker
fonksiyon çağrısında adlandırılması gerektiğini?
karakteriyle belirtir. Bu,MoveMarker
çağrısını okuyan veya yazan herhangi bir geliştiricininfloat
bağımsız değişkeninin ne yaptığını anlamasına yardımcı olur.
MoveMarker()
, Nesne API’sinden iki metottan birini çağırır: Daha önce kullandığın TeleportTo[]
veya MoveTo()
. OverTime
parametresinin 0.0
değerinden büyük olup olmadığını anlamak için bir if..else
bloku oluştur. Büyükse MoveTo()
metodunu çağır. Bu, hedefin anında ışınlanmak yerine bir sonraki konumuna belirlediğin sürede gitmesini sağlar.
(Marker : objective_marker).MoveMarker<public>(Transform : transform, ?OverTime : float)<suspends> : void =
if (OverTime > 0.0):
Marker.RootProp.MoveTo(Transform.Translation, Transform.Rotation, OverTime)
else:
if:
Marker.RootProp.TeleportTo[Transform.Translation, Transform.Rotation]
Kodu şimdi derlersen başarılı olur ancak İçerik Tarayıcısı’ndaki CreativeDevices klasöründe yeni bir cihaz görülmez. Bunun nedeni, objective_marker cihazının creative_device
üst sınıfından devralan bir sınıf değil, bir struct
(yapı) olmasıdır.
Hedef Koordinatörü Cihazını Güncelleme
Artık referans verilecek yeni bir türe sahip olduğuna göre, ona referans vermek için objective_coordinator_device öğesini de güncellemen gerekiyor.
-
RootProp
özelliğini silip yerineobjective_marker
türündePickupMarker
adlı bir özellik getir. Bu, burada oluşturduğun türdür. -
MoveMarker()
metodufloat
türünde bir bağımsız değişken gerektirdiğinden, bu değişkeniMoveTime
adlı bir düzenlenebilir özellik olarak oluştur. -
TeleportTo[]
çağrısını sil. Bunun yerine,objective_marker
için oluşturduğunMoveMarker()
metodunu çağır. Bu metot,?OverTime
adlandırılmış bağımsız değişkenini gerektirir.
objective_coordinator_device<public> := class<concrete>(creative_device):
@editable
PickupMarker<public> : objective_marker = objective_marker{}
# İşaretleyicinin hareket ettirileceği yer
@editable
Destination<public> : transform = transform{}
# İşaretleyicinin yeni konumuna ulaşma süresi
@editable
MoveTime<public> : float = 0.0
OnBegin<override>()<suspends> : void =
PickupMarker.MoveMarker(Destination, ?OverTime := MoveTime)
Bu kodu derle ve hedef koordinatörü cihazının Ayrıntılarını kontrol et. PickupMarker ve MoveTime özellikleri bulunmalı ve PickupMarker özelliği, RootProp ve MapIndicator alanlarını içermelidir.
-
RootProp alanını BuildingProp olarak, MapIndicator alanınıysa Harita Göstergesi Cihazı (Map Indicator Device) olarak ayarla.
-
Kodunu derleyip Oturumu Başlat butonuna tıkla. Mini haritanda oyunun başladıktan kısa bir süre sonra hareket eden bir işaretleyici görmelisin. İşaretleyicinin hareketini,
MoveTime
alanını0.0
dahil farklı değerlere ayarlayarak dene. Farklı senaryolar için hangi hareket düzeyinin en iyisi olacağını anlamaya çalış.
GetPlayers() ve ActivateObjectivePulse() metotları
Oyuncularına bir sonraki hedeflerine ulaşmaları için biraz daha yardım etmenin bir yolu var. Buna hedef atımı adı verilir ve etkinleştiğinde oyuncudan Harita Göstergesi Cihazı’na doğru hareket eden noktalı bir çizgi gösterir. Hedef koordinatörü cihazına bir hedef atımı eklemek için aşağıdaki talimatları izle.

Hedef atımını etkinleştirmek için kullanacağın metot, agent
türünde bir bağımsız değişken gerektiren ActivateObjectivePulse()
adlı metottur. Oyuncu karakterini temsil eden agent
örneğini almak için metodu oluşturarak işe başla.
-
Dönüş değeri
void
olan ve<private>
olarak ayarlananFindPlayer()
adlı bir fonksiyon bildir. -
Self.GetPlayspace().GetPlayers()
ile bölümündeki tüm oyuncuları içeren bir diziyi al. DiziyiAllPlayers
adlı bir değişkende depola.FindPlayer<private>() : void = AllPlayers := Self.GetPlayspace().GetPlayers()
-
Bölümündeki tek oyuncuya referans almak için ilk dizi elemanını kendi değişkenine ata. Bir diziye erişim başarısız olabilir bir ifadedir, bu nedenle onu bir
if
ifadesi içine yerleştir.if (FirstPlayer := AllPlayers[0]):
-
Oyuncunu (
player
) bir değişkene atamak başarısız olabileceğinden, kodunda oyuncuya referans verirkenoption
(seçenek) türünde bir değişken kullanmalısın. İsteğe bağlı bir?player
oyuncu değişkeni bildir. Bu değişken, diğer üye değişkenlerle uyumlu olmalıdır.objective_coordinator_device<public> := class<concrete>(creative_device): var PlayerOpt<private> : ?player = false @editable PickupMarker<public> : objective_marker = objective_marker{} # İşaretleyicinin hareket ettirileceği yer @editable Destination<public> : transform = transform{} # İşaretleyicinin yeni konumuna ulaşma süresi @editable MoveTime<public> : float = 0.0
-
Yeni değişkenini ayarlayıp bir oyuncunun bulunamadığını sana söyleyecek olan bir
Print()
ifadesine sahip birelse
bloku oluştur. ArtıkFindPlayer()
fonksiyonu tamamlandı.FindPlayer<private>() : void = # Bu bir tek oyunculu deneyim olduğundan ilk oyuncu [0] # kullanılabilir tek oyuncu olmalıdır. AllPlayers := Self.GetPlayspace().GetPlayers() if (FirstPlayer := AllPlayers[0]): set PlayerOpt = option{FirstPlayer} Print("Oyuncu bulundu") else: # Bir oyuncu bulamazsak günlüğe bir hata kaydet. Print("Geçerli oyuncu bulunamadı")
Şimdi OnBegin()
fonksiyonuna geri dönüp iki değişiklik daha yapman gerekiyor:
-
FindPlayer()
fonksiyonunu çağır.OnBegin<override>()<suspends> : void = FindPlayer()
-
MoveMarker()
çağrısından sonra, isteğe bağlı oyuncu değişkenini yeni bir değişkene ayarlamak için başka birif
ifadesi kullan ve onuPickupMarker.MapIndicator.ActivateObjectivePulse()
fonksiyonuna bağımsız değişken olarak ilet.if (FoundPlayer := PlayerOpt?): PickupMarker.MapIndicator.ActivateObjectivePulse(FoundPlayer)
Şimdi kodu çalıştırdığında bölümde karakterinden hedef işaretleyicinin bulunduğu konumu işaret eden hedef atımını göreceksin!
Tam Kodlar
Objective_marker.verse
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Fortnite.com/Devices/CreativeAnimation }
objective_marker<public> := struct<concrete>:
# Hareket ettirilecek nesne
@editable
RootProp<public> : creative_prop = creative_prop{}
# Nesnenin onunla birlikte hareket edecek alt öğesi
@editable
MapIndicator<public> : map_indicator_device = map_indicator_device{}
# objective_marker için bir uzatma metodu
# OverTime öğesinin önündeki “?”, onun bir adlandırılmış bağımsız değişken olduğunu belirtir
(Marker : objective_marker).MoveMarker<public>(Transform : transform, ?OverTime : float)<suspends> : void =
if (OverTime > 0.0):
Marker.RootProp.MoveTo(Transform.Translation, Transform.Rotation, OverTime)
else:
if:
Marker.RootProp.TeleportTo[Transform.Translation, Transform.Rotation]
Objective_coordinator_device.verse
using { /Verse.org/Simulation }
using { /Fortnite.com/Devices }
using { /Fortnite.com/Playspaces }
using { /UnrealEngine.com/Temporary/SpatialMath }
objective_coordinator_device<public> := class<concrete>(creative_device):
var PlayerOpt<private> : ?player = false
@editable
PickupMarker<public> : objective_marker = objective_marker{}
# İşaretleyicinin hareket ettirileceği yer
@editable
Destination<public> : transform = transform{}
# İşaretleyicinin yeni konumuna ulaşma süresi
@editable
MoveTime<public> : float = 0.0
OnBegin<override>()<suspends> : void =
FindPlayer()
PickupMarker.MoveMarker(Destination, ?OverTime := MoveTime)
# Oyuncu false değerine ayarlanmamışsa bulunan oyuncu için hedef atımını etkinleştir
if (FoundPlayer := PlayerOpt?):
PickupMarker.MapIndicator.ActivateObjectivePulse(FoundPlayer)
FindPlayer<private>() : void =
# Bu bir tek oyunculu deneyim olduğundan ilk oyuncu [0]
# kullanılabilir tek oyuncu olmalıdır.
AllPlayers := Self.GetPlayspace().GetPlayers()
if (FirstPlayer := AllPlayers[0]):
set PlayerOpt = option{FirstPlayer}
Print("Oyuncu bulundu")
else:
# Bir oyuncu bulamazsak günlüğe bir hata kaydet.
Print("Geçerli oyuncu bulunamadı")
Kendi Kendine Yapabileceklerin
Burada yazdığın hareket ettirme kodunun tüm nesneler için çalışacağını unutma. Hareket edebilir bir nesneyi bir cihazın üst öğesi yapabilirsen cihaz da nesneyle birlikte hareket edecektir. Başka nesneleri ve cihazları hareket ettirmeyi dene ve bunlardan başka hangi oyunlarda yararlanabileceğini düşün.
Sonraki Adımlar
Bu kılavuzu bir Toplama / Dağıtma oyunu inşa etmek için kullanıyorsan bir sonraki adımın Geri Sayım Süreölçeri özelliğini nasıl oluşturacağını öğrenmek olacak.