Mobile Game Crafting System Development
Crafting system—mechanic where player combines resources or items for new item. From simple "3 wood + 2 iron = sword" to multi-level recipe trees with probability outcomes and time mechanics. Implementation complexity determined not by UI but data architecture: recipes, inventory, craft state, server validation.
Recipe Data Architecture
Store recipes as data, not logic in code. This allows adding new recipes without app update via Remote Config or Addressables:
[Serializable]
public class CraftingRecipe
{
public string recipeId;
public string resultItemId;
public int resultQuantity;
public List<Ingredient> ingredients;
public float craftingTime; // seconds, 0 = instant
public float successRate; // 0.0-1.0, 1.0 = always
public string requiredStation; // "forge", "alchemy_table", null = everywhere
public int requiredLevel;
}
[Serializable]
public class Ingredient
{
public string itemId;
public int quantity;
public bool consumed; // false = tool, not consumed
}
Recipe list loads on startup from ScriptableObject or Addressables.LoadAssetAsync<CraftingDatabase>. For balance tuning without update—Remote Config stores JSON with overrides patching defaults.
CraftingManager: Core Logic
public class CraftingManager : MonoBehaviour
{
public static CraftingManager Instance { get; private set; }
private CraftingDatabase _database;
private InventoryManager _inventory;
public CraftingResult TryCraft(string recipeId, string stationId = null)
{
var recipe = _database.GetRecipe(recipeId);
if (recipe == null) return CraftingResult.InvalidRecipe;
// Check station
if (!string.IsNullOrEmpty(recipe.requiredStation) && recipe.requiredStation != stationId)
return CraftingResult.WrongStation;
// Check level
if (PlayerData.Level < recipe.requiredLevel)
return CraftingResult.LevelTooLow;
// Check ingredients
foreach (var ingredient in recipe.ingredients)
{
if (_inventory.GetCount(ingredient.itemId) < ingredient.quantity)
return CraftingResult.MissingIngredients;
}
// Success probability
bool success = Random.value <= recipe.successRate;
// Consume only consumed ingredients
foreach (var ingredient in recipe.ingredients.Where(i => i.consumed))
_inventory.Remove(ingredient.itemId, ingredient.quantity);
if (success)
_inventory.Add(recipe.resultItemId, recipe.resultQuantity);
// Analytics
GameAnalytics.NewDesignEvent($"Crafting:Result:{recipeId}", success ? 1 : 0);
return success ? CraftingResult.Success : CraftingResult.Failed;
}
}
Crafting with Timer
For "start craft, return in an hour" mechanic:
public class CraftingSlot
{
public string recipeId;
public DateTime completionTime;
public bool isComplete => DateTime.UtcNow >= completionTime;
}
public void StartCrafting(string recipeId, int slotIndex)
{
var recipe = _database.GetRecipe(recipeId);
_craftingSlots[slotIndex] = new CraftingSlot
{
recipeId = recipeId,
completionTime = DateTime.UtcNow.AddSeconds(recipe.craftingTime)
};
// Save in PlayerPrefs or Cloud Save
SaveCraftingState();
// Schedule local notification
NotificationManager.ScheduleLocal(
$"Crafting complete: {recipe.resultItemId}",
recipe.craftingTime
);
}
Slot state must persist—if player closes app, timer continues. For offline progress use DateTime.UtcNow on next launch: if completionTime < DateTime.UtcNow—craft complete.
Server Validation
For monetized games crafting can't fully trust client. Classic pattern via PlayFab Cloud Script:
// PlayFab Cloud Script
handlers.CraftItem = function(args) {
var recipeId = args.recipeId;
var recipe = getRecipeFromCatalog(recipeId);
// Check inventory on server
var inventory = server.GetUserInventory({ PlayFabId: currentPlayerId });
for (var ingredient of recipe.ingredients) {
var count = countItem(inventory, ingredient.itemId);
if (count < ingredient.quantity) {
return { success: false, error: "insufficient_items" };
}
}
// Consume and grant on server
for (var ingredient of recipe.ingredients.filter(i => i.consumed)) {
server.RevokeInventoryItems({ ... });
}
server.GrantItemsToUser({ itemIds: [recipe.resultItemId], ... });
return { success: true, resultItemId: recipe.resultItemId };
};
What's Included
- Recipe data schema and inventory design
-
CraftingManagerimplementation with checks and probabilities - Crafting with timers and offline progression
- Local push notifications on craft completion
- Server validation via PlayFab / GameSparks (if needed)
- UI: recipe book, craft slots, progress bar
- Analytics events for recipe popularity balancing
Timeline
Basic instant crafting: 3–5 days. Full system with timers, slots, server validation, and UI: 1.5–3 weeks. Cost calculated individually.







