Bitki referans projesi

*Bu içerik, yapay zekâ (beta) kullanılarak çevrildi ve hatalar içerebilir. Sayfayı İngilizce görüntülemek için buraya tıkla.

Bitki, oyuncuların tohum ektiği ve suladığı referans deneyimidir, böylece daha sonra ortaya çıkan bitkileri hasat edip satabilirler.

Bitki projesi afişi

Bu proje, Roblox'ta bir deneyim geliştirirken karşılaşabileceğiniz yaygın kullanım durumlarına odaklanmaktadır. Uygun yerlerde, takaslar, uzlaşmalar ve çeşitli uygulama seçimlerinin gerekçeleri hakkında notlar bulacaksınız, böylece kendi deneyimleriniz için en iyi kararı verebilirsiniz.

Dosyayı edinme

  1. Bitki deneyim sayfasına gidin.
  2. düğmesine tıklayın ve Stüdyo'da Düzenle seçeneğini tıklayın.

Kullanım durumları

Bitki aşağıdaki kullanım durumlarını kapsamaktadır:

  • Oturum verileri ve oyuncu verisi kalıcılığı
  • UI görünüm yönetimi
  • İstemci-sunucu ağ iletişimi
  • İlk Kez Kullanıcı Deneyimi (FTUE)
  • Sert ve yumuşak para alımları

Buna ek olarak, bu proje, birçok deneyime uygulanabilen daha dar bir sorun kümesini çözmektedir, bunlar arasında:

  • Bir oyuncuya ait bölgedeki alanın özelleştirilmesi
  • Oyuncu karakterinin hareket hızını yönetme
  • Karakterlerin etrafında takip eden bir nesne oluşturma
  • Bir karakterin dünyada bulunduğu kısmı tespit etme

Bu deneyimde, çok küçük, çok niş veya ilginç bir tasarım zorluğuna çözüm sunmayan birkaç kullanım durumu bulunmaktadır; bunlar kapsama alınmamıştır.

Proje yapısı

Bir deneyim oluştururken ilk karar, projenin nasıl yapılandırılacağına karar vermektir; bu, esas olarak belirli örneklerin veri modelinde nereye yerleştirileceğini ve istemci ve sunucu kodu için giriş noktalarının nasıl organize edileceğini içerir.

Veri modeli

Aşağıdaki tablo, veri modelindeki hizmetlerin hangi konteynerlerde olduğunu açıklamaktadır.

ServisÖrnek türleri
Workspace

Oyuncuya ait olmayan dünyanın parçaları da dahil olmak üzere 3D dünyayı temsil eden statik modelleri içerir. Çalışma zamanında bu örnekleri dinamik olarak oluşturmanız, değiştirmeniz veya yok etmeniz gerekmediğinden, burada bırakılması kabul edilebilir.

Ayrıca, oyuncuların çiftlik modellerinin çalışma zamanında ekleneceği boş bir Folder vardır.

Lighting

Atmosferik ve aydınlatma efektleri.

ReplicatedFirst

Yükleme ekranını görüntülemek ve deneyimi başlatmak için gereken en küçük örnek alt kümesini içerir. ReplicatedFirst içine yerleştirilen daha fazla örnek, ReplicatedFirst içindeki kodun çalışabilmesi için onları çoğaltmak için bekleme süresini uzatır.

  • Instances klasöründe yükleme ekranı GUI'si vardır.
  • Source klasöründe yükleme ekranı kodu ve deneyimin geri kalanının yüklenmesini beklemek için gereken kod bulunmaktadır. start LocalScript, projedeki tüm istemci tarafı kodu için giriş noktasıdır.
ReplicatedStorage

İstemcide ve sunucuda erişimi gereken tüm örnekler için bir depolama konteyneri görevi görür.

  • Dependencies klasöründe projenin kullandığı bazı üçüncü parti kütüphaneler vardır.
  • Instances klasöründe geniş bir önceden hazırlanmış örnek yelpazesi vardır.
  • Source klasöründe yükleme süreci için gerekmeyen ve hem istemciden hem de sunucudan erişilebilen tüm kod bulunur.
ServerScriptService

Projedeki tüm sunucu tarafı kodu için giriş noktası görevi gören bir Script içerir.

ServerStorage

İstemciye çoğaltılması gerekmeyen tüm örnekler için bir depolama konteyneri görevi görür.

  • Instances klasöründe bir şablon Çiftlik modeli vardır. Bu model, oyuncu deneyime katıldığında Workspace'da yerleştirilir ve tüm oyunculara çoğaltılır.
  • Source klasöründe yalnızca sunucuya özgü tüm kod bulunmaktadır.
SoundService

Deneyimdeki ses efektleri için kullanılan Sound nesnelerini içerir. SoundService altında, bu Sound nesnelerinin bir konumu yoktur ve 3D uzayda simüle edilmez.

Giriş noktaları

Çoğu proje, tüm kod tabanında içe aktarılabilen yeniden kullanılabilir ModuleScripts içine kodu organize eder. ModuleScripts yeniden kullanılabilir ancak kendi başlarına çalışmazlar; bir Script veya LocalScript tarafından içe aktarılmaları gerekir. Birçok Roblox projesi, deneyimdeki bir davranışa veya belirli bir sisteme ait olan, her biriyle ilişkili birden fazla Script ve LocalScript nesnesine sahip olacaktır ve bu da birden fazla giriş noktasını yaratır.

Bitki mikro oyununda, tüm istemci kodu için giriş noktası olan tek bir LocalScript ve tüm sunucu kodu için giriş noktası olan tek bir Script aracılığıyla farklı bir yaklaşım uygulanmaktadır. Projeniz için doğru yaklaşım ihtiyaçlarınıza bağlıdır, ancak tek bir giriş noktası, sistemlerin hangi sırayla çalıştırılacağı üzerinde daha fazla kontrol sağlar.

Aşağıdaki listeler, her iki yaklaşımın takaslarını tanımlar:

  • Tek bir Script ve tek bir LocalScript sırasıyla sunucu ve istemci kodunu kapsamaktadır.
  • Tüm kodın tek bir betikten başlatılması sayesinde farklı sistemlerin başlatıldığı sırayı daha fazla kontrol etme imkanı.
  • Sistemler arasında referansla nesneleri geçirebilirsiniz.

Yüksek seviyeli sistem mimarisi

Projede en üst düzey sistemler aşağıda detaylandırılmıştır. Bu sistemlerin bazıları diğerlerinden önemli ölçüde daha karmaşıktır ve birçok durumda işlevsellikleri diğer sınıflar hiyerarşisi üzerinde soyutlanmıştır.

Bitki projesi sistem mimarisi diyagramı

Bu sistemlerin her biri bir "singleton"dır; yani, kendi yöntemleri ile birlikte ihtiyaca göre ilgili istemci veya sunucu start betiği tarafından başlatılan, örneği oluşturulamayan bir sınıftır. Daha fazlasını singleton tasarım deseni hakkında daha sonra bu belgede okuyabilirsiniz.

Sunucu

Aşağıdaki sistemler sunucuyla ilişkilidir.

SistemAçıklama
  • Tüm RemoteEvent ve RemoteFunction nesnelerini oluşturur.
  • İstemciden mesaj gönderme ve dinleme yöntemlerini açığa çıkarır.
  • Çalışma zamanı sırasında istemciden alınan argümanlar için tür doğrulaması yapar.
PlayerDataServer
  • DataStoreService kullanarak kalıcı oyuncu verilerini kaydeder ve yükler.
  • Oyuncu verilerini bellek içinde depolar ve değişiklikleri istemciye çoğaltır.
  • Oyuncu verilerini abone olma, sorgulama ve güncelleme için yöntemler ve sinyaller açığa çıkarır.
Pazar
  • İstemciden yumuşak para işlemlerini yönetir.
  • Hasat edilen bitkileri satmak için bir yöntem sunar.
ÇarpışmaGrupYönetimi
  • Oyuncu karakteri modellerini çarpışma gruplarına atar.
  • Oyuncu karakterlerinin bitki arabalarıyla çarpışmalarını önlemek için çarpışma gruplarını yapılandırır.
FarmManagerServer
  • Bir oyuncunun deneyime katıldığında oyuncu verilerinden çiftlik modelini yeniden oluşturur.
  • Bir oyuncu ayrıldığında çiftlik modelini kaldırır.
  • Bir oyuncunun çiftliği değiştiğinde oyuncu verilerini günceller.
  • Verilen bir oyuncuyla ilişkili Çiftlik sınıfına erişmek için bir yöntem sunar.
PlayerObjectsContainer
  • Bir oyuncunun yaşam döngüsü ile ilişkili çeşitli nesneleri oluşturur ve bunları almak için bir yöntem sağlar.
TagPlayers
FtueManagerServer
  • FTUE sırasında her aşamayı çalıştırır ve tamamlanmasını bekler.
CharacterSpawner
  • Karakterler öldüğünde yeniden canlandırır. Players.CharacterAutoLoads devre dışı bırakıldığı için, oyuncunun verisi yüklenene kadar canlandırmanın durdurulması sağlanır.

İstemci

Aşağıdaki sistemler istemciyle ilişkilidir.

SistemAçıklama
  • Sunucunun tüm RemoteEvent ve RemoteFunction nesnelerini oluşturmasını bekler.
  • Sunucuya ve sunucudan mesaj gönderme ve dinleme için yöntemler sunar.
  • Çalışma zamanı parametre türü doğrulaması uygular.
  • Uzak işlevler üzerinde pcall() çalıştırır.
PlayerDataClient
  • Yerel oyuncunun verilerini bellek içinde depolar.
  • Oyuncu verilerindeki değişiklikleri sorgulama ve abone olma için yöntemler ve sinyaller sunar.
Pazarİstemci
  • İstemciden sunucudan bir öğeyi yumuşak para ile satın almak için bir yöntem talep etme sunar.
LocalWalkJumpManager
  • Bir karakterin WalkSpeed veya JumpHeight değerlerini değiştirmek için çarpanlar ile yöntemler sunar, böylece bu değerleri birden fazla yerden değiştirirken çakışmalardan kaçınılır.
FarmManagerClient
  • Belirli CollectionService etiketlerinin örneklere uygulanmasını dinler ve bu örneklere davranış ekleyen "bileşenler" oluşturur. Bir "bileşen", bir CollectionService etiketi bir örneğe eklendiğinde oluşturulan ve kaldırıldığında yok edilen bir sınıfı ifade eder; bunlar çiftlikteki CTA istemleri ve çeşitli sınıfların çiftlik durumunu oyuncuya iletmek için kullanılır.
UIKurulum
  • Tüm UI katmanlarını başlatır.
  • Belirli katmanları yalnızca dünyanın fiziksel bölümlerinde görünür olacak şekilde yapılandırır.
  • Menülerin etkinleştirildiği durumlar için özel bir kamera efekti uygular.
FtueManagerClient
  • İstemcide FTUE aşamalarını yapılandırır.
CharacterSprint
  • Bir oyuncu karakteri çiftliğinin dışındayken WalkSpeed değerini artırmak için LocalWalkJumpManager'ı kullanır.

İstemci-sunucu iletişimi

Çoğu Roblox deneyimi, istemci ile sunucu arasında bazı iletişim unsurlarını içerir. Bu, istemcinin sunucudan belirli bir eylem gerçekleştirmesini talep etmesini ve sunucunun istemciye güncellemeleri çoğaltmasını içerebilir.

Bu projede, istemci-sunucu iletişimi mümkün olduğunca genel tutulmaktadır; RemoteEvent ve RemoteFunction nesnelerinin kullanımını sınırlandırarak takip edilmesi gereken özel kural sayısını azaltmaktadır. Bu proje, şu yöntemleri tercih sırasına göre kullanmaktadır:

Oyuncu verisi sistemi aracılığıyla çoğaltma

oyuncu verisi sistemi, verilerin bir oyuncu ile ilişkilendirilmesi ve kaydetme oturumları arasında kalıcı olması için izin verir. Bu sistem, istemciden sunucuya çoğaltma sağlar ve veri sorgulama ve değişikliklere abone olma için kullanılabilecek bir dizi API sunar; bu, sunucudan istemciye oyuncu durumundaki değişikliklerin çoğaltılması için idealdir.

Örneğin, istemciye kaç jetonu olduğunu belirtmek için özel bir UpdateCoins RemoteEvent ateşlemek yerine, aşağıdaki çağrıyı yapabilir ve istemcinin PlayerDataClient.updated etkinliğine abone olmasını sağlayabilirsiniz.


PlayerDataServer.setValue(player, "coins", 5)

Elbette, bu yalnızca sunucudan istemciye çoğaltma için ve oturumlar arasında kalıcı olmasını istediğiniz değerler için yararlı olacaktır; ancak bu, projedeki oldukça çok sayıda durum için geçerlidir, bunlar arasında:

  • Mevcut FTUE aşaması
  • Oyuncunun envanteri
  • Oyuncunun sahip olduğu jeton miktarı
  • Oyuncunun çiftliğinin durumu

Öznitelikler aracılığıyla çoğaltma

Sunucunun belirli bir Instance için, istemciye çoğaltması gereken özel bir değeri çoğaltması gerektiğinde, öznitelikleri kullanabilirsiniz. Roblox, öznitelik değerlerini otomatik olarak çoğaltır, bu nedenle bir nesneyle ilişkili durumu çoğaltmak için herhangi bir kod yolu tutmanıza gerek yoktur. Bir diğer avantaj, bu çoğaltmanın nesne ile birlikte gerçekleşmesidir.

Bu, çalışma zamanı sırasında oluşturulan örnekler için özellikle faydalıdır; çünkü veri modeline eklenecek olan bir yeni örnekten önce ayarlanan öznitelikler atomik olarak bu örnek ile çoğaltılacaktır. Bu, RemoteEvent veya StringValue aracılığıyla ek verilerin çoğaltılması için bekleme kodu yazma gereğini ortadan kaldırır.

İster istemci ister sunucu olsun, veri modelinden doğrudan GetAttribute() yöntemi ile öznitelikleri okuyabilir ve değişikliklere GetAttributeChangedSignal() yöntemi ile abone olabilirsiniz. Bitki projesinde, bu yaklaşım, diğer şeylerin yanı sıra, bitkilerin mevcut durumunu istemcilere çoğaltmak için kullanılmaktadır.

Etiketler aracılığıyla çoğaltma

CollectionService, bir Instance'e bir dize etiketi uygulamanıza olanak tanır. Bu, örnekleri kategorize etmek ve bu kategorilerin istemciye çoğaltılmasını sağlamak için faydalıdır.

Örneğin, CanPlant etiketi, bir bitkinin ekleneceği belirli bir saksının istemcinin bu potu alabileceğini belirtmek için sunucuda uygulanır.

Ağ modülü aracılığıyla doğrudan mesajlaşma

Önceki seçeneklerin hiçbiri uygulanmıyorsa, modülü aracılığıyla özel ağ çağrılarını kullanabilirsiniz. Bu proje, istemciden sunucuya iletişimi sağlayan tek seçenektir ve bu nedenle istemci taleplerini iletmek ve sunucu yanıtı almak için en yararlısıdır.

Bitki, aşağıdaki istemci taleplerinin bir dizi için doğrudan ağ çağrılarını kullanır:

  • Bir bitkiyi sulama
  • Bir tohum ekme
  • Bir öğe satın alma

Bu yaklaşımın en büyük dezavantajı, her bir bireysel mesajın bazı özel yapılandırmalar gerektirmesidir; bu da projenin karmaşıklığını artırabilir. Ancak, bu, özellikle sunucudan istemciye iletişimde olabildiğince ortadan kaldırılmıştır.

Sınıflar ve singletonlar

Bitki projesindeki sınıflar, Roblox'taki örnekler gibi oluşturulabilir ve yok edilebilir. Sınıf sözdizimi, nesne yönelimli programlamaya yönelik yazım tarzıyla ilgili bazı değişiklikler ile Luau'nun geleneksel yaklaşımından ilham almıştır ve katı tür denetimi desteğini etkinleştirmek için bir dizi değişiklik içerir.

Oluşturma

Projede birçok sınıf bir veya daha fazla Instances ile ilişkilidir. Belirli bir sınıfın nesneleri, Roblox'taki örneklerin oluşturulması sırasında kullanılan new() yöntemi ile oluşturulmaktadır.

Bu desen, genel olarak veri modelinde fiziksel bir temsili olan nesneler için kullanılmaktadır ve sınıf, işlevselliğini genişletmektedir. İyi bir örnek, iki verilen Attachment nesnesi arasında bir Beam nesnesi oluşturan BeamBetween sınıfıdır ve bu bağlantıların yönlerini, ışının her zaman yukarıya bakmasını sağlamak için tutar. Bu örnekler, ReplicatedStorage'da önceden hazırlanmış bir versiyondan çoğaltılabilir veya new() argümanı olarak geçirilip nesne içinde self altında saklanabilir.

Karşılık gelen örnekler

Yukarıda belirtildiği gibi, projedeki birçok sınıfın veri modeli temsilcisi vardır; sınıf ile ilişkili ve onun tarafından manipüle edilen bir örnek.

Bu örnekler oluşturulurken, kod genel olarak Clone() ile ReplicatedStorage veya ServerStorage altında depolanan önceden hazırlanmış bir sürüm çoğaltmayı tercih etmektedir. Bu örneklerin özelliklerini serileştirib özel olarak oluşturmak mümkün olsa da, bunu yapmak nesneleri düzenlemeyi oldukça zahmetli hale getirir ve okuyucunun bunları anlamasını zorlaştırır. Bunun yanı sıra, bir örneği çoğaltmak, yeni bir örnek oluşturup çalışma zamanında özelliklerini özelleştirmekten genellikle daha hızlı bir işlemdir.

Kompozisyon

Luau'da metatable kullanarak kalıtsallık mümkün olsa da, proje bunun yerine sınıfların kompozisyon yoluyla birbiriyle genişlemesine izin vermeyi tercih etmektedir. Kompozisyon yoluyla sınıfları birleştirirken, "çocuk" nesnesi sınıfın new() yönteminde oluşturulur ve self altında bir üye olarak dahil edilir.

Bunun bir örneğini, Button sınıfını saran CloseButton sınıfında görebilirsiniz.

Temizlik

Bir Instance, Destroy() yöntemi ile yok edilebildiği gibi, oluşturulabilen sınıflar da yok edilebilir. Projedeki sınıflar için yok edici yöntem destroy() olup, camelCase tutarlılığı sağlamak için küçük harfle yazılmıştır, ayrıca projenin sınıflarıyla Roblox örneklerini ayırmak için kullanılır.

destroy() yönteminin rolü, nesneyle oluşturulan örnekleri yok etmek, bağlantıları kesmek ve çocuk nesnelerde destroy() çağırmaktır. Bu özellikle bağlantılar için önemlidir çünkü aktif bağlantılara sahip nesneler, nesneye veya bağlantılara olan referansların kalmadığı durumlarda bile Luau çöp toplayıcısı tarafından temizlenmez.

Singletonlar

Singletonlar, adından da anlaşılacağı gibi, yalnızca bir nesnenin var olabileceği sınıflardır. Bunlar, projenin Roblox'la Hizmetler karşılığıdır. Singleton nesnesine bir referans depolamak ve Luau kodunda dolaşımını sağlamak yerine, Bitki ModuleScript'in gerek duyulan değeri önbelleğe aldığını kullanma avantajından yararlanmaktadır. Bu, farklı yerlerden aynı singleton ModuleScript'i talep etmenin sürekli olarak aynı dönen nesneyi sağlaması anlamına gelir. Bu kuralın tek istisnası, farklı ortamların (istemci veya sunucu) ModuleScript'e eriştiği durumlarda geçerlidir.

Singletonlar, bir new() yöntemi olmadığından, oluşturulabilir sınıflardan ayrılmaktadır. Bunun yerine nesne ve durumları doğrudan ModuleScript aracılığıyla döndürülmektedir. Singletonlar oluşturulmadığından, self sözdizimi kullanılmamaktadır ve yöntemler yerine nokta (.) ile çağrılmaktadır.

Katı tür çıkarımı

Luau kademeli tipleri desteklemektedir; bu, bazı veya tüm kodunuza isteğe bağlı tür tanımları ekleyebileceğiniz anlamına gelir. Bu projede, her betik için strict tür denetimi kullanılmaktadır. Bu, Roblox'un Betik Analizi aracı için en az izin veren seçenektir ve dolayısıyla çalışma zamanı öncesinde tür hatalarını yakalama olasılığı en yüksektir.

Tipi belirlenmiş sınıf sözdizimi

Luau'da sınıf oluşturma için mevcut olan yaklaşım iyi belgelenmiştir, ancak bu, güçlü Luau tipi için pek uygun değildir. Luau'da bir sınıfın tipini almanın en basit yolu typeof() yöntemidir:


type ClassType = typeof(Class.new())

Bu çalışır, ancak sınıfınızın çalışma zamanında yalnızca mevcut olan değerlere sahip olduğu durumlarda pek kullanışlı değildir; örneğin Player nesneleri. Bunun yanı sıra, geleneksel Lua sınıf sözdiziminde self üzerinde bir yöntemin tanımlanmasının her zaman o sınıfın bir örneği olacağı varsayılmaktadır; bu, tip çıkarım motorunun yapabileceği bir varsayım değildir.

Katı tür çıkarımını desteklemek amacıyla, Bitki projesi, geleneksel Lua sınıf sözdiziminden çeşitli şekillerde farklı bir çözüm kullanmaktadır; bunların bazıları sezgisel hissettirmeyebilir:

  • self tanımının hem tip açıklamasında hem de yapıcıda yinelendiği. Bu, bakım yükü getirir; ancak, iki tanımın birbirleriyle senkronize edilmediği durumlarda uyarılar olacaktır.
  • Sınıf yöntemleri, self'in türünün ClassType olarak açık bir şekilde tanımlanabilmesi için nokta ile tanımlanmaktadır. Yöntemler hâlâ beklenildiği gibi iki nokta ile çağrılabilir.

--!strict
local MyClass = {}
MyClass.__index = MyClass
export type ClassType = typeof(setmetatable(
{} :: {
property: number,
},
MyClass
))
function MyClass.new(property: number): ClassType
local self = {
property = property,
}
setmetatable(self, MyClass)
return self
end
function MyClass.addOne(self: ClassType)
self.property += 1
end
return MyClass

Mantıksal bekçeler sonrasında türleri dönüştürme

Yazma anında, bir değerin türü bir bekçi (guard) koşul ifadesinden sonra daraltılmamaktadır. Örneğin, aşağıdaki bekçi sonrasında optionalParameter'ın türü number olarak daraltılmaz.


--!strict
local function foo(optionalParameter: number?)
if not optionalParameter then
return
end
print(optionalParameter + 1)
end

Bunu hafifletmek için, bu bekçelerden sonra açıkça dönüştürülmüş türü ile yeni değişkenler oluşturulmaktadır.


--!strict
local function foo(optionalParameter: number?)
if not optionalParameter then
return
end
local parameter = optionalParameter :: number
print(parameter + 1)
end

Veri Modeli hiyerarşilerini dolaşma

Bazı durumlarda, kod tabanı, çalışma zamanında oluşturulan nesnelerin bir ağacını veri modeli hiyerarşisinde dolaşmak zorundadır. Bu, tür denetimi açısından ilginç bir zorluk oluşturmaktadır. Yazma anında, bir veri modeli hiyerarşisini bir tip olarak tanımlamak mümkün değildir. Sonuçta, veri modeli yapısı için mevcut olan tek tip bilgisi, en üst düzey örneğin türü olacaktır.

Bu zorluğa bir yaklaşım, any türüne dönüştürmek ve ardından rafine etmektir. Örneğin:


local function enableVendor(vendor: Model)
local zonePart: BasePart = (vendor :: any).ZonePart
end

Bu yaklaşım, okunabilirliği etkilediğinden sorun oluşturur. Bunun yerine, proje veri modeli hiyerarşilerini dolaşmak için, içsel olarak any türüne dönüştüren getInstance adında genel bir modül kullanmaktadır.


local function enableVendor(vendor: Model)
local zonePart: BasePart = getInstance(vendor, "ZonePart")
end

Tip motorunun veri modeli anlayışı geliştikçe, bu tür kalıpların artık gerekli olmaması mümkündür.

Kullanıcı arayüzü

Bitki çeşitli karmaşık ve basit 2D kullanıcı arayüzleri içermektedir. Bu, jeton sayacı gibi etkileşimde bulunmayan üst bilgi görüntüleme (HUD) öğeleri ve mağaza gibi karmaşık etkileşimli menüleri içerir.

UI yaklaşımı

Roblox UI ile HTML DOM'u birbirine çok benzer bir şekilde karşılaştırabiliriz.Tam bir nesne hiyerarşisi olan bir özelliktir ve bunun üstünde kullanıcının ne görmesi gerektiğini tanımlar. Roblox'ta bir UI oluşturma ve güncelleme yaklaşımları genel hatlarıyla imperatif ve declarative uygulama yöntemlerine ayrılmıştır.

YaklaşımAvantajlar ve dezavantajlar
Imperatif

Imperatif yaklaşımda, UI, Roblox'taki diğer örnek hiyerarşi nesneleri gibi ele alınır. UI yapısı, çalışma zamanından önce Stüdyo'da oluşturulur ve veri modeline eklenir; genellikle doğrudan StarterGui'da. Ardından, çalışma zamanında kod, yaratıcının gerektirdiği durumu yansıtmak için UI'nin belirli parçalarını değiştirir.

Bu yaklaşımın bazı avantajları vardır. UI'yi Stüdyo'da scratch'tan oluşturabilir ve bunu veri modeline kaydedebilirsiniz. Bu, UI oluşturma sürecini hızlandıran basit ve görsel bir düzenleme deneyimi sunar. Imperatif UI kodu yalnızca değişiklik gerektiren durumlarla ilgilendiğinden, basit UI değişikliklerini uygulamak da kolaylaşır.

Önemli bir dezavantaj, imperatif UI yaklaşımlarının, durumları dönüşümler şeklinde manuel olarak uygulamanızı gerektirmesidir; bu da karmaşık durum temsillerinin oldukça zor bulunmasını ve hata ayıklanmasını gerektirebilir. Genellikle imperatif UI kodu geliştirilirken hataların ortaya çıkması yaygındır, özellikle de durum ve UI, beklenmedik bir sıradaki birden fazla güncellemeden dolayı senkronizasyonsuz hale geldiğinde.

Imperatif yaklaşımların bir diğer zorluğu, UI'yi anlamlı bileşenlere ayırmanın daha zor olmasıdır; bu bileşenler bir kez açıklanıp yeniden kullanılabilirler. Tüm UI ağacının düzenleme zamanında tanımlanması nedeniyle, yaygın kalıplar veri modelinin birden fazla yerinde tekrarlanabilir.

Deklaratif

Deklaratif yaklaşımda, UI örneklerinin arzu edilen durumu açıkça belirtilir, bu durumu etkili bir şekilde uygulamak ise Roact veya Fusion gibi kütüphaneler tarafından soyutlanmaktadır.

Bu yaklaşımın avantajı, durumun uygulanması önemsiz hale gelmesi ve yalnızca UI'nizin nasıl görünmesini istediğinizi tanımlamanız gerektiğidir. Bu, hata ayıklamayı ve tespit etmeyi önemli ölçüde kolaylaştırır.

Önemli bir dezavantaj, tüm UI ağacını kodda belirtme zorunluluğudur. Roact ve Fusion gibi kütüphanelerin bunu kolaylaştırmak için bir sözdizimi vardır; ancak bu hâlâ zaman alıcı bir süreçtir ve UI’yi bir araya getirirken daha az sezgisel bir düzenleme deneyimi sağlar.

Bitki imperatif bir yaklaşım kullanmaktadır; bu da dönüşümlerin doğrudan gösterilmesinin Roblox'ta UI'nin nasıl oluşturulup manipüle edildiğine dair daha etkili bir genel bakış sağladığı düşüncesindendir. Bu, deklaratif bir yaklaşımla mümkün değildir. Bazı yinelenen UI yapıları ve mantıkları da, imperatif UI tasarımında yaygın bir tuzaktan kaçınmak için yeniden kullanılabilir bileşenlere soyutlanmıştır.

Yüksek seviyeli mimari

Bitki projesi UI mimarisi diyagramı

Katman ve bileşenler

Bitki'de tüm UI yapıları ya bir Layer ya da bir Component'dir.

  • Layer, ReplicatedStorage'da önceden hazırlanmış UI yapılarını saran üst düzey bir grup singleton olarak tanımlanmaktadır. Bir katman, birçok bileşen içerebilir ya da tüm mantığını tamamen kapsülleyebilir. Katmanlar arasında envanter menüsü veya üst bilgi görüntüleme jeton sayacı gibi örnekler vardır.
  • Component, yeniden kullanılabilir bir UI öğesidir. Yeni bir bileşen nesnesi oluşturulduğunda, ReplicatedStorage'dan önceden hazırlanmış bir şablonu klonlar. Bileşenler, kendileri başka bileşenler içerebilir. Bileşenler arasında genel bir buton sınıfı ya da bir öğe listesi kavramı vardır.

Görüntü yönetimi

Yaygın bir UI yönetimi sorunu, görüntü yönetimidir. Bu proje, kullanıcı girişlerini dinleyen çeşitli menüler ve HUD öğelerine sahiptir ve bunların görünür veya etkin olma zamanlarının dikkatlice yönetilmesi gerekmektedir.

Bitki, bir UI katmanının görünür olup olmayacağını yöneten UIHandler sistemi sayesinde bu sorunu ele almaktadır. Deneyimdeki tüm UI katmanları HUD veya Menu olarak kategorize edilir ve görünürlükleri aşağıdaki kurallar tarafından yönetilir:

  • Menu ve HUD katmanlarının etkin durumu değiştirilebilir.
  • Etkin HUD katmanları, hiçbir Menu katmanı etkin değilse yalnızca gösterilir.
  • Etkin Menu katmanları bir yığında saklanır ve her seferinde yalnızca bir Menu katmanı görünür. Bir Menu katmanı etkinleştirildiğinde, yığının en önüne eklenir ve gösterilir. Bir Menu katmanı devre dışı bırakıldığında, yığından kaldırılır ve sıradaki etkin Menu katmanı gösterilir.

Bu yaklaşım sezgiseldir çünkü menüleri geçmiş ile gezilebilir hale getirir. Eğer bir menü başka bir menüden açılırsa, yeni menü kapatıldığında eski menü tekrar görünecektir.

Daha fazla okuma

Bitki projesinin bu kapsamlı incelemesinden sonra, ilişkili kavramlar ve konular hakkında daha derinlemesine incelemek isteyebileceğiniz aşağıdaki kılavuzları keşfetmek isteyebilirsiniz.

  • İstemci-Sunucu Modeli — Roblox'taki istemci-sunucu modeli hakkında genel bir bakış.
  • Luau — Roblox tarafından oluşturulan Luau ile ilgili detaylar; Lua 5.1 versiyonundan türeemiştir.
  • Uzaktan Etkinlikler ve Geri Çağırmalar — İstemci-sunucu sınırında iletişim için uzaktan ağ olayları ve geri çağırmalar hakkında her şey.
  • UI — Roblox'taki kullanıcı arayüzü nesneleri ve tasarım hakkında detaylar.
©2026 Roblox Corporation. Roblox, the Roblox logo and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.