목차
Why a Complete Store System Matters
A robust in-game store is essential for monetization, progression systems, and player engagement. Creating a store system that supports real-world monetization, multiple currencies, dynamic pricing, user authentication, inventory integration, and more is no small feat. This guide takes you through building a comprehensive, reusable store system in Unity.
This system includes:
- Dynamic loading of store data.
- Multiple payment options (in-game and real-world currency).
- Discount and promotion systems.
- Purchase validation and inventory integration.
- Modular design for easy adaptation across projects.
What You’ll Learn
By following this guide, you will create a store system that can:
- Fetch product details dynamically.
- Support multiple in-game currencies and real-money purchases.
- Manage player inventory and validate purchases.
- Implement time-limited offers and discounts.
- Provide modular, reusable components for any Unity project.
Comprehensive Code Implementation
Below is a detailed implementation of a Unity store system.
Step 1: Define Core Data Structures
We’ll use ScriptableObject
for predefined store items and external data for dynamic updates.
using System;
using UnityEngine;
[Serializable]
public class StoreItem
{
public string ItemID; // Unique identifier
public string Name;
public string Description;
public int Price;
public string CurrencyType; // "Coins", "Gems", or "USD"
public bool IsLimitedTimeOffer;
public DateTime OfferExpiryDate;
public Sprite Icon;
}
Step 2: Create a ScriptableObject for Store Configuration
[CreateAssetMenu(fileName = "StoreData", menuName = "Store/StoreData")]
public class StoreData : ScriptableObject
{
public StoreItem[] Items;
}
Step 3: Store Manager with Dynamic Data Loading
This class manages the store’s lifecycle, fetching data, updating UI, and handling purchases.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class StoreManager : MonoBehaviour
{
public StoreData LocalStoreData; // For offline fallback
public Transform StoreUIParent;
public GameObject StoreItemPrefab;
public string StoreDataURL = "https://example.com/storedata.json"; // Replace with your server URL
private List<GameObject> activeItems = new List<GameObject>();
void Start()
{
LoadStore();
}
public void LoadStore()
{
StartCoroutine(FetchStoreData());
}
private IEnumerator FetchStoreData()
{
UnityWebRequest request = UnityWebRequest.Get(StoreDataURL);
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
var fetchedItems = JsonUtility.FromJson<StoreItem[]>(request.downloadHandler.text);
PopulateStore(fetchedItems);
}
else
{
Debug.LogError("Failed to fetch store data. Loading local data.");
PopulateStore(LocalStoreData.Items);
}
}
private void PopulateStore(StoreItem[] items)
{
foreach (Transform child in StoreUIParent) Destroy(child.gameObject);
activeItems.Clear();
foreach (var item in items)
{
GameObject itemUI = Instantiate(StoreItemPrefab, StoreUIParent);
StoreItemUI uiComponent = itemUI.GetComponent<StoreItemUI>();
uiComponent.Setup(item);
activeItems.Add(itemUI);
}
}
}
Step 4: UI for Store Items
using UnityEngine;
using UnityEngine.UI;
public class StoreItemUI : MonoBehaviour
{
public Text NameText;
public Text PriceText;
public Image IconImage;
public Button PurchaseButton;
private StoreItem currentItem;
public void Setup(StoreItem item)
{
currentItem = item;
NameText.text = item.Name;
PriceText.text = $"{item.Price} {item.CurrencyType}";
IconImage.sprite = item.Icon;
if (item.IsLimitedTimeOffer && item.OfferExpiryDate < System.DateTime.Now)
{
PurchaseButton.interactable = false;
PriceText.text = "Expired";
}
else
{
PurchaseButton.interactable = true;
}
}
public void OnPurchaseButtonClicked()
{
Debug.Log($"Attempting to purchase: {currentItem.Name}");
// Trigger purchase logic
StorePurchaseHandler.Instance.PurchaseItem(currentItem);
}
}
Step 5: Handle Purchases
This singleton handles purchase validations and inventory updates.
using UnityEngine;
public class StorePurchaseHandler : MonoBehaviour
{
public static StorePurchaseHandler Instance;
private void Awake()
{
if (Instance == null) Instance = this;
else Destroy(gameObject);
}
public void PurchaseItem(StoreItem item)
{
if (item.CurrencyType == "Coins" && PlayerData.Coins >= item.Price)
{
PlayerData.Coins -= item.Price;
AddToInventory(item);
Debug.Log($"{item.Name} purchased successfully!");
}
else if (item.CurrencyType == "Gems" && PlayerData.Gems >= item.Price)
{
PlayerData.Gems -= item.Price;
AddToInventory(item);
Debug.Log($"{item.Name} purchased successfully!");
}
else
{
Debug.LogError("Insufficient currency!");
}
}
private void AddToInventory(StoreItem item)
{
PlayerData.Inventory.Add(item);
}
}
Step 6: Player Data Structure
using System.Collections.Generic;
public static class PlayerData
{
public static int Coins = 1000;
public static int Gems = 50;
public static List<StoreItem> Inventory = new List<StoreItem>();
}
Step 7: Implement Discounts and Promotions
Add a utility class to manage discounts dynamically.
using UnityEngine;
public class PromotionManager
{
public static int GetDiscountedPrice(StoreItem item)
{
if (item.IsLimitedTimeOffer && item.OfferExpiryDate > System.DateTime.Now)
{
return Mathf.RoundToInt(item.Price * 0.8f); // 20% discount
}
return item.Price;
}
}
Update the PriceText
in StoreItemUI
to reflect discounted prices.
Features of This System
- Dynamic Data Fetching: Store items update dynamically from the server.
- Multiple Currencies: Supports coins, gems, and more.
- Discounts & Promotions: Easily integrate limited-time offers.
- Purchase Validation: Ensures fair transactions and inventory updates.
- Reusability: Modular and scalable for various projects.
Closing Thoughts
A modular and feature-rich store system is a must-have for modern game developers. The provided implementation ensures you can integrate a flexible and scalable system into any Unity project while maintaining player satisfaction and engagement.
Feel free to enhance it with payment gateway integration (e.g., Google Play or Apple Store) for real-money transactions!