Paketler paketi

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

Paketler özelliği paketi, oyunculara indirimle koleksiyon halinde ürünler satmak için kutudan çıktığı gibi işlevsellik sunar. Oyuncuların paketleri özel deneyim içi para birimi veya Robux ile satın almasına izin verip vermeyeceğinizi, hangi paket türünü kullanmak istediğinizi, satmak istediğiniz ürün setini ve oyuncuları oyun sırasında nasıl bilgilendirmek istediğinizi seçebilirsiniz.

Paketin özelleştirme seçeneklerini kullanarak, paketlerinizi deneyimlerinizin tasarım ve para kazanma hedeflerine ulaşacak şekilde özelleştirebilirsiniz, örneğin:

  • Yeni oyunculara değer sağlayan ve erken harcamaları teşvik eden indirimli başlangıç paketleri sunarak düşük dönüşüm oranı ölçütünü hedeflemek.
  • Çeşitli fiyat noktalarında ürünleri birleştirerek daha geniş bir oyuncu yelpazesine hitap etmek için harcama derinliğini artırmak.
  • Sınırlı süreli özel ürün paketleri sunarak canlı operasyonlar (LiveOps) etkinliklerini paraya dönüştürmek.

Paketi al

Yaratıcı Mağaza, projelerinizde kullanılmak üzere Roblox ve Roblox topluluğu tarafından oluşturulan tüm varlıkları bulabileceğiniz Araç Kutusunun bir sekmesidir. Model, resim, mesh, ses, eklenti, video ve font varlıklarını da içerir. Yaratıcı mağazayı kullanarak bir veya daha fazla varlığı açık bir deneyime doğrudan ekleyebilirsiniz, ayrıca özellik paketlerini de ekleyebilirsiniz!

Her özellik paketi, düzgün çalışması için Çekirdek özellik paketine ihtiyaç duyar. Çekirdek ve Paketler özellik paketi varlıklarınız envanterinizde bulunduktan sonra, onları platformdaki herhangi bir projede yeniden kullanabilirsiniz.

Envanterinizdeki paketleri deneyiminize almak için:

  1. Aşağıdaki bileşenlerden oluşan setteki Envantere Ekle bağlantısına tıklayarak Çekirdek ve Paketler özellik paketlerini Studio içinde envanterinize ekleyin.

  2. Studio'nun Pencere menüsü veya Ana Sayfa sekmesi araç çubuğundan Araç Kutusunu açın.

  3. Araç Kutusu penceresinde, Envanter sekmesine tıklayın. Modellerim sıralaması görüntülenir.

    Studio'nun Araç Kutusu penceresi, Envanter sekmesi vurgulanmış.
  4. Özellik Paketi Çekirdek kutucuğuna tıklayın, sonra Paket Özellik Paketi kutucuğuna tıklayın. Her iki paket klasörü Keşfedin penceresinde görüntülenir.

  5. Paket klasörlerini ReplicatedStorage içine sürükleyin.

  6. Paketlerle birlikte oyuncu satın alımlarını takip etmek için veri mağazası çağrılarına izin verin.

    1. Studio'nun DosyaDeneyim Ayarları penceresini açın.
    2. Güvenlik sekmesine gidin, ardından API Hizmetlerine Studio Erişimini Etkinleştir seçeneğini etkinleştirin.

Para birimlerini tanımla

Eğer deneyiminizin kendi para birimi sistemi varsa, bunları Çekirdek özellik paketi ile tanımlayarak kaydedebilirsiniz; ReplicatedStorage.FeaturePackagesCore.Configs.Currencies içinde tanımlayarak. Bu dosyada zaten yorum satırlarında bir Gemler para birimi örneği var; bunu kendi para biriminizle değiştirebilirsiniz.

Para Birimleri

Gems = {
displayName = "Gemler",
symbol = "💎",
icon = nil,
},

Para Birimleri betiği, Çekirdek özellik paketine para biriminiz hakkında bazı meta verileri belirtir:

  • (zorunlu) displayName - Para biriminizin adı. Eğer bir sembol veya simge belirtmezseniz, bu ad satın alma düğmelerinde kullanılır (yani "100 Gemler").
  • (isteğe bağlı) symbol - Para biriminiz için simge olarak kullanmak üzere bir metin karakteriniz varsa, bu, satın alma düğmelerindeki displayName yerine kullanılır (yani "💎100").
  • (isteğe bağlı) icon - Para biriminiz için bir AssetId resim simgeniz varsa, bu displayName yerine kullanılacaktır (yani resim fiyatın soluna yerleştirilecektir "🖼️100").

Para biriminiz ayarlandığında, paketin fiyatını, para birimini ve bilgi ekranı görüntüsü için simgeyi manuel olarak belirtmeniz gerekir; bu bilgi, paketin ilişkilendirilmiş geliştirici ürününden alınmaz.

Paketler

-- Eğer bir dev ürünü kullanmak istiyorsanız, yalnızca bir pakete ait olan eşsiz bir devProductId sağlamanız gerekir.
-- Paket fiyatı ve simgesini geliştirici ürününden alacağız
pricing = {
priceType = CurrencyTypes.PriceType.Marketplace,
devProductId = 1795621566,
},
-- Aksi halde, bir dev ürünü yerine deneyim içi para birimi kullanmak istiyorsanız, aşağıdakileri kullanabilirsiniz:
-- Fiyat burada deneyim içindeki para biriminde, Robux değil
pricing = {
priceType = CurrencyTypes.PriceType.InExperience,
price = 79,
currencyId = "Gems",
icon = 18712203759,
},

Ayrıca BundlesExample betiğini referans alarak setInExperiencePurchaseHandler çağrısını yapmanız gerekir.

BundlesExample

local function awardInExperiencePurchase(
_player: Player,
_bundleId: Types.BundleId,
_currencyId: CurrencyTypes.CurrencyId,
_price: number
)
-- Oyuncunun paketi satın almak için yeterli parası olup olmadığını kontrol et
-- Oyuncu verilerini güncelle, ürünleri ver, vb.
-- Oyuncudan parayı düş
task.wait(2)
return true
end
local function initializePurchaseHandlers()
local bundles = Bundles.getBundles()
for bundleId, bundle in bundles do
-- Eğer pazar fiyat türü yoksa, paket geliştirici ürünü ile ilişkili değildir
if not bundle or bundle.pricing.priceType ~= "Marketplace" then
continue
end
Bundles.setPurchaseHandler(bundleId, awardMarketplacePurchase)
receiptHandlers[bundle.pricing.devProductId] = receiptHandler
end
-- Eğer paketler için kullandığınız herhangi bir deneyim içi para biriminiz varsa, burada handler'ı ayarlayın
for currencyId, _ in Currencies do
Bundles.setInExperiencePurchaseHandler(currencyId, awardInExperiencePurchase)
end
end

Özellikle, awardInExperiencePurchase fonksiyonunu doldurmanız gerekir; bu, Currencies üzerinden bir döngü ile çağrılır (yani her currencyId, Bundles.setInExperiencePurchaseHandler(currencyId, awardInExperiencePurchase) ile handler'a bağlıdır).

Paketleri tanımla

Deneyiminizde sunulabilir tüm paketler ReplicatedStorage.Bundles.Configs.Bundles içinde tanımlanabilir; tipler aynı klasördeki Types scriptinden dışa aktarılmıştır.

Eğer bir devProductId kullanıyorsanız, paketin ana devProductId'sini deneyiminizdeki ile eşleştirmenizi gerektirir. Bu, paketi satın almak için MarketplaceService üzerinden yönlendirilecektir. Satışların ayrı bir şekilde takip edilmesini kolaylaştırmak için pakete yeni bir geliştirici ürünü kullanmanız şiddetle önerilir.

Eğer birden fazla ürün bulunan bir paket istiyorsanız ve bunlar deneyiminizde geliştirici ürünleri ile zaten temsil ediliyorsa, ürün fiyatı/assetId/isimlerini açıkça ayarlamanıza gerek yoktur, bunlar ürün bilgileri üzerinden alınacaktır:

README

{
itemType = ItemTypes.ItemType.DevProduct,
devProductId = <DEV_PRODUCT_ID>,
metadata = {
caption = {
text = "x1",
color = Color3.fromRGB(236, 201, 74),
} -- Altyazı isteğe bağlıdır! Bu alanı da çıkarabilirsiniz
}
},

Aksi takdirde, bu ürün bilgilerini manuel olarak yapılandırabilirsiniz:

README

{
itemType = ItemTypes.ItemType.Robux,
priceInRobux = 49,
icon = <IMAGE_ASSET_ID>,
metadata = {
caption = {
text = "x1",
color = Color3.fromRGB(236, 201, 74),
} -- Altyazı isteğe bağlıdır! Bu alanı da çıkarabilirsiniz
}
},

Örneğin, tüm paketiniz muhtemelen şöyle görünecektir:

README

local starterBundle: Types.RelativeTimeBundle = {
bundleType = Types.BundleType.RelativeTime,
-- Eğer bir dev ürünü kullanmak istiyorsanız, yalnızca bir pakete ait olan eşsiz bir devProductId sağlamanız gerekir.
-- Paket fiyatı ve simgesini geliştirici ürününden alacağız
pricing = {
priceType = CurrencyTypes.PriceType.Marketplace,
devProductId = <DEV_PRODUCT_ID>,
},
-- Aksi takdirde, bir dev ürünü yerine deneyim içi para birimi kullanmak istiyorsanız, aşağıdakileri kullanabilirsiniz:
-- Fiyat burada deneyim içindeki para biriminde, Robux değil
-- pricing = {
-- priceType = CurrencyTypes.PriceType.InExperience,
-- price = 79,
-- currencyId = <CURRENCY_ID>,
-- icon = <IMAGE_ASSET_ID>,
-- },
includedItems = {
[1] = {
-- Ürün geliştirici ürünü aracılığıyla satılmadığından, Robux cinsinden değerini belirtin ve bir simge verin
-- priceInRobux, Paketlerin paket fiyatı ile içindekilerin toplam değeri arasında ilişki göstermesine yardımcı olur
itemType = ItemTypes.ItemType.Robux,
priceInRobux = 49,
icon = <IMAGE_ASSET_ID>,
-- Alternatif olarak, eğer bu bir dev ürünü ise yukarıdaki fiyat ve simgeyi bırakın ve sadece devProductId'yi ayarlayın
-- Fiyat ve simge geliştirici ürününden alınacaktır
-- devProductId = <ITEM_DEV_PRODUCT_ID>
-- Eğer gerekirse UI'ye özgü daha fazla isteğe bağlı meta veri alanı vardır
metadata = {
caption = {
text = "x1",
color = Color3.fromRGB(236, 201, 74),
},
},
},
[2] = {
itemType = ItemTypes.ItemType.Robux,
priceInRobux = 99,
icon = <IMAGE_ASSET_ID>,
metadata = {
caption = {
text = "x1",
color = Color3.fromRGB(236, 201, 74),
},
},
},
[3] = {
itemType = ItemTypes.ItemType.Robux,
priceInRobux = 149,
icon = <IMAGE_ASSET_ID>,
metadata = {
caption = {
text = "x1",
color = Color3.fromRGB(236, 201, 74),
},
},
},
},
singleUse = true, -- Bir kez satın alındıktan veya süresi dolduktan sonra geçerli değildir; deneyiminiz tekrar prompte ulaşmaya çalışsa bile. Test aşamasında bunu false yapabilirsiniz.
durationInSeconds = 900, -- 15 dakika
includesOfflineTime = false, -- Sadece deneyimde geçen süre sayılır
metadata = {
displayName = "BAŞLANGIÇ PAKETİ",
description = "Yüzde 75 tasarruf edin ve başlanğıç yapın!",
},
}

Sunucu mantığını entegre et

ReplicatedStorage.Bundles.Server.Examples.BundlesExample'a bir göz atın, bu betik Paketler özellik paketi ile sunucunuzun nasıl etkileşime gireceğini ve yukarıdaki yöntemleri gösterir. Aşağıdaki parçalar bu betikten alınmıştır.

Paketler özellik paketini deneyiminize sürükledikten sonra dört şeyi bağlamanız gerekecek:

  1. Bundles.setPurchaseHandler aracılığıyla satın alma işlemi sırasında ürünleri ödüllendirmek için hangi fonksiyonların çağrılacağını belirlemek için satın alma yönetici işlem bağlayıcılarını bağlayın.

    BundlesExample

    local function awardMarketplacePurchase(_player: Player, _bundleId: Types.BundleId, _receiptInfo: { [string]: any })
    -- Oyuncu verilerini güncelle, ürünleri ver, vb.
    -- ... VE receiptInfo.PurchaseId'yi kaydederek kullanıcı zaten bu pakete sahip mi kontrol edebilirsiniz
    task.wait(2)
    return Enum.ProductPurchaseDecision.PurchaseGranted
    end
    local function awardInExperiencePurchase(
    _player: Player,
    _bundleId: Types.BundleId,
    _currencyId: CurrencyTypes.CurrencyId,
    _price: number
    )
    -- Oyuncunun paketi satın almak için yeterli parası olup olmadığını kontrol et
    -- Oyuncu verilerini güncelle, ürünleri ver, vb.
    -- Oyuncudan parayı düş
    task.wait(2)
    return true
    end
    local function initializePurchaseHandlers()
    local bundles = Bundles.getBundles()
    for bundleId, bundle in bundles do
    -- Paket, geliştirici ürünü ile ilişkili değilse pazar geçerli fiyat türü olamaz
    if not bundle or bundle.pricing.priceType ~= "Marketplace" then
    continue
    end
    Bundles.setPurchaseHandler(bundleId, awardMarketplacePurchase)
    receiptHandlers[bundle.pricing.devProductId] = receiptHandler
    end
    -- Eğer paketler için kullandığınız her hangi bir deneyim içi para biriminiz varsa, burada handler'ı ayarlayın
    for currencyId, _ in Currencies do
    Bundles.setInExperiencePurchaseHandler(currencyId, awardInExperiencePurchase)
    end
    end
  2. MarketplaceService.ProcessReceipt için mantığınızı bağlayın, ancak bu, deneyimizin zaten satışta geliştirici ürünleri varsa başka bir yerde yapılandırılabilir. Temelde, bir geliştirici ürünü makbuzu işlenirken, şimdi Bundles.getBundleByDevProduct çağrılır; eğer ürün bir pakete aitse, script Bundles.processReceipt çağrısını yapar.

    BundlesExample

    -- Pazar makbuzunu işleyin, böylece oyuncudan ücret alınıp alınmadığını belirleyin
    local function processReceipt(receiptInfo): Enum.ProductPurchaseDecision
    local userId, productId = receiptInfo.PlayerId, receiptInfo.ProductId
    local player = Players:GetPlayerByUserId(userId)
    if not player then
    return Enum.ProductPurchaseDecision.NotProcessedYet
    end
    local handler = receiptHandlers[productId] -- Ürün için handler'ı al
    local success, result = pcall(handler, receiptInfo, player) -- Handler'ı çağırarak satın alma mantığının başarılı olup olmadığını kontrol et
    if not success or not result then
    warn("Makbuzu işleyemedi:", receiptInfo, result)
    return Enum.ProductPurchaseDecision.NotProcessedYet
    end
    return Enum.ProductPurchaseDecision.PurchaseGranted
    end
    local function receiptHandler(receiptInfo: { [string]: any }, player: Player)
    local bundleId, _bundle = Bundles.getBundleByProductId(receiptInfo.ProductId)
    if bundleId then
    -- Bu satın alma bir pakete aittir, Bundles bununla ilgilensin
    local purchaseDecision = Bundles.processReceiptAsync(player, bundleId, receiptInfo)
    return purchaseDecision == Enum.ProductPurchaseDecision.PurchaseGranted
    end
    -- Bu satın alma bir pakete ait değildir,
    -- ... Eğer varsa mevcut tüm mantığınızı burada yönetin
    return false
    end
  3. Paketler özellik paketinin herhangi bir aktif paketi yeniden yönlendirebilmesi için Players.PlayerAdded:Connect(Bundles.OnPlayerAdded) bağlantısını kurun ve süresi dolmamış olan paketin yeniden yönlendirilmesini sağlayın.

    README

    local function onPlayerAdded(player: Player)
    -- Oyuncu katıldığında Pakete bildirir, böylece verilerini yeniden yükleyebilir
    Bundles.onPlayerAdded(player)
    -- Eğer yeni kullanıcılara sunmak istediğiniz başlangıç paketi varsa, burada bunu yönlendirebilirsiniz
    -- ... Paketler, eğer oyuncu bunu zaten satın aldıysa veya süresi dolduysa bu durumu yönetecektir.
    -- Bundles.promptIfValidAsync(player, "StarterBundle")
    -- Bunu burada örnek olması açısından çağırıyorum, bunu istediğiniz zaman veya istediğiniz yerde çağırabilirsiniz.
    onPromptBundleXYZEvent(player)
    end
  4. Paketleri yönlendirin. Bu oyun oynama durumuna bağlıdır; örnekte, yeni katılan oyunculara bir Başlangıç Paketi ile yönlendirme gerçekleşmektedir.

    • Paketler özellik paketi mantığı, her oyuncunun zaten satın aldığı bir teklifi tekrar almadığından emin olur veya teklifin süresi dolduysa yönlendirmeyi sağlar (paket yapılandırmasına göre).

    • Bir oyuncuya bir paketi yönlendirmek istediğiniz her seferde, Bundles.promptIfValidAsync(player, bundleId) çağrısını yapabilirsiniz.

    README

    local function onPromptBundleXYZEvent(player: Player)
    -- Bir oyuncunun paketi ne zaman yönlendirileceğini belirlemek için istediğiniz deneyim olayını bağlayın
    -- ... Bu, oyuncunun paketi yönlendirmek için uygunluk kriterlerinizi karşıladığı zaman olacaktır
    -- ... Örneğin, bir oyuncu katıldığında veya bir oyuncu seviye atladığında bir paketi yönlendirmek isterseniz,
    task.spawn(Bundles.promptIfValidAsync, player, <Some_Bundle_Id>)
    -- ... Eğer birden fazla paket oluşturuyorsanız, yukarıdaki işlev çağrısını sarmak için task.spawn() kullanmak, geri sayımlar arasındaki tutarsızlıkları en aza indirecektir.
    end

Aşağıdaki en iyi uygulama önerilerini, Makbuz Kimliklerinin gereksiz kayıtları konusunda dikkate alın:

  • Paketler özellik paketi, aynı makbuzu iki kez işlememek için Makbuz Kimliklerini kaydetsede, satın alma akışı, satın alma işleyicisi başarıyla tamamlandıktan sonra başarısız olursa, sizin de tablolarınızda Makbuz Kimliklerini kaydetmiş olmanız gerekir.

  • Paketler özellik paketi, satın almanın herhangi bir aşamasında başarısız olursa Makbuz Kimliği kaydetmeyecektir, dolayısıyla işlem makbuzunu işlemeden önce tablolarınızda Makbuz Kimliğini kaydettiğinizden emin olmalısınız.

  • Bu gereknizlik, tüm satın alma mantığının uygun şekilde işlenmesini sağlamak ve veri mağazanız ile Paketler özellik paketinin veri mağazasının nihai tutarlılığa ulaşmasına yardımcı olur; veri mağazanız doğru kaynaktır.

Sabitleri yapılandır

Çekirdek özellik paketi için sabitler iki yerde bulunmaktadır:

  • Paylaşılan sabitler ReplicatedStorage.FeaturePackagesCore.Configs.SharedConstants içinde yer alır.

  • Paket özel sabitleri, bu durumda Paketler özellik paketi ReplicatedStorage.Bundles.Configs.Constants içinde yer alır.

Deneyiminizin tasarım gereksinimlerini karşılamak için ayarlamak isteyebileceğiniz ana unsurlar:

  • Ses varlık kimlikleri
  • Satın alma etkisi süresi ve parçacık renkleri
  • Bilgi ekranı çökebilirliğini

Ayrıca, çeviri için dizilmiş dizeleri tek bir konumda bulabilirsiniz: ReplicatedStorage.FeaturePackagesCore.Configs.TranslationStrings.

UI bileşenlerini özelleştir

Paket nesnelerinin renklerini, fontunu ve saydamlığını değiştirerek, paket yönlendirmelerinizin görsel sunumunu ayarlayabilirsiniz. Ancak, herhangi bir nesneyi hiyerarşik olarak hareket ettirirseniz kodun onları bulması mümkün olmayacaktır; bu nedenle kodunuzda yabancı değişiklik yapmanız gerekir.

Bir yönlendirme, iki üst düzey bileşenden oluşur:

  • PromptItem – Bir paketteki her bir ürün için tekrarlanan bireysel bileşen (ürün resmi, altyazı, isim, fiyat).
  • Prompt – Yönlendirme penceresinin kendisi.

Bilgi ekranı da iki bileşenden oluşur:

  • HudItem – Bilgi ekranında her bir menü seçeneğini temsil eden bireysel bileşen.
  • Hud – Programatik olarak HudItems ile doldurulur.

Eğer bilgi ekranını daha fazla kontrol etmek istiyorsanız, ReplicatedStorage.Bundles.Objects.BundlesGui içinde bulunan mevcut HUD arayüzünü kullanmak yerine, istediğiniz tasarım gereksinimlerini karşılayacak şekilde nesneleri yer değiştirebilirsiniz. Sadece ReplicatedStorage.Bundles.Client.UIController betiğindeki istemci betiği davranışlarını güncellemeyi unutmayın.

API referansı

Türler

RelativeTime

RelativeTime paketi bir oyuncuya sunulduğunda, zaman süresi dolana kadar kullanılabilir kalır. Bu tür, oyuncunun bilgi ekranında görüntülenir ve paket süresi dolana kadar veya oyuncu onu satın alana kadar gelecekteki oturumlarda otomatik olarak yönlendirilir.

Bu paket türüne yaygın bir örnek, tüm yeni oyunculara 24 saat boyunca viewable olan tek kullanımlık bir başlangıç paketi sunmaktır.

İsimTürAçıklama
includeOfflineTimebool(İsteğe Bağlı) Belirtilmezse, yalnızca deneyimde geçirilen süre kalan teklif süresine sayılacaktır.
singleUsebool(İsteğe Bağlı) Belirtilmezse, satın alma işlemi satın alındıktan sonra veya süresi dolduktan sonra tekrar etkinleştirilebilir.

Belirtilirse, ilk kez satın alındıktan veya süresi dolduktan sonra artık bir daha yönlendirilmez, hatta Bundles.promptIfValidAsync ile bundleId ile çağırırsanız bile yönlendirilmez.

FixedTime

FixedTime paketi bir oyuncuya sunulduğunda, belirlenen evrensel koordinat zamanının (UTC) sonuna kadar kullanılabilir kalır. Bu tür, oyuncunun bilgi ekranında görüntülenir ve paket süresi dolana kadar veya oyuncu onu satın alana kadar gelecekteki oturumlarda otomatik olarak yönlendirilir.

Bu paket türüne yaygın bir örnek, yalnızca bir ay için geçerli olan bir tatil teklifidir.

OneTime

OneTime paketi, bir oyuncuya sunulduğu an itibarıyla yalnızca o anda geçerlidir. Oyuncunun bilgi ekranında görüntülenmez ve bir oyuncu yönlendirmeyi kapattıktan sonra tekrar açılmaz, yalnızca sunucu tarafından tekrar yönlendirilirse açılabilir.

Bu paket türüne yaygın bir örnek, bir oyuncunun deneyim para birimi bittiğinde, hemen daha fazla satın alması için sunulan bir tekliftir.

©2026 Roblox Corporation. Roblox, the Roblox logo and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.